1 package wire
2 3 import (
4 "fmt"
5 "io"
6 )
7 8 // MsgNotFound defines a bitcoin notfound message which is sent in response to a getdata message if any of the requested
9 // data in not available on the peer. Each message is limited to a maximum number of inventory vectors, which is
10 // currently 50,000. Use the AddInvVect function to podbuild up the list of inventory vectors when sending a notfound
11 // message to another peer.
12 type MsgNotFound struct {
13 InvList []*InvVect
14 }
15 16 // AddInvVect adds an inventory vector to the message.
17 func (msg *MsgNotFound) AddInvVect(iv *InvVect) (e error) {
18 if len(msg.InvList)+1 > MaxInvPerMsg {
19 str := fmt.Sprintf(
20 "too many invvect in message [max %v]",
21 MaxInvPerMsg,
22 )
23 return messageError("MsgNotFound.AddInvVect", str)
24 }
25 msg.InvList = append(msg.InvList, iv)
26 return nil
27 }
28 29 // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. This is part of the Message interface
30 // implementation.
31 func (msg *MsgNotFound) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) (e error) {
32 var count uint64
33 if count, e = ReadVarInt(r, pver); E.Chk(e) {
34 return
35 }
36 // Limit to max inventory vectors per message.
37 if count > MaxInvPerMsg {
38 str := fmt.Sprintf("too many invvect in message [%v]", count)
39 return messageError("MsgNotFound.BtcDecode", str)
40 }
41 // Create a contiguous slice of inventory vectors to deserialize into in order to reduce the number of allocations.
42 invList := make([]InvVect, count)
43 msg.InvList = make([]*InvVect, 0, count)
44 for i := uint64(0); i < count; i++ {
45 iv := &invList[i]
46 if e = readInvVect(r, pver, iv); E.Chk(e) {
47 return
48 }
49 if e = msg.AddInvVect(iv); E.Chk(e) {
50 }
51 }
52 return nil
53 }
54 55 // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. This is part of the Message interface
56 // implementation.
57 func (msg *MsgNotFound) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) (e error) {
58 // Limit to max inventory vectors per message.
59 count := len(msg.InvList)
60 if count > MaxInvPerMsg {
61 str := fmt.Sprintf("too many invvect in message [%v]", count)
62 return messageError("MsgNotFound.BtcEncode", str)
63 }
64 if e = WriteVarInt(w, pver, uint64(count)); E.Chk(e) {
65 return
66 }
67 for _, iv := range msg.InvList {
68 if e = writeInvVect(w, pver, iv); E.Chk(e) {
69 return
70 }
71 }
72 return
73 }
74 75 // Command returns the protocol command string for the message. This is part of the Message interface implementation.
76 func (msg *MsgNotFound) Command() string {
77 return CmdNotFound
78 }
79 80 // MaxPayloadLength returns the maximum length the payload can be for the receiver. This is part of the Message
81 // interface implementation.
82 func (msg *MsgNotFound) MaxPayloadLength(pver uint32) uint32 {
83 // Max var int 9 bytes + max InvVects at 36 bytes each. Num inventory vectors (varInt) + max allowed inventory
84 // vectors.
85 return MaxVarIntPayload + (MaxInvPerMsg * maxInvVectPayload)
86 }
87 88 // NewMsgNotFound returns a new bitcoin notfound message that conforms to the Message interface. See MsgNotFound for
89 // details.
90 func NewMsgNotFound() *MsgNotFound {
91 return &MsgNotFound{
92 InvList: make([]*InvVect, 0, defaultInvListAlloc),
93 }
94 }
95