github.com/lbryio/lbcd@v0.22.119/wire/msgmerkleblock.go (about)

     1  // Copyright (c) 2014-2016 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package wire
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  
    11  	"github.com/lbryio/lbcd/chaincfg/chainhash"
    12  )
    13  
    14  // maxFlagsPerMerkleBlock is the maximum number of flag bytes that could
    15  // possibly fit into a merkle block.  Since each transaction is represented by
    16  // a single bit, this is the max number of transactions per block divided by
    17  // 8 bits per byte.  Then an extra one to cover partials.
    18  const maxFlagsPerMerkleBlock = maxTxPerBlock / 8
    19  
    20  // MsgMerkleBlock implements the Message interface and represents a bitcoin
    21  // merkleblock message which is used to reset a Bloom filter.
    22  //
    23  // This message was not added until protocol version BIP0037Version.
    24  type MsgMerkleBlock struct {
    25  	Header       BlockHeader
    26  	Transactions uint32
    27  	Hashes       []*chainhash.Hash
    28  	Flags        []byte
    29  }
    30  
    31  // AddTxHash adds a new transaction hash to the message.
    32  func (msg *MsgMerkleBlock) AddTxHash(hash *chainhash.Hash) error {
    33  	if len(msg.Hashes)+1 > maxTxPerBlock {
    34  		str := fmt.Sprintf("too many tx hashes for message [max %v]",
    35  			maxTxPerBlock)
    36  		return messageError("MsgMerkleBlock.AddTxHash", str)
    37  	}
    38  
    39  	msg.Hashes = append(msg.Hashes, hash)
    40  	return nil
    41  }
    42  
    43  // BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
    44  // This is part of the Message interface implementation.
    45  func (msg *MsgMerkleBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error {
    46  	if pver < BIP0037Version {
    47  		str := fmt.Sprintf("merkleblock message invalid for protocol "+
    48  			"version %d", pver)
    49  		return messageError("MsgMerkleBlock.BtcDecode", str)
    50  	}
    51  
    52  	err := readBlockHeader(r, pver, &msg.Header)
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	err = readElement(r, &msg.Transactions)
    58  	if err != nil {
    59  		return err
    60  	}
    61  
    62  	// Read num block locator hashes and limit to max.
    63  	count, err := ReadVarInt(r, pver)
    64  	if err != nil {
    65  		return err
    66  	}
    67  	if count > maxTxPerBlock {
    68  		str := fmt.Sprintf("too many transaction hashes for message "+
    69  			"[count %v, max %v]", count, maxTxPerBlock)
    70  		return messageError("MsgMerkleBlock.BtcDecode", str)
    71  	}
    72  
    73  	// Create a contiguous slice of hashes to deserialize into in order to
    74  	// reduce the number of allocations.
    75  	hashes := make([]chainhash.Hash, count)
    76  	msg.Hashes = make([]*chainhash.Hash, 0, count)
    77  	for i := uint64(0); i < count; i++ {
    78  		hash := &hashes[i]
    79  		err := readElement(r, hash)
    80  		if err != nil {
    81  			return err
    82  		}
    83  		msg.AddTxHash(hash)
    84  	}
    85  
    86  	msg.Flags, err = ReadVarBytes(r, pver, maxFlagsPerMerkleBlock,
    87  		"merkle block flags size")
    88  	return err
    89  }
    90  
    91  // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
    92  // This is part of the Message interface implementation.
    93  func (msg *MsgMerkleBlock) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error {
    94  	if pver < BIP0037Version {
    95  		str := fmt.Sprintf("merkleblock message invalid for protocol "+
    96  			"version %d", pver)
    97  		return messageError("MsgMerkleBlock.BtcEncode", str)
    98  	}
    99  
   100  	// Read num transaction hashes and limit to max.
   101  	numHashes := len(msg.Hashes)
   102  	if numHashes > maxTxPerBlock {
   103  		str := fmt.Sprintf("too many transaction hashes for message "+
   104  			"[count %v, max %v]", numHashes, maxTxPerBlock)
   105  		return messageError("MsgMerkleBlock.BtcDecode", str)
   106  	}
   107  	numFlagBytes := len(msg.Flags)
   108  	if numFlagBytes > maxFlagsPerMerkleBlock {
   109  		str := fmt.Sprintf("too many flag bytes for message [count %v, "+
   110  			"max %v]", numFlagBytes, maxFlagsPerMerkleBlock)
   111  		return messageError("MsgMerkleBlock.BtcDecode", str)
   112  	}
   113  
   114  	err := writeBlockHeader(w, pver, &msg.Header)
   115  	if err != nil {
   116  		return err
   117  	}
   118  
   119  	err = writeElement(w, msg.Transactions)
   120  	if err != nil {
   121  		return err
   122  	}
   123  
   124  	err = WriteVarInt(w, pver, uint64(numHashes))
   125  	if err != nil {
   126  		return err
   127  	}
   128  	for _, hash := range msg.Hashes {
   129  		err = writeElement(w, hash)
   130  		if err != nil {
   131  			return err
   132  		}
   133  	}
   134  
   135  	return WriteVarBytes(w, pver, msg.Flags)
   136  }
   137  
   138  // Command returns the protocol command string for the message.  This is part
   139  // of the Message interface implementation.
   140  func (msg *MsgMerkleBlock) Command() string {
   141  	return CmdMerkleBlock
   142  }
   143  
   144  // MaxPayloadLength returns the maximum length the payload can be for the
   145  // receiver.  This is part of the Message interface implementation.
   146  func (msg *MsgMerkleBlock) MaxPayloadLength(pver uint32) uint32 {
   147  	return MaxBlockPayload
   148  }
   149  
   150  // NewMsgMerkleBlock returns a new bitcoin merkleblock message that conforms to
   151  // the Message interface.  See MsgMerkleBlock for details.
   152  func NewMsgMerkleBlock(bh *BlockHeader) *MsgMerkleBlock {
   153  	return &MsgMerkleBlock{
   154  		Header:       *bh,
   155  		Transactions: 0,
   156  		Hashes:       make([]*chainhash.Hash, 0),
   157  		Flags:        make([]byte, 0),
   158  	}
   159  }