Пример #1
0
func (m *Message_alert) Decode(payload []byte) error {
	buf := bytes.NewBuffer(payload)
	var lastError error
	var contentLen, signatureLen klib.VarUint

	lastError = readData(buf, &contentLen, lastError)
	if lastError != nil {
		return lastError
	} else if contentLen > klib.VarUint(kaiju.MaxAlertSize) {
		return errors.New("alert content is too long")
	}
	m.Content = make([]byte, contentLen)
	lastError = readData(buf, m.Content, lastError)
	if lastError != nil {
		return lastError
	}

	lastError = readData(buf, &signatureLen, lastError)
	if lastError != nil {
		return lastError
	} else if contentLen > klib.VarUint(kaiju.MaxAlertSingnatureSize) {
		return errors.New("alert singature is too long")
	}
	sing := make([]byte, signatureLen)
	lastError = readData(buf, sing, lastError)
	if lastError != nil {
		return lastError
	}

	// Now check the singnature
	// TODO
	return nil
}
Пример #2
0
func (tx *Tx) Deserialize(r io.Reader) error {
	lastError := readData(r, &tx.Version, nil)
	var listSize klib.VarUint
	lastError = readData(r, &listSize, lastError)
	if lastError != nil {
		return lastError
	} else if listSize > klib.VarUint(kaiju.MaxInvListSize) {
		return errors.New("TxIn list too long")
	}
	tx.TxIns = make([]*catma.TxIn, listSize)
	txins := tx.TxIns
	for i := uint64(0); i < uint64(listSize); i++ {
		txins[i] = new(catma.TxIn)
		lastError = readData(r, &txins[i].PreviousOutput, lastError)
		lastError = readData(r, (*klib.VarString)(&txins[i].SigScript), lastError)
		lastError = readData(r, &txins[i].Sequence, lastError)
	}
	lastError = readData(r, &listSize, lastError)
	if lastError != nil {
		return lastError
	} else if listSize > klib.VarUint(kaiju.MaxInvListSize) {
		return errors.New("TxOut list too long")
	}
	tx.TxOuts = make([]*catma.TxOut, listSize)
	txouts := tx.TxOuts
	for i := uint64(0); i < uint64(listSize); i++ {
		txouts[i] = new(catma.TxOut)
		lastError = readData(r, &txouts[i].Value, lastError)
		lastError = readData(r, (*klib.VarString)(&txouts[i].PKScript), lastError)
	}
	lastError = readData(r, &tx.LockTime, lastError)
	return lastError
}
Пример #3
0
// Returns the data size of serialized Tx
func (t *Tx) ByteSize() int {
	opLen := 32 /*OutPoint.Hash*/ + 4 /*OutPoint.Index*/
	totalLen := 4                     // Version
	totalLen += klib.VarUint(len(t.TxIns)).ByteSize()
	for _, txin := range t.TxIns {
		totalLen += opLen
		totalLen += klib.VarString(txin.SigScript).ByteSize()
		totalLen += 4 // Sequence
	}
	totalLen += klib.VarUint(len(t.TxOuts)).ByteSize()
	for _, txout := range t.TxOuts {
		totalLen += 8 // Value
		totalLen += klib.VarString(txout.PKScript).ByteSize()
	}
	totalLen += 4 // LockTime
	return totalLen
}
Пример #4
0
// Returns the serialized byte of the Tx
func (t *Tx) Bytes() []byte {
	p := new(bytes.Buffer)
	binary.Write(p, binary.LittleEndian, t.Version)

	p.Write(klib.VarUint(len(t.TxIns)).Bytes())
	for _, txin := range t.TxIns {
		binary.Write(p, binary.LittleEndian, txin.PreviousOutput)
		p.Write(klib.VarString(txin.SigScript).Bytes())
		binary.Write(p, binary.LittleEndian, txin.Sequence)
	}
	p.Write(klib.VarUint(len(t.TxOuts)).Bytes())
	for _, txout := range t.TxOuts {
		binary.Write(p, binary.LittleEndian, txout.Value)
		p.Write(klib.VarString(txout.PKScript).Bytes())
	}
	binary.Write(p, binary.LittleEndian, t.LockTime)
	return p.Bytes()
}
Пример #5
0
func (m *Message_headers) Encode() ([]byte, error) {
	buf := new(bytes.Buffer)
	var err error

	listSize := klib.VarUint(len(m.Headers))
	err = writeData(buf, &listSize, err)
	for _, h := range m.Headers {
		err = writeData(buf, (*blockHeader)(h), err)
	}
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
Пример #6
0
func (m *Message_inv) Encode() ([]byte, error) {
	buf := new(bytes.Buffer)
	var err error

	listSize := klib.VarUint(len(m.Inventory))
	err = writeData(buf, &listSize, err)
	for _, e := range m.Inventory {
		err = writeData(buf, e, err)
	}
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
Пример #7
0
func (m *Message_block) Encode() ([]byte, error) {
	buf := new(bytes.Buffer)
	var err error

	err = writeData(buf, m.Header, err)
	listSize := klib.VarUint(len(m.Txs))
	err = writeData(buf, &listSize, err)
	for _, t := range m.Txs {
		err = writeData(buf, t, err)
	}
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
Пример #8
0
func (m *Message_getheaders) Encode() ([]byte, error) {
	buf := new(bytes.Buffer)
	var err error

	err = writeData(buf, m.Version, err)
	listSize := klib.VarUint(len(m.BlockLocators))
	err = writeData(buf, &listSize, err)
	for _, l := range m.BlockLocators {
		err = writeData(buf, l, err)
	}
	err = writeData(buf, m.HashStop, err)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
Пример #9
0
func (m *Message_addr) Encode() ([]byte, error) {
	buf := new(bytes.Buffer)
	var err error
	listSize := klib.VarUint(len(m.Addresses))
	err = writeData(buf, &listSize, err)
	if err != nil {
		return nil, err
	}

	for _, addr := range m.Addresses {
		err = writePeerInfo(buf, addr, true, err)
	}
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
Пример #10
0
func (m *Message_headers) Decode(payload []byte) error {
	buf := bytes.NewBuffer(payload)
	var err error
	var listSize klib.VarUint

	err = readData(buf, &listSize, err)
	if err != nil {
		return err
	} else if listSize > klib.VarUint(kaiju.MaxInvListSize) {
		return errors.New("Message_headers list too long")
	}

	bhs := make([]*catma.Header, listSize)
	for i := uint64(0); i < uint64(listSize); i++ {
		bhs[i] = new(catma.Header)
		err = readData(buf, (*blockHeader)(bhs[i]), err)
	}
	m.Headers = bhs
	return err
}
Пример #11
0
func (m *Message_inv) Decode(payload []byte) error {
	buf := bytes.NewBuffer(payload)
	var err error
	var listSize klib.VarUint

	err = readData(buf, &listSize, err)
	if err != nil {
		return err
	} else if listSize > klib.VarUint(kaiju.MaxInvListSize) {
		return errors.New("Message_inv list too long")
	}

	inv := make([]*blockchain.InvElement, listSize)
	for i := uint64(0); i < uint64(listSize); i++ {
		inv[i] = new(blockchain.InvElement)
		err = readData(buf, inv[i], err)
	}
	m.Inventory = inv
	return err
}
Пример #12
0
func (m *Message_block) Decode(payload []byte) error {
	buf := bytes.NewBuffer(payload)
	var err error
	var listSize klib.VarUint

	err = readData(buf, m.Header, err)
	err = readData(buf, &listSize, err)
	if err != nil {
		return err
	} else if listSize > klib.VarUint(kaiju.MaxInvListSize) {
		return errors.New("Message_block list too long")
	}

	txs := make([]*Tx, listSize)
	for i := uint64(0); i < uint64(listSize); i++ {
		txs[i] = new(Tx)
		err = readData(buf, txs[i], err)
	}
	m.Txs = txs
	return err
}
Пример #13
0
func (m *Message_addr) Decode(payload []byte) error {
	buf := bytes.NewBuffer(payload)
	var err error
	var listSize klib.VarUint

	err = readData(buf, &listSize, err)
	if err != nil {
		return err
	}

	if listSize > klib.VarUint(kaiju.MaxAddrListSize) {
		return errors.New(fmt.Sprintf("Message_addr list too long: %v", listSize))
	}

	addresses := make([]*PeerInfo, listSize)
	for i := uint64(0); i < uint64(listSize); i++ {
		addresses[i] = new(PeerInfo)
		err = readPeerInfo(buf, addresses[i], true, err)
	}
	m.Addresses = addresses
	return err
}
Пример #14
0
func (m *Message_getheaders) Decode(payload []byte) error {
	buf := bytes.NewBuffer(payload)
	var err error
	var listSize klib.VarUint

	err = readData(buf, &m.Version, err)
	err = readData(buf, &listSize, err)
	if err != nil {
		return err
	} else if listSize > klib.VarUint(kaiju.MaxInvListSize) {
		return errors.New("Message_getheaders/Message_geblocks list too long")
	}

	inv := make([]*klib.Hash256, listSize)
	for i := uint64(0); i < uint64(listSize); i++ {
		inv[i] = new(klib.Hash256)
		err = readData(buf, inv[i], err)
	}
	m.BlockLocators = inv
	m.HashStop = new(klib.Hash256)
	err = readData(buf, m.HashStop, err)
	return err
}
Пример #15
0
func (t *Tx) HashToSign(subScript []byte, ii int, hashType byte) (*klib.Hash256, error) {
	if ii >= len(t.TxIns) {
		return nil, errors.New("Tx.StringToSign invalid index")
	}
	anyoneCanPay := (hashType & SIGHASH_ANYONECANPAY) != 0
	htype := hashType & numbers.HashTypeMask
	p := new(bytes.Buffer)

	// STEP0: version
	binary.Write(p, binary.LittleEndian, t.Version)
	// STEP1: inputs
	if anyoneCanPay {
		// If SIGHASH_ANYONECANPAY is set, only current input is written,
		// and subScipt is used as SigScript
		p.Write(klib.VarUint(1).Bytes())                                 // inputs count
		binary.Write(p, binary.LittleEndian, t.TxIns[ii].PreviousOutput) // PreviousOutput
		p.Write(((klib.VarString)(subScript)).Bytes())                   // subScript
		binary.Write(p, binary.LittleEndian, t.TxIns[ii].Sequence)       // Sequence
	} else {
		// Else write all the inputs with modifications
		p.Write(klib.VarUint(len(t.TxIns)).Bytes())
		for i, txin := range t.TxIns {
			binary.Write(p, binary.LittleEndian, txin.PreviousOutput)
			if i == ii { // If this is current input, write subScript
				p.Write(((klib.VarString)(subScript)).Bytes())
			} else { // Else write an empty VarString
				p.Write((klib.VarString{}).Bytes())
			}
			sequence := txin.Sequence
			if i != ii && (htype == SIGHASH_NONE || htype == SIGHASH_SINGLE) {
				// If not current input, and of type SIGHASH_NONE || SIGHASH_SINGLE,
				// set sequence to 0
				sequence = 0
			}
			binary.Write(p, binary.LittleEndian, sequence)
		}
	}
	// STEP3: outputs
	switch htype {
	case SIGHASH_NONE:
		p.Write((klib.VarString{}).Bytes())
	case SIGHASH_SINGLE:
		if ii >= len(t.TxOuts) {
			// This is actually allowed due to a Satoshi Bug, right thing to do:
			// panic("Tx.StringToSign invalid index with type SIGHASH_SINGLE")
			return new(klib.Hash256).SetUint64(1), nil
		}
		p.Write(klib.VarUint(ii + 1).Bytes()) // output count
		for i := 0; i < ii; i++ {             // All outputs except the last one are written as blank
			binary.Write(p, binary.LittleEndian, int64(-1)) // value
			p.Write((klib.VarString{}).Bytes())             // script
		}
		txout := t.TxOuts[ii]
		binary.Write(p, binary.LittleEndian, txout.Value)
		p.Write(((klib.VarString)(txout.PKScript)).Bytes())
	default:
		// Another Satoshi Bug: any other hashtype are considered as SIGHASH_ALL
		p.Write(klib.VarUint(len(t.TxOuts)).Bytes())
		for _, txout := range t.TxOuts {
			binary.Write(p, binary.LittleEndian, txout.Value)
			p.Write(((klib.VarString)(txout.PKScript)).Bytes())
		}
	}
	// STEP4: LockTime and HashType
	binary.Write(p, binary.LittleEndian, t.LockTime)
	// Notice hashTypes needs to take 4 bytes
	binary.Write(p, binary.LittleEndian, uint32(hashType))
	return klib.Sha256Sha256(p.Bytes()), nil
}