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