github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/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 70 if txCount > 0 { 71 // remove for bc2 72 // str := fmt.Sprintf("block headers may not contain "+ 73 // "transactions [count %v]", txCount) 74 // return messageError("MsgHeaders.BtcDecode", str) 75 } 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 err := WriteVarInt(w, pver, uint64(count)) 95 if err != nil { 96 return err 97 } 98 99 for _, bh := range msg.Headers { 100 err := WriteBlockHeader(w, pver, bh) 101 if err != nil { 102 return err 103 } 104 105 // The wire protocol encoding always includes a 0 for the number 106 // of transactions on header messages. This is really just an 107 // artifact of the way the original implementation serializes 108 // block headers, but it is required. 109 err = WriteVarInt(w, pver, 0) 110 if err != nil { 111 return err 112 } 113 } 114 115 return nil 116 } 117 118 // Command returns the protocol command string for the message. This is part 119 // of the Message interface implementation. 120 func (msg *MsgHeaders) Command() string { 121 return CmdHeaders 122 } 123 124 // MaxPayloadLength returns the maximum length the payload can be for the 125 // receiver. This is part of the Message interface implementation. 126 func (msg *MsgHeaders) MaxPayloadLength(pver uint32) uint32 { 127 // Num headers (varInt) + max allowed headers (header length + 1 byte 128 // for the number of transactions which is always 0). 129 return MaxVarIntPayload + ((MaxBlockHeaderPayload + 1) * 130 MaxBlockHeadersPerMsg) 131 } 132 133 // NewMsgHeaders returns a new bitcoin headers message that conforms to the 134 // Message interface. See MsgHeaders for details. 135 func NewMsgHeaders() *MsgHeaders { 136 return &MsgHeaders{ 137 Headers: make([]*BlockHeader, 0, MaxBlockHeadersPerMsg), 138 } 139 }