// FactoidEncode encodes the receiver to w using the protocol encoding. // This is part of the Message interface implementation. // See Serialize for encoding transactions to be stored to disk, such as in a // database, as opposed to encoding transactions for the wire. func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32) error { var buf [1]byte buf[0] = msg.Version _, err := w.Write(buf[:]) if err != nil { return err } var buf8 [8]byte if !factoid.FactoidTx_LocktimeCheck(msg.LockTime) { return errors.New("fTx encode locktime check") } binary.BigEndian.PutUint64(buf8[:], uint64(msg.LockTime)) _, err = w.Write(buf8[3:8]) // LockTime is 5 bytes if err != nil { return err } txoutcount := uint64(len(msg.TxOut)) err = writeVarInt(w, pver, txoutcount) if err != nil { return err } for _, to := range msg.TxOut { err = writeTxOut(w, pver, to) if err != nil { return err } } ecoutcount := uint64(len(msg.ECOut)) err = writeVarInt(w, pver, ecoutcount) if err != nil { return err } for _, eco := range msg.ECOut { err = writeECOut(w, pver, eco) if err != nil { return err } } incount := uint64(len(msg.TxIn)) err = writeVarInt(w, pver, incount) if err != nil { return err } for _, ti := range msg.TxIn { err = writeTxIn(w, pver, ti) if err != nil { return err } } /* TODO: RE-ENABLE rcdcount := uint64(len(msg.RCDreveal)) err = writeVarInt(w, pver, rcdcount) if err != nil { return err } for _, rcd := range msg.RCDreveal { err = writeRCD(w, pver, rcd) if err != nil { return err } } */ /* TODO: RE-ENABLE for _, sig := range msg.TxSig { err = writeSig(w, pver, sig) if err != nil { return err } } */ return nil }
// BtcDecode decodes r using the protocol encoding into the receiver. // This is part of the Message interface implementation. // See Deserialize for decoding transactions stored to disk, such as in a // database, as opposed to decoding transactions from the wire. func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32) error { // util.Trace() /* if s, ok := r.(io.Seeker); ok { } nowseek, _ := s.Seek(0, os.SEEK_CUR) fmt.Println("nowseek= ", nowseek) { me := bufio.NewReader(r) peekbuf, _ := me.Peek(1000) fmt.Println("bufio peek= ", spew.Sdump(peekbuf)) } */ // s.Seek(nowseek, os.SEEK_SET) var buf [1]byte _, err := io.ReadFull(r, buf[:]) if err != nil { return err } msg.Version = uint8(buf[0]) // util.Trace(fmt.Sprintf("version=%d\n", msg.Version)) // fmt.Printf("buf= %v (%d)\n", buf, msg.Version) if !factoid.FactoidTx_VersionCheck(msg.Version) { return errors.New("fTx version check") } var buf5 [5]byte _, err = io.ReadFull(r, buf5[:]) if err != nil { return err } fmt.Printf("buf5= %v\n", buf5) full8slice := []byte{0, 0, 0} full8slice = append(full8slice, buf5[:]...) fmt.Printf("full8slice= %v\n", full8slice) msg.LockTime = int64(binary.BigEndian.Uint64(full8slice)) if !factoid.FactoidTx_LocktimeCheck(msg.LockTime) { //util.Trace("LOCKTIME error: MsgTx= " + spew.Sdump(*msg)) return errors.New("fTx decode locktime check") } outcount, err := readVarInt(r, pver) if err != nil { return err } //util.Trace(fmt.Sprintf("outcount=%d\n", outcount)) // Prevent more input transactions than could possibly fit into a // message. It would be possible to cause memory exhaustion and panics // without a sane upper bound on this count. if outcount > uint64(inNout_cap) { str := fmt.Sprintf("too many input transactions to fit into "+ "max message size [count %d, max %d]", outcount, inNout_cap) return messageError("MsgTx.BtcDecode maxtxout", str) } msg.TxOut = make([]*TxOut, outcount) for i := uint64(0); i < outcount; i++ { to := TxOut{} err = readTxOut(r, pver, &to) if err != nil { return err } msg.TxOut[i] = &to } // util.Trace() eccount, err := readVarInt(r, pver) if err != nil { return err } // util.Trace(fmt.Sprintf("eccount=%d\n", eccount)) // Prevent more input transactions than could possibly fit into a // message. It would be possible to cause memory exhaustion and panics // without a sane upper bound on this count. if eccount > uint64(inNout_cap) { str := fmt.Sprintf("too many input transactions to fit into "+ "max message size [count %d, max %d]", eccount, inNout_cap) return messageError("MsgTx.BtcDecode maxecout", str) } // util.Trace() msg.ECOut = make([]*TxEntryCreditOut, eccount) for i := uint64(0); i < eccount; i++ { eco := TxEntryCreditOut{} err = readECOut(r, pver, &eco) if err != nil { return err } msg.ECOut[i] = &eco } // util.Trace() incount, err := readVarInt(r, pver) //util.Trace(fmt.Sprintf("incount=%d\n", incount)) msg.TxIn = make([]*TxIn, incount) for i := uint64(0); i < incount; i++ { ti := TxIn{} err = readTxIn(r, pver, &ti) if err != nil { return err } msg.TxIn[i] = &ti } // util.Trace() /* LOOKS LIKE ERROR HERE _, err = io.ReadFull(r, buf[:]) if err != nil { return err } // util.Trace() */ /* TODO: RE-ENABLE rcdcount, err := readVarInt(r, pver) if rcdcount > uint64(inNout_cap) { str := fmt.Sprintf("too many RCDs to fit into "+ "max message size [count %d, max %d]", rcdcount, inNout_cap) return messageError("MsgTx.BtcDecode max rcd", str) } // util.Trace() msg.RCDreveal = make([]*RCDreveal, rcdcount) for i := uint64(0); i < rcdcount; i++ { rcd := RCDreveal{} err = readRCD(r, pver, &rcd) if err != nil { return err } msg.RCDreveal[i] = &rcd } */ /* TODO: RE - ENABLE msg.TxSig = make([]*TxSig, incount) for i := uint64(0); i < incount; i++ { sig := TxSig{} err = readSig(r, pver, &sig) if err != nil { return err } msg.TxSig[i] = &sig } //util.Trace() // ---------------------------------------------- if !factoid_CountCheck(msg) { errors.New("Factoid check 1") } */ if !disableSpew { fmt.Println("MsgTx= ", spew.Sdump(*msg)) } return nil }