github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/wire/msgmerkleblock.go (about)

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