OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / wire / msginv.go
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 }