github.com/btcsuite/btcd@v0.24.0/wire/msgheaders.go (about)

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