github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/wire/msginv.go (about) 1 // Copyright (c) 2013-2015 The btcsuite developers 2 // Copyright (c) 2016 The Dash developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package wire 7 8 import ( 9 "fmt" 10 "io" 11 ) 12 13 // defaultInvListAlloc is the default size used for the backing array for an 14 // inventory list. The array will dynamically grow as needed, but this 15 // figure is intended to provide enough space for the max number of inventory 16 // vectors in a *typical* inventory message without needing to grow the backing 17 // array multiple times. Technically, the list can grow to MaxInvPerMsg, but 18 // rather than using that large figure, this figure more accurately reflects the 19 // typical case. 20 const defaultInvListAlloc = 1000 21 22 // MsgInv implements the Message interface and represents a bitcoin inv message. 23 // It is used to advertise a peer's known data such as blocks and transactions 24 // through inventory vectors. It may be sent unsolicited to inform other peers 25 // of the data or in response to a getblocks message (MsgGetBlocks). Each 26 // message is limited to a maximum number of inventory vectors, which is 27 // currently 50,000. 28 // 29 // Use the AddInvVect function to build up the list of inventory vectors when 30 // sending an inv message to another peer. 31 type MsgInv struct { 32 InvList []*InvVect 33 } 34 35 // AddInvVect adds an inventory vector to the message. 36 func (msg *MsgInv) AddInvVect(iv *InvVect) error { 37 if len(msg.InvList)+1 > MaxInvPerMsg { 38 str := fmt.Sprintf("too many invvect in message [max %v]", 39 MaxInvPerMsg) 40 return messageError("MsgInv.AddInvVect", str) 41 } 42 43 msg.InvList = append(msg.InvList, iv) 44 return nil 45 } 46 47 // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. 48 // This is part of the Message interface implementation. 49 func (msg *MsgInv) BtcDecode(r io.Reader, pver uint32) error { 50 count, err := ReadVarInt(r, pver) 51 if err != nil { 52 return err 53 } 54 55 // Limit to max inventory vectors per message. 56 if count > MaxInvPerMsg { 57 str := fmt.Sprintf("too many invvect in message [%v]", count) 58 return messageError("MsgInv.BtcDecode", str) 59 } 60 61 // Create a contiguous slice of inventory vectors to deserialize into in 62 // order to reduce the number of allocations. 63 invList := make([]InvVect, count) 64 msg.InvList = make([]*InvVect, 0, count) 65 for i := uint64(0); i < count; i++ { 66 iv := &invList[i] 67 err := readInvVect(r, pver, iv) 68 if err != nil { 69 return err 70 } 71 msg.AddInvVect(iv) 72 } 73 74 return nil 75 } 76 77 // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. 78 // This is part of the Message interface implementation. 79 func (msg *MsgInv) BtcEncode(w io.Writer, pver uint32) error { 80 // Limit to max inventory vectors per message. 81 count := len(msg.InvList) 82 if count > MaxInvPerMsg { 83 str := fmt.Sprintf("too many invvect in message [%v]", count) 84 return messageError("MsgInv.BtcEncode", str) 85 } 86 87 err := WriteVarInt(w, pver, uint64(count)) 88 if err != nil { 89 return err 90 } 91 92 for _, iv := range msg.InvList { 93 err := writeInvVect(w, pver, iv) 94 if err != nil { 95 return err 96 } 97 } 98 99 return nil 100 } 101 102 // Command returns the protocol command string for the message. This is part 103 // of the Message interface implementation. 104 func (msg *MsgInv) Command() string { 105 return CmdInv 106 } 107 108 // MaxPayloadLength returns the maximum length the payload can be for the 109 // receiver. This is part of the Message interface implementation. 110 func (msg *MsgInv) MaxPayloadLength(pver uint32) uint32 { 111 // Num inventory vectors (varInt) + max allowed inventory vectors. 112 return MaxVarIntPayload + (MaxInvPerMsg * maxInvVectPayload) 113 } 114 115 // NewMsgInv returns a new bitcoin inv message that conforms to the Message 116 // interface. See MsgInv for details. 117 func NewMsgInv() *MsgInv { 118 return &MsgInv{ 119 InvList: make([]*InvVect, 0, defaultInvListAlloc), 120 } 121 } 122 123 // NewMsgInvSizeHint returns a new bitcoin inv message that conforms to the 124 // Message interface. See MsgInv for details. This function differs from 125 // NewMsgInv in that it allows a default allocation size for the backing array 126 // which houses the inventory vector list. This allows callers who know in 127 // advance how large the inventory list will grow to avoid the overhead of 128 // growing the internal backing array several times when appending large amounts 129 // of inventory vectors with AddInvVect. Note that the specified hint is just 130 // that - a hint that is used for the default allocation size. Adding more 131 // (or less) inventory vectors will still work properly. The size hint is 132 // limited to MaxInvPerMsg. 133 func NewMsgInvSizeHint(sizeHint uint) *MsgInv { 134 // Limit the specified hint to the maximum allow per message. 135 if sizeHint > MaxInvPerMsg { 136 sizeHint = MaxInvPerMsg 137 } 138 139 return &MsgInv{ 140 InvList: make([]*InvVect, 0, sizeHint), 141 } 142 }