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

     1  // Copyright (c) 2013-2016 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  // MaxBlockHeadersPerMsg is the maximum number of block headers that can be in
    14  // a single bitcoin headers message.
    15  const MaxBlockHeadersPerMsg = 2000
    16  
    17  // MsgHeaders implements the Message interface and represents a bitcoin headers
    18  // message.  It is used to deliver block header information in response
    19  // to a getheaders message (MsgGetHeaders).  The maximum number of block headers
    20  // per message is currently 2000.  See MsgGetHeaders for details on requesting
    21  // the headers.
    22  type MsgHeaders struct {
    23  	Headers []*BlockHeader
    24  }
    25  
    26  // AddBlockHeader adds a new block header to the message.
    27  func (msg *MsgHeaders) AddBlockHeader(bh *BlockHeader) error {
    28  	if len(msg.Headers)+1 > MaxBlockHeadersPerMsg {
    29  		str := fmt.Sprintf("too many block headers in message [max %v]",
    30  			MaxBlockHeadersPerMsg)
    31  		return messageError("MsgHeaders.AddBlockHeader", str)
    32  	}
    33  
    34  	msg.Headers = append(msg.Headers, bh)
    35  	return nil
    36  }
    37  
    38  // BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
    39  // This is part of the Message interface implementation.
    40  func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32) error {
    41  	count, err := ReadVarInt(r, pver)
    42  	if err != nil {
    43  		return err
    44  	}
    45  
    46  	// Limit to max block headers per message.
    47  	if count > MaxBlockHeadersPerMsg {
    48  		str := fmt.Sprintf("too many block headers for message "+
    49  			"[count %v, max %v]", count, MaxBlockHeadersPerMsg)
    50  		return messageError("MsgHeaders.BtcDecode", str)
    51  	}
    52  
    53  	// Create a contiguous slice of headers to deserialize into in order to
    54  	// reduce the number of allocations.
    55  	headers := make([]BlockHeader, count)
    56  	msg.Headers = make([]*BlockHeader, 0, count)
    57  	for i := uint64(0); i < count; i++ {
    58  		bh := &headers[i]
    59  		err := readBlockHeader(r, pver, bh)
    60  		if err != nil {
    61  			return err
    62  		}
    63  
    64  		txCount, err := ReadVarInt(r, pver)
    65  		if err != nil {
    66  			return err
    67  		}
    68  
    69  		// Ensure the transaction count is zero for headers.
    70  		if txCount > 0 {
    71  			str := fmt.Sprintf("block headers may not contain "+
    72  				"transactions [count %v]", txCount)
    73  			return messageError("MsgHeaders.BtcDecode", str)
    74  		}
    75  		msg.AddBlockHeader(bh)
    76  	}
    77  
    78  	return nil
    79  }
    80  
    81  // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
    82  // This is part of the Message interface implementation.
    83  func (msg *MsgHeaders) BtcEncode(w io.Writer, pver uint32) error {
    84  	// Limit to max block headers per message.
    85  	count := len(msg.Headers)
    86  	if count > MaxBlockHeadersPerMsg {
    87  		str := fmt.Sprintf("too many block headers for message "+
    88  			"[count %v, max %v]", count, MaxBlockHeadersPerMsg)
    89  		return messageError("MsgHeaders.BtcEncode", str)
    90  	}
    91  
    92  	err := WriteVarInt(w, pver, uint64(count))
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	for _, bh := range msg.Headers {
    98  		err := writeBlockHeader(w, pver, bh)
    99  		if err != nil {
   100  			return err
   101  		}
   102  
   103  		// The wire protocol encoding always includes a 0 for the number
   104  		// of transactions on header messages.  This is really just an
   105  		// artifact of the way the original implementation serializes
   106  		// block headers, but it is required.
   107  		err = WriteVarInt(w, pver, 0)
   108  		if err != nil {
   109  			return err
   110  		}
   111  	}
   112  
   113  	return nil
   114  }
   115  
   116  // Command returns the protocol command string for the message.  This is part
   117  // of the Message interface implementation.
   118  func (msg *MsgHeaders) Command() string {
   119  	return CmdHeaders
   120  }
   121  
   122  // MaxPayloadLength returns the maximum length the payload can be for the
   123  // receiver.  This is part of the Message interface implementation.
   124  func (msg *MsgHeaders) MaxPayloadLength(pver uint32) uint32 {
   125  	// Num headers (varInt) + max allowed headers (header length + 1 byte
   126  	// for the number of transactions which is always 0).
   127  	return MaxVarIntPayload + ((MaxBlockHeaderPayload + 1) *
   128  		MaxBlockHeadersPerMsg)
   129  }
   130  
   131  // NewMsgHeaders returns a new bitcoin headers message that conforms to the
   132  // Message interface.  See MsgHeaders for details.
   133  func NewMsgHeaders() *MsgHeaders {
   134  	return &MsgHeaders{
   135  		Headers: make([]*BlockHeader, 0, MaxBlockHeadersPerMsg),
   136  	}
   137  }