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 }