diff --git a/blockheader.go b/blockheader.go index d9ed680a..519305b9 100644 --- a/blockheader.go +++ b/blockheader.go @@ -11,7 +11,7 @@ import ( ) // BlockVersion is the current latest supported block version. -const BlockVersion uint32 = 2 +const BlockVersion = 2 // Version 4 bytes + Timestamp 4 bytes + Bits 4 bytes + Nonce 4 bytes + // PrevBlock and MerkleRoot hashes. @@ -21,7 +21,7 @@ const MaxBlockHeaderPayload = 16 + (HashSize * 2) // block (MsgBlock) and headers (MsgHeaders) messages. type BlockHeader struct { // Version of the block. This is not the same as the protocol version. - Version uint32 + Version int32 // Hash of the previous block in the block chain. PrevBlock ShaHash diff --git a/internal_test.go b/internal_test.go index 14437201..6f332712 100644 --- a/internal_test.go +++ b/internal_test.go @@ -141,36 +141,36 @@ func TstReadMessageHeader(r io.Reader) (int, *messageHeader, error) { // TstReadOutPoint makes the internal readOutPoint function available to the // test package. -func TstReadOutPoint(r io.Reader, pver uint32, version uint32, op *OutPoint) error { +func TstReadOutPoint(r io.Reader, pver uint32, version int32, op *OutPoint) error { return readOutPoint(r, pver, version, op) } // TstWriteOutPoint makes the internal writeOutPoint function available to the // test package. -func TstWriteOutPoint(w io.Writer, pver uint32, version uint32, op *OutPoint) error { +func TstWriteOutPoint(w io.Writer, pver uint32, version int32, op *OutPoint) error { return writeOutPoint(w, pver, version, op) } // TstReadTxOut makes the internal readTxOut function available to the test // package. -func TstReadTxOut(r io.Reader, pver uint32, version uint32, to *TxOut) error { +func TstReadTxOut(r io.Reader, pver uint32, version int32, to *TxOut) error { return readTxOut(r, pver, version, to) } // TstWriteTxOut makes the internal writeTxOut function available to the test // package. -func TstWriteTxOut(w io.Writer, pver uint32, version uint32, to *TxOut) error { +func TstWriteTxOut(w io.Writer, pver uint32, version int32, to *TxOut) error { return writeTxOut(w, pver, version, to) } // TstReadTxIn makes the internal readTxIn function available to the test // package. -func TstReadTxIn(r io.Reader, pver uint32, version uint32, ti *TxIn) error { +func TstReadTxIn(r io.Reader, pver uint32, version int32, ti *TxIn) error { return readTxIn(r, pver, version, ti) } // TstWriteTxIn makes the internal writeTxIn function available to the test // package. -func TstWriteTxIn(w io.Writer, pver uint32, version uint32, ti *TxIn) error { +func TstWriteTxIn(w io.Writer, pver uint32, version int32, ti *TxIn) error { return writeTxIn(w, pver, version, ti) } diff --git a/msgblock.go b/msgblock.go index d03dc539..60f46eb1 100644 --- a/msgblock.go +++ b/msgblock.go @@ -194,6 +194,20 @@ func (msg *MsgBlock) Serialize(w io.Writer) error { return msg.BtcEncode(w, 0) } +// SerializeSize returns the number of bytes it would take to serialize the +// the block. +func (msg *MsgBlock) SerializeSize() int { + // Block header bytes + Serialized varint size for the number of + // transactions. + n := blockHeaderLen + VarIntSerializeSize(uint64(len(msg.Transactions))) + + for _, tx := range msg.Transactions { + n += tx.SerializeSize() + } + + return n +} + // Command returns the protocol command string for the message. This is part // of the Message interface implementation. func (msg *MsgBlock) Command() string { diff --git a/msgblock_test.go b/msgblock_test.go index a2520cfa..d8b2280a 100644 --- a/msgblock_test.go +++ b/msgblock_test.go @@ -449,6 +449,34 @@ func TestBlockOverflowErrors(t *testing.T) { } } +// TestBlockSerializeSize performs tests to ensure the serialize size for +// various blocks is accurate. +func TestBlockSerializeSize(t *testing.T) { + // Block with no transactions. + noTxBlock := btcwire.NewMsgBlock(&blockOne.Header) + + tests := []struct { + in *btcwire.MsgBlock // Block to encode + size int // Expected serialized size + }{ + // Block with no transactions. + {noTxBlock, 81}, + + // First block in the mainnet block chain. + {&blockOne, len(blockOneBytes)}, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + serializedSize := test.in.SerializeSize() + if serializedSize != test.size { + t.Errorf("MsgBlock.SerializeSize: #%d got: %d, want: "+ + "%d", i, serializedSize, test.size) + continue + } + } +} + var blockOne = btcwire.MsgBlock{ Header: btcwire.BlockHeader{ Version: 1, diff --git a/msgtx.go b/msgtx.go index 0d6714e9..df2426c7 100644 --- a/msgtx.go +++ b/msgtx.go @@ -133,7 +133,7 @@ func NewTxOut(value int64, pkScript []byte) *TxOut { // Use the AddTxIn and AddTxOut functions to build up the list of transaction // inputs and outputs. type MsgTx struct { - Version uint32 + Version int32 TxIn []*TxIn TxOut []*TxOut LockTime uint32 @@ -240,7 +240,7 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32) error { if err != nil { return err } - msg.Version = binary.LittleEndian.Uint32(buf[:]) + msg.Version = int32(binary.LittleEndian.Uint32(buf[:])) count, err := readVarInt(r, pver) if err != nil { @@ -324,7 +324,7 @@ func (msg *MsgTx) Deserialize(r io.Reader) error { // database, as opposed to encoding transactions for the wire. func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32) error { var buf [4]byte - binary.LittleEndian.PutUint32(buf[:], msg.Version) + binary.LittleEndian.PutUint32(buf[:], uint32(msg.Version)) _, err := w.Write(buf[:]) if err != nil { return err @@ -428,7 +428,7 @@ func NewMsgTx() *MsgTx { } // readOutPoint reads the next sequence of bytes from r as an OutPoint. -func readOutPoint(r io.Reader, pver uint32, version uint32, op *OutPoint) error { +func readOutPoint(r io.Reader, pver uint32, version int32, op *OutPoint) error { _, err := io.ReadFull(r, op.Hash[:]) if err != nil { return err @@ -445,7 +445,7 @@ func readOutPoint(r io.Reader, pver uint32, version uint32, op *OutPoint) error // writeOutPoint encodes op to the bitcoin protocol encoding for an OutPoint // to w. -func writeOutPoint(w io.Writer, pver uint32, version uint32, op *OutPoint) error { +func writeOutPoint(w io.Writer, pver uint32, version int32, op *OutPoint) error { _, err := w.Write(op.Hash[:]) if err != nil { return err @@ -462,7 +462,7 @@ func writeOutPoint(w io.Writer, pver uint32, version uint32, op *OutPoint) error // readTxIn reads the next sequence of bytes from r as a transaction input // (TxIn). -func readTxIn(r io.Reader, pver uint32, version uint32, ti *TxIn) error { +func readTxIn(r io.Reader, pver uint32, version int32, ti *TxIn) error { var op OutPoint err := readOutPoint(r, pver, version, &op) if err != nil { @@ -488,7 +488,7 @@ func readTxIn(r io.Reader, pver uint32, version uint32, ti *TxIn) error { // writeTxIn encodes ti to the bitcoin protocol encoding for a transaction // input (TxIn) to w. -func writeTxIn(w io.Writer, pver uint32, version uint32, ti *TxIn) error { +func writeTxIn(w io.Writer, pver uint32, version int32, ti *TxIn) error { err := writeOutPoint(w, pver, version, &ti.PreviousOutpoint) if err != nil { return err @@ -511,7 +511,7 @@ func writeTxIn(w io.Writer, pver uint32, version uint32, ti *TxIn) error { // readTxOut reads the next sequence of bytes from r as a transaction output // (TxOut). -func readTxOut(r io.Reader, pver uint32, version uint32, to *TxOut) error { +func readTxOut(r io.Reader, pver uint32, version int32, to *TxOut) error { var buf [8]byte _, err := io.ReadFull(r, buf[:]) if err != nil { @@ -530,7 +530,7 @@ func readTxOut(r io.Reader, pver uint32, version uint32, to *TxOut) error { // writeTxOut encodes to into the bitcoin protocol encoding for a transaction // output (TxOut) to w. -func writeTxOut(w io.Writer, pver uint32, version uint32, to *TxOut) error { +func writeTxOut(w io.Writer, pver uint32, version int32, to *TxOut) error { var buf [8]byte binary.LittleEndian.PutUint64(buf[:], uint64(to.Value)) _, err := w.Write(buf[:])