msgheaders.go raw

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