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