1 package wire
2 3 import (
4 "fmt"
5 "io"
6 )
7 8 // MaxAddrPerMsg is the maximum number of addresses that can be in a single bitcoin addr message (MsgAddr).
9 const MaxAddrPerMsg = 1000
10 11 // MsgAddr implements the Message interface and represents a bitcoin addr message. It is used to provide a list of known
12 // active peers on the network. An active peer is considered one that has transmitted a message within the last 3 hours.
13 // Nodes which have not transmitted in that time frame should be forgotten. Each message is limited to a maximum number
14 // of addresses, which is currently 1000. As a result, multiple messages must be used to relay the full list. Use the
15 // AddAddress function to podbuild up the list of known addresses when sending an addr message to another peer.
16 type MsgAddr struct {
17 AddrList []*NetAddress
18 }
19 20 // AddAddress adds a known active peer to the message.
21 func (msg *MsgAddr) AddAddress(na *NetAddress) (e error) {
22 if len(msg.AddrList)+1 > MaxAddrPerMsg {
23 str := fmt.Sprintf(
24 "too many addresses in message [max %v]",
25 MaxAddrPerMsg,
26 )
27 return messageError("MsgAddr.AddAddress", str)
28 }
29 msg.AddrList = append(msg.AddrList, na)
30 return nil
31 }
32 33 // AddAddresses adds multiple known active peers to the message.
34 func (msg *MsgAddr) AddAddresses(netAddrs ...*NetAddress) (e error) {
35 for _, na := range netAddrs {
36 e = msg.AddAddress(na)
37 if E.Chk(e) {
38 return
39 }
40 }
41 return
42 }
43 44 // ClearAddresses removes all addresses from the message.
45 func (msg *MsgAddr) ClearAddresses() {
46 msg.AddrList = []*NetAddress{}
47 }
48 49 // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. This is part of the Message interface
50 // implementation.
51 func (msg *MsgAddr) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) (e error) {
52 var count uint64
53 if count, e = ReadVarInt(r, pver); E.Chk(e) {
54 return
55 }
56 // Limit to max addresses per message.
57 if count > MaxAddrPerMsg {
58 str := fmt.Sprintf(
59 "too many addresses for message "+
60 "[count %v, max %v]", count, MaxAddrPerMsg,
61 )
62 return messageError("MsgAddr.BtcDecode", str)
63 }
64 addrList := make([]NetAddress, count)
65 msg.AddrList = make([]*NetAddress, 0, count)
66 for i := uint64(0); i < count; i++ {
67 na := &addrList[i]
68 if e = readNetAddress(r, pver, na, true); E.Chk(e) {
69 return
70 }
71 if e = msg.AddAddress(na); E.Chk(e) {
72 }
73 }
74 return
75 }
76 77 // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. This is part of the Message interface
78 // implementation.
79 func (msg *MsgAddr) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) (e error) {
80 // Protocol versions before MultipleAddressVersion only allowed 1 address per message.
81 count := len(msg.AddrList)
82 if pver < MultipleAddressVersion && count > 1 {
83 str := fmt.Sprintf(
84 "too many addresses for message of "+
85 "protocol version %v [count %v, max 1]", pver, count,
86 )
87 return messageError("MsgAddr.BtcEncode", str)
88 }
89 if count > MaxAddrPerMsg {
90 str := fmt.Sprintf(
91 "too many addresses for message "+
92 "[count %v, max %v]", count, MaxAddrPerMsg,
93 )
94 return messageError("MsgAddr.BtcEncode", str)
95 }
96 if e = WriteVarInt(w, pver, uint64(count)); E.Chk(e) {
97 return
98 }
99 for _, na := range msg.AddrList {
100 if e = writeNetAddress(w, pver, na, true); E.Chk(e) {
101 return
102 }
103 }
104 return
105 }
106 107 // Command returns the protocol command string for the message. This is part of the Message interface implementation.
108 func (msg *MsgAddr) Command() string {
109 return CmdAddr
110 }
111 112 // MaxPayloadLength returns the maximum length the payload can be for the receiver. This is part of the Message
113 // interface implementation.
114 func (msg *MsgAddr) MaxPayloadLength(pver uint32) uint32 {
115 if pver < MultipleAddressVersion {
116 // Num addresses (varInt) + a single net addresses.
117 return MaxVarIntPayload + maxNetAddressPayload(pver)
118 }
119 // Num addresses (varInt) + max allowed addresses.
120 return MaxVarIntPayload + (MaxAddrPerMsg * maxNetAddressPayload(pver))
121 }
122 123 // NewMsgAddr returns a new bitcoin addr message that conforms to the Message interface. See MsgAddr for details.
124 func NewMsgAddr() *MsgAddr {
125 return &MsgAddr{
126 AddrList: make([]*NetAddress, 0, MaxAddrPerMsg),
127 }
128 }
129