diff --git a/block.go b/block.go index 5fa860b..254ef64 100644 --- a/block.go +++ b/block.go @@ -25,13 +25,12 @@ func (e OutOfRangeError) Error() string { } // Block defines a bitcoin block that provides easier and more efficient -// manipulation of raw wire protocol blocks. It also memoizes hashes for the -// block and its transactions on their first access so subsequent accesses don't -// have to repeat the relatively expensive hashing operations. +// manipulation of raw blocks. It also memoizes hashes for the block and its +// transactions on their first access so subsequent accesses don't have to +// repeat the relatively expensive hashing operations. type Block struct { msgBlock *btcwire.MsgBlock // Underlying MsgBlock - rawBlock []byte // Raw wire encoded bytes for the block - protocolVersion uint32 // Protocol version used to encode rawBlock + serializedBlock []byte // Serialized bytes for the block blockSha *btcwire.ShaHash // Cached block hash blockHeight int64 // Height in the main block chain txShas []*btcwire.ShaHash // Cached transaction hashes @@ -44,28 +43,26 @@ func (b *Block) MsgBlock() *btcwire.MsgBlock { return b.msgBlock } -// Bytes returns the raw wire protocol encoded bytes for the Block and the -// protocol version used to encode it. This is equivalent to calling BtcEncode -// on the underlying btcwire.MsgBlock, however it caches the result so -// subsequent calls are more efficient. -func (b *Block) Bytes() ([]byte, uint32, error) { - // Return the cached raw block bytes and associated protocol version if - // it has already been generated. - if len(b.rawBlock) != 0 { - return b.rawBlock, b.protocolVersion, nil +// Bytes returns the serialized bytes for the Block. This is equivalent to +// calling Serialize on the underlying btcwire.MsgBlock, however it caches the +// result so subsequent calls are more efficient. +func (b *Block) Bytes() ([]byte, error) { + // Return the cached serialized bytes if it has already been generated. + if len(b.serializedBlock) != 0 { + return b.serializedBlock, nil } - // Encode the MsgBlock into raw block bytes. + // Serialize the MsgBlock. var w bytes.Buffer - err := b.msgBlock.BtcEncode(&w, b.protocolVersion) + err := b.msgBlock.Serialize(&w) if err != nil { - return nil, 0, err + return nil, err } - rawBlock := w.Bytes() + serializedBlock := w.Bytes() - // Cache the encoded bytes and return them. - b.rawBlock = rawBlock - return rawBlock, b.protocolVersion, nil + // Cache the serialized bytes and return them. + b.serializedBlock = serializedBlock + return serializedBlock, nil } // Sha returns the block identifier hash for the Block. This is equivalent to @@ -79,7 +76,7 @@ func (b *Block) Sha() (*btcwire.ShaHash, error) { // Generate the block hash. Ignore the error since BlockSha can't // currently fail. - sha, _ := b.msgBlock.BlockSha(b.protocolVersion) + sha, _ := b.msgBlock.BlockSha() // Cache the block hash and return it. b.blockSha = &sha @@ -112,7 +109,7 @@ func (b *Block) TxSha(txNum int) (*btcwire.ShaHash, error) { // Generate the hash for the transaction. Ignore the error since TxSha // can't currently fail. - sha, _ := b.msgBlock.Transactions[txNum].TxSha(b.protocolVersion) + sha, _ := b.msgBlock.Transactions[txNum].TxSha() // Cache the transaction hash and return it. b.txShas[txNum] = &sha @@ -140,7 +137,7 @@ func (b *Block) TxShas() ([]*btcwire.ShaHash, error) { for i, hash := range b.txShas { if hash == nil { // Ignore the error since TxSha can't currently fail. - sha, _ := b.msgBlock.Transactions[i].TxSha(b.protocolVersion) + sha, _ := b.msgBlock.Transactions[i].TxSha() b.txShas[i] = &sha } } @@ -149,79 +146,69 @@ func (b *Block) TxShas() ([]*btcwire.ShaHash, error) { return b.txShas, nil } -// ProtocolVersion returns the protocol version that was used to create the -// underlying btcwire.MsgBlock. -func (b *Block) ProtocolVersion() uint32 { - return b.protocolVersion -} - // TxLoc returns the offsets and lengths of each transaction in a raw block. // It is used to allow fast indexing into transactions within the raw byte // stream. func (b *Block) TxLoc() ([]btcwire.TxLoc, error) { - rawMsg, pver, err := b.Bytes() + rawMsg, err := b.Bytes() if err != nil { return nil, err } rbuf := bytes.NewBuffer(rawMsg) var mblock btcwire.MsgBlock - txLocs, err := mblock.BtcDecodeTxLoc(rbuf, pver) + txLocs, err := mblock.DeserializeTxLoc(rbuf) if err != nil { return nil, err } return txLocs, err } -// Height returns the saved height of the block in the blockchain. This value +// Height returns the saved height of the block in the block chain. This value // will be BlockHeightUnknown if it hasn't already explicitly been set. func (b *Block) Height() int64 { return b.blockHeight } -// SetHeight sets the height of the block in the blockchain. +// SetHeight sets the height of the block in the block chain. func (b *Block) SetHeight(height int64) { b.blockHeight = height } // NewBlock returns a new instance of a bitcoin block given an underlying -// btcwire.MsgBlock and protocol version. See Block. -func NewBlock(msgBlock *btcwire.MsgBlock, pver uint32) *Block { +// btcwire.MsgBlock. See Block. +func NewBlock(msgBlock *btcwire.MsgBlock) *Block { return &Block{ - msgBlock: msgBlock, - protocolVersion: pver, - blockHeight: BlockHeightUnknown, + msgBlock: msgBlock, + blockHeight: BlockHeightUnknown, } } // NewBlockFromBytes returns a new instance of a bitcoin block given the -// raw wire encoded bytes and protocol version used to encode those bytes. -// See Block. -func NewBlockFromBytes(rawBlock []byte, pver uint32) (*Block, error) { - // Decode the raw block bytes into a MsgBlock. +// serialized bytes. See Block. +func NewBlockFromBytes(serializedBlock []byte) (*Block, error) { + // Deserialize the bytes into a MsgBlock. var msgBlock btcwire.MsgBlock - br := bytes.NewBuffer(rawBlock) - err := msgBlock.BtcDecode(br, pver) + br := bytes.NewBuffer(serializedBlock) + err := msgBlock.Deserialize(br) if err != nil { return nil, err } b := Block{ msgBlock: &msgBlock, - rawBlock: rawBlock, - protocolVersion: pver, + serializedBlock: serializedBlock, blockHeight: BlockHeightUnknown, } return &b, nil } // NewBlockFromBlockAndBytes returns a new instance of a bitcoin block given -// an underlying btcwire.MsgBlock, protocol version and raw Block. See Block. -func NewBlockFromBlockAndBytes(msgBlock *btcwire.MsgBlock, rawBlock []byte, pver uint32) *Block { +// an underlying btcwire.MsgBlock and the serialized bytes for it. See Block. +func NewBlockFromBlockAndBytes(msgBlock *btcwire.MsgBlock, serializedBlock []byte) *Block { return &Block{ msgBlock: msgBlock, - rawBlock: rawBlock, - protocolVersion: pver, + serializedBlock: serializedBlock, blockHeight: BlockHeightUnknown, } } diff --git a/block_test.go b/block_test.go index 1a2da5f..8f39d4b 100644 --- a/block_test.go +++ b/block_test.go @@ -17,14 +17,9 @@ import ( // TestBlock tests the API for Block. func TestBlock(t *testing.T) { - pver := btcwire.ProtocolVersion - b := btcutil.NewBlock(&Block100000, pver) + b := btcutil.NewBlock(&Block100000) // Ensure we get the same data back out. - if gotPver := b.ProtocolVersion(); gotPver != pver { - t.Errorf("ProtocolVersion: wrong protocol version - got %v, want %v", - gotPver, pver) - } if msgBlock := b.MsgBlock(); !reflect.DeepEqual(msgBlock, &Block100000) { t.Errorf("MsgBlock: mismatched MsgBlock - got %v, want %v", spew.Sdump(msgBlock), spew.Sdump(&Block100000)) @@ -89,7 +84,7 @@ func TestBlock(t *testing.T) { } // Create a new block to nuke all cached data. - b = btcutil.NewBlock(&Block100000, pver) + b = btcutil.NewBlock(&Block100000) // Request slice of all transaction shas multiple times to test // generation and caching. @@ -125,34 +120,28 @@ func TestBlock(t *testing.T) { } } - // Encode the test block to bytes. + // Serialize the test block. var block100000Buf bytes.Buffer - err = Block100000.BtcEncode(&block100000Buf, pver) + err = Block100000.Serialize(&block100000Buf) if err != nil { - t.Errorf("BtcEncode: %v", err) + t.Errorf("Serialize: %v", err) } block100000Bytes := block100000Buf.Bytes() - // Request raw bytes multiple times to test generation and caching. + // Request serialized bytes multiple times to test generation and + // caching. for i := 0; i < 2; i++ { - rawBytes, tmpPver, err := b.Bytes() + serializedBytes, err := b.Bytes() if err != nil { t.Errorf("Bytes: %v", err) continue } - if !bytes.Equal(rawBytes, block100000Bytes) { + if !bytes.Equal(serializedBytes, block100000Bytes) { t.Errorf("Bytes #%d wrong bytes - got %v, want %v", i, - spew.Sdump(rawBytes), + spew.Sdump(serializedBytes), spew.Sdump(block100000Bytes)) continue } - if tmpPver != pver { - t.Errorf("Bytes #%d wrong protocol version - "+ - "got %v, want %v", i, spew.Sdump(rawBytes), - spew.Sdump(block100000Bytes)) - continue - - } } // Transaction offsets and length for the transaction in Block100000. @@ -176,39 +165,34 @@ func TestBlock(t *testing.T) { } } -// TestNewBlockFromBytes tests creation of a Block from raw bytes. +// TestNewBlockFromBytes tests creation of a Block from serialized bytes. func TestNewBlockFromBytes(t *testing.T) { - // Encode the test block to bytes. - pver := btcwire.ProtocolVersion + // Serialize the test block. var block100000Buf bytes.Buffer - err := Block100000.BtcEncode(&block100000Buf, pver) + err := Block100000.Serialize(&block100000Buf) if err != nil { - t.Errorf("BtcEncode: %v", err) + t.Errorf("Serialize: %v", err) } block100000Bytes := block100000Buf.Bytes() - // Create a new block from the encoded bytes. - b, err := btcutil.NewBlockFromBytes(block100000Bytes, pver) + // Create a new block from the serialized bytes. + b, err := btcutil.NewBlockFromBytes(block100000Bytes) if err != nil { t.Errorf("NewBlockFromBytes: %v", err) return } // Ensure we get the same data back out. - rawBytes, tmpPver, err := b.Bytes() + serializedBytes, err := b.Bytes() if err != nil { t.Errorf("Bytes: %v", err) return } - if !bytes.Equal(rawBytes, block100000Bytes) { + if !bytes.Equal(serializedBytes, block100000Bytes) { t.Errorf("Bytes: wrong bytes - got %v, want %v", - spew.Sdump(rawBytes), + spew.Sdump(serializedBytes), spew.Sdump(block100000Bytes)) } - if tmpPver != pver { - t.Errorf("Bytes: wrong protocol version - got %v, want %v", - tmpPver, pver) - } // Ensure the generated MsgBlock is correct. if msgBlock := b.MsgBlock(); !reflect.DeepEqual(msgBlock, &Block100000) { @@ -220,34 +204,28 @@ func TestNewBlockFromBytes(t *testing.T) { // TestNewBlockFromBlockAndBytes tests creation of a Block from a MsgBlock and // raw bytes. func TestNewBlockFromBlockAndBytes(t *testing.T) { - // Encode the test block to bytes. - pver := btcwire.ProtocolVersion + // Serialize the test block. var block100000Buf bytes.Buffer - err := Block100000.BtcEncode(&block100000Buf, pver) + err := Block100000.Serialize(&block100000Buf) if err != nil { - t.Errorf("BtcEncode: %v", err) + t.Errorf("Serialize: %v", err) } block100000Bytes := block100000Buf.Bytes() - // Create a new block from the encoded bytes. - b := btcutil.NewBlockFromBlockAndBytes(&Block100000, - block100000Bytes, pver) + // Create a new block from the serialized bytes. + b := btcutil.NewBlockFromBlockAndBytes(&Block100000, block100000Bytes) // Ensure we get the same data back out. - rawBytes, tmpPver, err := b.Bytes() + serializedBytes, err := b.Bytes() if err != nil { t.Errorf("Bytes: %v", err) return } - if !bytes.Equal(rawBytes, block100000Bytes) { + if !bytes.Equal(serializedBytes, block100000Bytes) { t.Errorf("Bytes: wrong bytes - got %v, want %v", - spew.Sdump(rawBytes), + spew.Sdump(serializedBytes), spew.Sdump(block100000Bytes)) } - if tmpPver != pver { - t.Errorf("Bytes: wrong protocol version - got %v, want %v", - tmpPver, pver) - } if msgBlock := b.MsgBlock(); !reflect.DeepEqual(msgBlock, &Block100000) { t.Errorf("MsgBlock: mismatched MsgBlock - got %v, want %v", spew.Sdump(msgBlock), spew.Sdump(&Block100000)) @@ -264,17 +242,16 @@ func TestBlockErrors(t *testing.T) { testErr.Error(), wantErr) } - // Encode the test block to bytes. - pver := btcwire.ProtocolVersion + // Serialize the test block. var block100000Buf bytes.Buffer - err := Block100000.BtcEncode(&block100000Buf, pver) + err := Block100000.Serialize(&block100000Buf) if err != nil { - t.Errorf("BtcEncode: %v", err) + t.Errorf("Serialize: %v", err) } block100000Bytes := block100000Buf.Bytes() - // Create a new block from the encoded bytes. - b, err := btcutil.NewBlockFromBytes(block100000Bytes, pver) + // Create a new block from the serialized bytes. + b, err := btcutil.NewBlockFromBytes(block100000Bytes) if err != nil { t.Errorf("NewBlockFromBytes: %v", err) return @@ -282,7 +259,7 @@ func TestBlockErrors(t *testing.T) { // Truncate the block byte buffer to force errors. shortBytes := block100000Bytes[:80] - _, err = btcutil.NewBlockFromBytes(shortBytes, pver) + _, err = btcutil.NewBlockFromBytes(shortBytes) if err != io.EOF { t.Errorf("NewBlockFromBytes: did not get expected error - "+ "got %v, want %v", err, io.EOF) diff --git a/internal_test.go b/internal_test.go index 0dfb8df..de96c76 100644 --- a/internal_test.go +++ b/internal_test.go @@ -11,8 +11,9 @@ interface. The functions are only exported while the tests are being run. package btcutil -// SetBlockBytes sets the internal raw block byte buffer to the passed buffer. -// It is used to inject errors and only available to the test package. +// SetBlockBytes sets the internal serialized block byte buffer to the passed +// buffer. It is used to inject errors and is only available to the test +// package. func (b *Block) SetBlockBytes(buf []byte) { - b.rawBlock = buf + b.serializedBlock = buf }