github.com/palcoin-project/palcd@v1.0.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  	count, err := ReadVarInt(r, pver)
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	// Limit to max block headers per message.
    46  	if count > MaxBlockHeadersPerMsg {
    47  		str := fmt.Sprintf("too many block headers for message "+
    48  			"[count %v, max %v]", count, MaxBlockHeadersPerMsg)
    49  		return messageError("MsgHeaders.BtcDecode", str)
    50  	}
    51  
    52  	// Create a contiguous slice of headers to deserialize into in order to
    53  	// reduce the number of allocations.
    54  	headers := make([]BlockHeader, count)
    55  	msg.Headers = make([]*BlockHeader, 0, count)
    56  	for i := uint64(0); i < count; i++ {
    57  		bh := &headers[i]
    58  		err := readBlockHeader(r, pver, bh)
    59  		if err != nil {
    60  			return err
    61  		}
    62  
    63  		txCount, err := ReadVarInt(r, pver)
    64  		if err != nil {
    65  			return err
    66  		}
    67  
    68  		// Ensure the transaction count is zero for headers.
    69  		if txCount > 0 {
    70  			str := fmt.Sprintf("block headers may not contain "+
    71  				"transactions [count %v]", txCount)
    72  			return messageError("MsgHeaders.BtcDecode", str)
    73  		}
    74  		msg.AddBlockHeader(bh)
    75  	}
    76  
    77  	return nil
    78  }
    79  
    80  // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
    81  // This is part of the Message interface implementation.
    82  func (msg *MsgHeaders) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error {
    83  	// Limit to max block headers per message.
    84  	count := len(msg.Headers)
    85  	if count > MaxBlockHeadersPerMsg {
    86  		str := fmt.Sprintf("too many block headers for message "+
    87  			"[count %v, max %v]", count, MaxBlockHeadersPerMsg)
    88  		return messageError("MsgHeaders.BtcEncode", str)
    89  	}
    90  
    91  	err := WriteVarInt(w, pver, uint64(count))
    92  	if err != nil {
    93  		return err
    94  	}
    95  
    96  	for _, bh := range msg.Headers {
    97  		err := writeBlockHeader(w, pver, bh)
    98  		if err != nil {
    99  			return err
   100  		}
   101  
   102  		// The wire protocol encoding always includes a 0 for the number
   103  		// of transactions on header messages.  This is really just an
   104  		// artifact of the way the original implementation serializes
   105  		// block headers, but it is required.
   106  		err = WriteVarInt(w, pver, 0)
   107  		if err != nil {
   108  			return err
   109  		}
   110  	}
   111  
   112  	return nil
   113  }
   114  
   115  // Command returns the protocol command string for the message.  This is part
   116  // of the Message interface implementation.
   117  func (msg *MsgHeaders) Command() string {
   118  	return CmdHeaders
   119  }
   120  
   121  // MaxPayloadLength returns the maximum length the payload can be for the
   122  // receiver.  This is part of the Message interface implementation.
   123  func (msg *MsgHeaders) MaxPayloadLength(pver uint32) uint32 {
   124  	// Num headers (varInt) + max allowed headers (header length + 1 byte
   125  	// for the number of transactions which is always 0).
   126  	return MaxVarIntPayload + ((MaxBlockHeaderPayload + 1) *
   127  		MaxBlockHeadersPerMsg)
   128  }
   129  
   130  // NewMsgHeaders returns a new bitcoin headers message that conforms to the
   131  // Message interface.  See MsgHeaders for details.
   132  func NewMsgHeaders() *MsgHeaders {
   133  	return &MsgHeaders{
   134  		Headers: make([]*BlockHeader, 0, MaxBlockHeadersPerMsg),
   135  	}
   136  }