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