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 }
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 }
// 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 }
// 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() }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }