diff --git a/addrmgr/addrmanager.go b/addrmgr/addrmanager.go index 402e43300..6bb97d8ac 100644 --- a/addrmgr/addrmanager.go +++ b/addrmgr/addrmanager.go @@ -110,14 +110,14 @@ type AddrManager struct { type addrTypeFilter struct { wantIPv4 bool wantIPv6 bool - wantTORv3 bool + wantTorV3 bool } // bucketStats tracks the number of addresses by type within a single bucket. type bucketStats struct { numIPv4 uint16 numIPv6 uint16 - numTORv3 uint16 + numTorV3 uint16 } // serializedKnownAddress is used to represent the serializable state of a @@ -249,8 +249,8 @@ func (bs *bucketStats) increment(addrType NetAddressType) { bs.numIPv4++ case IPv6Address: bs.numIPv6++ - case TORv3Address: - bs.numTORv3++ + case TorV3Address: + bs.numTorV3++ } } @@ -261,8 +261,8 @@ func (bs *bucketStats) decrement(addrType NetAddressType) { bs.numIPv4-- case IPv6Address: bs.numIPv6-- - case TORv3Address: - bs.numTORv3-- + case TorV3Address: + bs.numTorV3-- } } @@ -275,8 +275,8 @@ func (bs *bucketStats) total(filter addrTypeFilter) int { if filter.wantIPv6 { sum += int(bs.numIPv6) } - if filter.wantTORv3 { - sum += int(bs.numTORv3) + if filter.wantTorV3 { + sum += int(bs.numTorV3) } return sum } @@ -285,14 +285,14 @@ func (bs *bucketStats) total(filter addrTypeFilter) int { func (bs *bucketStats) matches(filter addrTypeFilter) bool { return (filter.wantIPv4 && bs.numIPv4 > 0) || (filter.wantIPv6 && bs.numIPv6 > 0) || - (filter.wantTORv3 && bs.numTORv3 > 0) + (filter.wantTorV3 && bs.numTorV3 > 0) } // matches returns true if the address type matches the filter criteria. func (f addrTypeFilter) matches(addrType NetAddressType) bool { return (f.wantIPv4 && addrType == IPv4Address) || (f.wantIPv6 && addrType == IPv6Address) || - (f.wantTORv3 && addrType == TORv3Address) + (f.wantTorV3 && addrType == TorV3Address) } // addOrUpdateAddress is a helper function to either update an address already known @@ -829,16 +829,16 @@ func (a *AddrManager) reset() { // returns the result. If the host string is not recognized as any known type, // then an unknown address type is returned without error. func EncodeHost(host string) (NetAddressType, []byte) { - // Check if this is a valid TORv3 address. + // Check if this is a valid TorV3 address. if len(host) == 62 && strings.HasSuffix(host, ".onion") { - // TORv3 addresses tend to be lowercase by convention, but + // TorV3 addresses tend to be lowercase by convention, but // Go's base32.StdEncoding.DecodeString expects uppercase // input. Convert to uppercase for successful decoding. torAddressBytes, err := base32.StdEncoding.DecodeString( strings.ToUpper(host[:56])) if err == nil { - if pubkey, valid := isTORv3(torAddressBytes); valid { - return TORv3Address, pubkey[:] + if pubkey, valid := isTorV3(torAddressBytes); valid { + return TorV3Address, pubkey[:] } } } @@ -872,10 +872,10 @@ func (a *AddrManager) GetAddress(filterFn NetAddressTypeFilter) *KnownAddress { filter := addrTypeFilter{ wantIPv4: filterFn(IPv4Address), wantIPv6: filterFn(IPv6Address), - wantTORv3: filterFn(TORv3Address), + wantTorV3: filterFn(TorV3Address), } - if !filter.wantIPv4 && !filter.wantIPv6 && !filter.wantTORv3 { + if !filter.wantIPv4 && !filter.wantIPv6 && !filter.wantTorV3 { return nil } @@ -1241,7 +1241,7 @@ const ( // Ipv6Strong represents a connection state between two IPv6 addresses. Ipv6Strong - // Private represents a connection state between two TORv3 addresses. + // Private represents a connection state between two TorV3 addresses. Private ) @@ -1254,9 +1254,9 @@ func getRemoteReachabilityFromLocal(localAddr, remoteAddr *NetAddress) NetAddres case !remoteAddr.IsRoutable(): return Unreachable - case remoteAddr.Type == TORv3Address: + case remoteAddr.Type == TorV3Address: switch { - case localAddr.Type == TORv3Address: + case localAddr.Type == TorV3Address: return Private case localAddr.IsRoutable() && localAddr.Type == IPv4Address: return Ipv4 @@ -1280,7 +1280,7 @@ func getRemoteReachabilityFromLocal(localAddr, remoteAddr *NetAddress) NetAddres switch { case localAddr.IsRoutable() && localAddr.Type == IPv4Address: return Ipv4 - case localAddr.Type == TORv3Address: + case localAddr.Type == TorV3Address: return Ipv4 default: return Unreachable @@ -1294,7 +1294,7 @@ func getRemoteReachabilityFromLocal(localAddr, remoteAddr *NetAddress) NetAddres return Teredo case localAddr.Type == IPv4Address: return Ipv4 - case localAddr.Type == TORv3Address: + case localAddr.Type == TorV3Address: return Ipv6Strong // Is our IPv6 tunneled? diff --git a/addrmgr/addrmanager_test.go b/addrmgr/addrmanager_test.go index 2310ec957..94919a114 100644 --- a/addrmgr/addrmanager_test.go +++ b/addrmgr/addrmanager_test.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2014 The btcsuite developers -// Copyright (c) 2015-2025 The Decred developers +// Copyright (c) 2015-2026 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -41,9 +41,9 @@ func natfOnlyIPv6(addrType NetAddressType) bool { return addrType == IPv6Address } -// natfOnlyTORv3 defines a filter that will only allow TORv3 netAddrs. -func natfOnlyTORv3(addrType NetAddressType) bool { - return addrType == TORv3Address +// natfOnlyTorV3 defines a filter that will only allow TorV3 netAddrs. +func natfOnlyTorV3(addrType NetAddressType) bool { + return addrType == TorV3Address } // addAddressByIP is a convenience function that adds an address to the @@ -708,7 +708,7 @@ func TestAddLocalAddress(t *testing.T) { priority: InterfacePrio, valid: true, }, { - name: "routable TORv3 address", + name: "routable TorV3 address", host: torv3Host, priority: ManualPrio, valid: true, @@ -787,12 +787,12 @@ func TestGetBestLocalAddress(t *testing.T) { newAddressFromIP(net.ParseIP("2001:470::1")), } - // TORv3 address. + // TorV3 address. torAddrType, torAddrBytes := EncodeHost(torv3Host) torAddr, err := NewNetAddressFromParams(torAddrType, torAddrBytes, 0, time.Unix(time.Now().Unix(), 0), wire.SFNodeNetwork) if err != nil { - t.Fatalf("failed to create TORv3 NetAddress: %v", err) + t.Fatalf("failed to create TorV3 NetAddress: %v", err) } var tests = []struct { @@ -892,7 +892,7 @@ func TestGetBestLocalAddress(t *testing.T) { } } - // Test4: Add TORv3 address with ManualPrio + // Test4: Add TorV3 address with ManualPrio amgr.AddLocalAddress(torAddr, ManualPrio) for x, test := range tests { remoteAddr := test.remoteAddr @@ -1120,10 +1120,10 @@ func TestGetAddressWithFilter(t *testing.T) { filter: natfOnlyIPv6, wantType: IPv6Address, }, { - name: "returns address matching TORv3 filter", + name: "returns address matching TorV3 filter", addresses: []*NetAddress{ipv4Addr, ipv6Addr, torv3Addr}, - filter: natfOnlyTORv3, - wantType: TORv3Address, + filter: natfOnlyTorV3, + wantType: TorV3Address, }, { name: "returns nil when no matching IPv4 addresses", addresses: []*NetAddress{ipv6Addr}, @@ -1136,7 +1136,7 @@ func TestGetAddressWithFilter(t *testing.T) { wantNil: true, }, { name: "returns nil when address manager empty", - addresses: []*NetAddress{}, + addresses: nil, filter: natfAny, wantNil: true, }} diff --git a/addrmgr/netaddress.go b/addrmgr/netaddress.go index 9ceaa9886..4380bb147 100644 --- a/addrmgr/netaddress.go +++ b/addrmgr/netaddress.go @@ -38,7 +38,7 @@ type NetAddress struct { // IsRoutable returns a boolean indicating whether the network address is // routable. func (netAddr *NetAddress) IsRoutable() bool { - if netAddr.Type == TORv3Address { + if netAddr.Type == TorV3Address { return true } return IsRoutable(netAddr.IP) @@ -53,10 +53,10 @@ func (netAddr *NetAddress) ipString() string { return net.IP(netIP).String() case IPv4Address: return net.IP(netIP).String() - case TORv3Address: + case TorV3Address: var publicKey [32]byte copy(publicKey[:], netIP) - checksum := calcTORv3Checksum(publicKey) + checksum := calcTorV3Checksum(publicKey) var torAddressBytes [35]byte copy(torAddressBytes[:32], publicKey[:]) copy(torAddressBytes[32:34], checksum[:]) @@ -105,8 +105,8 @@ func deriveNetAddressType(claimedType NetAddressType, addrBytes []byte) (NetAddr return IPv4Address, nil case len == 16: return IPv6Address, nil - case len == 32 && claimedType == TORv3Address: - return TORv3Address, nil + case len == 32 && claimedType == TorV3Address: + return TorV3Address, nil } str := fmt.Sprintf("unable to determine address type from raw network "+ "address bytes: %v", addrBytes) diff --git a/addrmgr/netaddress_test.go b/addrmgr/netaddress_test.go index b70ad8890..8008b21b4 100644 --- a/addrmgr/netaddress_test.go +++ b/addrmgr/netaddress_test.go @@ -110,7 +110,7 @@ func TestKey(t *testing.T) { {host: "fee2::3:3", port: 8335, want: "[fee2::3:3]:8335"}, {host: "fef3::4:4", port: 8336, want: "[fef3::4:4]:8336"}, - // TORv3 + // TorV3 {host: torAddress, port: 8333, want: torAddress + ":8333"}, } @@ -220,14 +220,14 @@ func TestNewNetAddressFromParams(t *testing.T) { }, { name: "32 byte torv3 address stored in 32 bytes", - addrType: TORv3Address, + addrType: TorV3Address, addrBytes: torAddressBytes, want: &NetAddress{ IP: torAddressBytes, Port: port, Services: services, Timestamp: timestamp, - Type: TORv3Address, + Type: TorV3Address, }, error_expected: false, }, diff --git a/addrmgr/network.go b/addrmgr/network.go index 14ae95353..92b9f46a7 100644 --- a/addrmgr/network.go +++ b/addrmgr/network.go @@ -112,7 +112,7 @@ const ( IPv4Address NetAddressType = 1 IPv6Address NetAddressType = 2 // TorV2Address NetAddressType = 3 // No longer supported - TORv3Address NetAddressType = 4 + TorV3Address NetAddressType = 4 ) // NetAddressTypeFilter represents a function that returns whether a particular @@ -212,9 +212,9 @@ func isRFC6598(netIP net.IP) bool { return rfc6598Net.Contains(netIP) } -// calcTORv3Checksum returns the checksum bytes given a 32 byte -// TORv3 public key. -func calcTORv3Checksum(publicKey [32]byte) [2]byte { +// calcTorV3Checksum returns the checksum bytes given a 32-byte TorV3 public +// key. +func calcTorV3Checksum(publicKey [32]byte) [2]byte { const ( prefix = ".onion checksum" prefixLen = len(prefix) @@ -231,10 +231,10 @@ func calcTORv3Checksum(publicKey [32]byte) [2]byte { return result } -// isTORv3 returns whether or not the passed address is a valid TORv3 address +// isTorV3 returns whether or not the passed address is a valid TorV3 address // with the checksum and version bytes. If it is valid, it also returns the // public key of the tor v3 address. -func isTORv3(addressBytes []byte) ([32]byte, bool) { +func isTorV3(addressBytes []byte) ([32]byte, bool) { var publicKey [32]byte if len(addressBytes) != 35 { return publicKey, false @@ -246,7 +246,7 @@ func isTORv3(addressBytes []byte) ([32]byte, bool) { } copy(publicKey[:], addressBytes[:32]) - computedChecksum := calcTORv3Checksum(publicKey) + computedChecksum := calcTorV3Checksum(publicKey) var checksum [2]byte copy(checksum[:], addressBytes[32:34]) @@ -284,7 +284,7 @@ func IsRoutable(netIP net.IP) bool { // address. func (na *NetAddress) GroupKey() string { netIP := net.IP(na.IP) - if na.Type == TORv3Address { + if na.Type == TorV3Address { // Group is keyed off the first 4 bits of the public key. return fmt.Sprintf("torv3:%d", netIP[0]&0xf) } diff --git a/addrmgr/network_test.go b/addrmgr/network_test.go index bc22f0946..970f3c994 100644 --- a/addrmgr/network_test.go +++ b/addrmgr/network_test.go @@ -184,7 +184,7 @@ func TestGroupKey(t *testing.T) { {name: "ipv6 hurricane electric", host: "2001:470:1f10:a1::2", expected: "2001:470:1000::"}, {name: "ipv6 hurricane electric 2", host: "2001:0470:1f10:a1::2", expected: "2001:470:1000::"}, - // TORv3 + // TorV3 { name: "torv3", host: "xa4r2iadxm55fbnqgwwi5mymqdcofiu3w6rpbtqn7b2dyn7mgwj64jyd.onion", diff --git a/peer/peer.go b/peer/peer.go index 679544b70..c3bd3fca1 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2016-2025 The Decred developers +// Copyright (c) 2016-2026 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -30,7 +30,7 @@ import ( const ( // MaxProtocolVersion is the max protocol version the peer supports. - MaxProtocolVersion = wire.TORv3Version + MaxProtocolVersion = wire.AddrV2Version // outputBufferSize is the number of elements the output channels use. outputBufferSize = 5000 @@ -898,10 +898,7 @@ func (p *Peer) PushAddrV2Msg(addresses []wire.NetAddressV2) []wire.NetAddressV2 addrs = addrs[:wire.MaxAddrPerV2Msg] } - msg := wire.NewMsgAddrV2() - msg.AddrList = addrs - - p.QueueMessage(msg, nil) + p.QueueMessage(wire.NewMsgAddrV2(addrs), nil) return addrs } @@ -2077,14 +2074,14 @@ func (p *Peer) localVersionMsg() (*wire.MsgVersion, error) { if p.cfg.Proxy != "" { proxyaddress, _, err := net.SplitHostPort(p.cfg.Proxy) // invalid proxy means poorly configured, be on the safe side. - if err != nil || net.IP(p.na.IP).String() == proxyaddress { + if err != nil || net.IP(p.na.EncodedAddr).String() == proxyaddress { theirNA = wire.NewNetAddressIPPort(net.IP([]byte{0, 0, 0, 0}), 0, peerNA.Services) } } if theirNA == nil { theirNA = wire.NewNetAddressTimestamp(peerNA.Timestamp, peerNA.Services, - peerNA.IP, peerNA.Port) + peerNA.EncodedAddr, peerNA.Port) } // Create a wire.NetAddress with only the services set to use as the diff --git a/peer/peer_test.go b/peer/peer_test.go index 2fae203f1..03d88fac8 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -1,5 +1,5 @@ // Copyright (c) 2015-2016 The btcsuite developers -// Copyright (c) 2016-2025 The Decred developers +// Copyright (c) 2016-2026 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -477,9 +477,10 @@ func TestPeerListeners(t *testing.T) { }, { listener: "OnAddrV2", msg: func() *wire.MsgAddrV2 { - msg := wire.NewMsgAddrV2() - msg.AddAddress(wire.NewNetAddressV2(wire.IPv4Address, - net.ParseIP("127.0.0.1").To4(), 8333, time.Now(), wire.SFNodeNetwork)) + ipv4Localhost := net.ParseIP("127.0.0.1").To4() + addr := wire.NewNetAddressV2(wire.IPv4Address, ipv4Localhost, 8333, + time.Now(), wire.SFNodeNetwork) + msg := wire.NewMsgAddrV2([]wire.NetAddressV2{addr}) return msg }(), pver: pver, @@ -570,31 +571,30 @@ func TestPeerListeners(t *testing.T) { listener: "OnCFilterV2", msg: wire.NewMsgCFilterV2(&chainhash.Hash{}, nil, 0, nil), pver: pver, - }, + }, { // only one version message is allowed // only one verack message is allowed - { - listener: "OnSendHeaders", - msg: wire.NewMsgSendHeaders(), - pver: pver, - }, { - listener: "OnGetInitState", - msg: wire.NewMsgGetInitState(), - pver: pver, - }, { - listener: "OnInitState", - msg: wire.NewMsgInitState(), - pver: pver, - }, { - listener: "OnGetCFiltersV2", - msg: wire.NewMsgGetCFsV2(&chainhash.Hash{}, &chainhash.Hash{}), - pver: pver, - }, { - listener: "OnCFiltersV2", - msg: wire.NewMsgCFiltersV2([]wire.MsgCFilterV2{}), - pver: pver, - }, - } + listener: "OnSendHeaders", + msg: wire.NewMsgSendHeaders(), + pver: pver, + }, { + listener: "OnGetInitState", + msg: wire.NewMsgGetInitState(), + pver: pver, + }, { + listener: "OnInitState", + msg: wire.NewMsgInitState(), + pver: pver, + }, { + listener: "OnGetCFiltersV2", + msg: wire.NewMsgGetCFsV2(&chainhash.Hash{}, &chainhash.Hash{}), + pver: pver, + }, { + listener: "OnCFiltersV2", + msg: wire.NewMsgCFiltersV2([]wire.MsgCFilterV2{}), + pver: pver, + }} + t.Logf("Running %d tests", len(tests)) for _, test := range tests { testPver := test.pver @@ -962,41 +962,39 @@ func TestPushAddrV2Msg(t *testing.T) { name string addrs []wire.NetAddressV2 wantSentLen int - }{ - { - name: "nil address list", - addrs: nil, - wantSentLen: 0, - }, { - name: "empty address list", - addrs: []wire.NetAddressV2{}, - wantSentLen: 0, - }, { - name: "single address", - addrs: []wire.NetAddressV2{addr}, - wantSentLen: 1, - }, { - name: "multiple addresses under limit", - addrs: func() []wire.NetAddressV2 { - addrs := make([]wire.NetAddressV2, 10) - for i := range addrs { - addrs[i] = addr - } - return addrs - }(), - wantSentLen: 10, - }, { - name: "addresses over MaxAddrPerV2Msg limit", - addrs: func() []wire.NetAddressV2 { - addrs := make([]wire.NetAddressV2, wire.MaxAddrPerV2Msg+100) - for i := range addrs { - addrs[i] = addr - } - return addrs - }(), - wantSentLen: wire.MaxAddrPerV2Msg, - }, - } + }{{ + name: "nil address list", + addrs: nil, + wantSentLen: 0, + }, { + name: "empty address list", + addrs: []wire.NetAddressV2{}, + wantSentLen: 0, + }, { + name: "single address", + addrs: []wire.NetAddressV2{addr}, + wantSentLen: 1, + }, { + name: "multiple addresses under limit", + addrs: func() []wire.NetAddressV2 { + addrs := make([]wire.NetAddressV2, 10) + for i := range addrs { + addrs[i] = addr + } + return addrs + }(), + wantSentLen: 10, + }, { + name: "addresses over MaxAddrPerV2Msg limit", + addrs: func() []wire.NetAddressV2 { + addrs := make([]wire.NetAddressV2, wire.MaxAddrPerV2Msg+100) + for i := range addrs { + addrs[i] = addr + } + return addrs + }(), + wantSentLen: wire.MaxAddrPerV2Msg, + }} // Create a mock connection. inConn, outConn := pipe( @@ -1017,13 +1015,9 @@ func TestPushAddrV2Msg(t *testing.T) { sent := peer.PushAddrV2Msg(test.addrs) // Check the number of addresses sent. - gotSentLen := 0 - if sent != nil { - gotSentLen = len(sent) - } - if gotSentLen != test.wantSentLen { - t.Errorf("%s: expected %d addresses sent, got %d", - test.name, test.wantSentLen, gotSentLen) + if got := len(sent); got != test.wantSentLen { + t.Errorf("%s: expected %d addresses sent, got %d", test.name, + test.wantSentLen, got) } } diff --git a/server.go b/server.go index 4bc0ad2ec..a354c5130 100644 --- a/server.go +++ b/server.go @@ -77,7 +77,7 @@ const ( connectionRetryInterval = time.Second * 5 // maxProtocolVersion is the max protocol version the server supports. - maxProtocolVersion = wire.TORv3Version + maxProtocolVersion = wire.AddrV2Version // These fields are used to track known addresses on a per-peer basis. // @@ -967,8 +967,8 @@ func wireToAddrmgrNetAddressType(addrType wire.NetAddressType) addrmgr.NetAddres return addrmgr.IPv4Address case wire.IPv6Address: return addrmgr.IPv6Address - case wire.TORv3Address: - return addrmgr.TORv3Address + case wire.TorV3Address: + return addrmgr.TorV3Address } return addrmgr.UnknownAddressType } @@ -981,8 +981,8 @@ func addrmgrToWireNetAddressType(addrType addrmgr.NetAddressType) wire.NetAddres return wire.IPv4Address case addrmgr.IPv6Address: return wire.IPv6Address - case addrmgr.TORv3Address: - return wire.TORv3Address + case addrmgr.TorV3Address: + return wire.TorV3Address } return wire.UnknownAddressType } @@ -1014,8 +1014,9 @@ func wireToAddrmgrNetAddressesV2(netAddrs []wire.NetAddressV2) ([]*addrmgr.NetAd for i := range netAddrs { wireAddr := &netAddrs[i] addrType := wireToAddrmgrNetAddressType(wireAddr.Type) - addr, err := addrmgr.NewNetAddressFromParams(addrType, wireAddr.IP, - wireAddr.Port, wireAddr.Timestamp, wireAddr.Services) + addr, err := addrmgr.NewNetAddressFromParams(addrType, + wireAddr.EncodedAddr, wireAddr.Port, wireAddr.Timestamp, + wireAddr.Services) if err != nil { return nil, err } @@ -1039,9 +1040,9 @@ func addrmgrToWireNetAddressV2(netAddr *addrmgr.NetAddress) wire.NetAddressV2 { netAddr.Timestamp, netAddr.Services) } -// pushAddrMsg sends an addr message to the connected peer using the provided -// addresses. -func (sp *serverPeer) pushAddrMsg(addresses []*addrmgr.NetAddress) { +// pushAddrV1Msg sends a legacy version 1 addr message to the connected peer +// using the provided addresses. +func (sp *serverPeer) pushAddrV1Msg(addresses []*addrmgr.NetAddress) { // Filter addresses already known to the peer. addrs := make([]*wire.NetAddress, 0, len(addresses)) for _, addr := range addresses { @@ -1061,6 +1062,36 @@ func (sp *serverPeer) pushAddrMsg(addresses []*addrmgr.NetAddress) { sp.addKnownAddresses(knownNetAddrs) } +// pushAddrV2Msg sends an addrv2 message to the connected peer using the +// provided addresses. +func (sp *serverPeer) pushAddrV2Msg(addresses []*addrmgr.NetAddress) { + // Filter addresses already known to the peer. + addrs := make([]wire.NetAddressV2, 0, len(addresses)) + for _, addr := range addresses { + if !sp.addressKnown(addr) { + wireNetAddr := addrmgrToWireNetAddressV2(addr) + addrs = append(addrs, wireNetAddr) + } + } + known := sp.PushAddrV2Msg(addrs) + knownNetAddrs, err := wireToAddrmgrNetAddressesV2(known) + if err != nil { + peerLog.Errorf("Failed to convert known addresses: %v", err) + return + } + sp.addKnownAddresses(knownNetAddrs) +} + +// pushAddrMsg sends an appropriate version address message to the connected +// peer using the provided addresses depending on the protocol version. +func (sp *serverPeer) pushAddrMsg(pver uint32, addresses []*addrmgr.NetAddress) { + if pver >= wire.AddrV2Version { + sp.pushAddrV2Msg(addresses) + return + } + sp.pushAddrV1Msg(addresses) +} + // addBanScore increases the persistent and decaying ban score fields by the // provided values unless banning is disabled. // @@ -1114,7 +1145,7 @@ func isSupportedNetAddrTypeV1(addrType addrmgr.NetAddressType) bool { // network address type is supported by the addrv2 wire message. func isSupportedNetAddressTypeV2(addrType addrmgr.NetAddressType) bool { switch addrType { - case addrmgr.IPv4Address, addrmgr.IPv6Address, addrmgr.TORv3Address: + case addrmgr.IPv4Address, addrmgr.IPv6Address, addrmgr.TorV3Address: return true } return false @@ -1124,32 +1155,12 @@ func isSupportedNetAddressTypeV2(addrType addrmgr.NetAddressType) bool { // protocol version. func natfSupported(pver uint32) addrmgr.NetAddressTypeFilter { switch { - case pver <= wire.AddrV2Version: + case pver < wire.AddrV2Version: return isSupportedNetAddrTypeV1 } return isSupportedNetAddressTypeV2 } -// pushAddrV2Msg sends an addrv2 message to the connected peer using the -// provided addresses. -func (sp *serverPeer) pushAddrV2Msg(addresses []*addrmgr.NetAddress) { - // Filter addresses already known to the peer. - addrs := make([]wire.NetAddressV2, 0, len(addresses)) - for _, addr := range addresses { - if !sp.addressKnown(addr) { - wireNetAddr := addrmgrToWireNetAddressV2(addr) - addrs = append(addrs, wireNetAddr) - } - } - known := sp.PushAddrV2Msg(addrs) - knownNetAddrs, err := wireToAddrmgrNetAddressesV2(known) - if err != nil { - peerLog.Errorf("Failed to convert known addresses: %v", err) - return - } - sp.addKnownAddresses(knownNetAddrs) -} - // NA returns the address manager network address for the peer. // // This method shadows the embedded peer.Peer.NA() method to provide the @@ -1165,7 +1176,7 @@ func (sp *serverPeer) NA() *addrmgr.NetAddress { return &addrmgr.NetAddress{ Type: wireToAddrmgrNetAddressType(wireNA.Type), - IP: wireNA.IP, + IP: wireNA.EncodedAddr, Port: wireNA.Port, Timestamp: wireNA.Timestamp, Services: wireNA.Services, @@ -1258,16 +1269,12 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { // known tip. if !cfg.DisableListen && sp.server.syncManager.IsCurrent() { // Get address that best matches. - msgProtocolVersion := uint32(msg.ProtocolVersion) - addrTypeFilter := natfSupported(msgProtocolVersion) + pver := uint32(msg.ProtocolVersion) + addrTypeFilter := natfSupported(pver) lna := addrManager.GetBestLocalAddress(remoteAddr, addrTypeFilter) if lna.IsRoutable() { addresses := []*addrmgr.NetAddress{lna} - if msgProtocolVersion >= wire.AddrV2Version { - sp.pushAddrV2Msg(addresses) - } else { - sp.pushAddrMsg(addresses) - } + sp.pushAddrMsg(pver, addresses) } else { srvrLog.Debugf("Local address %s is not routable and will not "+ "be broadcast to outbound peer %v", lna.Key(), sp.Addr()) @@ -1863,11 +1870,7 @@ func (sp *serverPeer) OnGetAddr(_ *peer.Peer, msg *wire.MsgGetAddr) { addrCache := sp.server.addrManager.AddressCache(addrTypeFilter) // Push addresses using version-appropriate message type. - if pver >= wire.AddrV2Version { - sp.pushAddrV2Msg(addrCache) - } else { - sp.pushAddrMsg(addrCache) - } + sp.pushAddrMsg(pver, addrCache) } // OnAddr is invoked when a peer receives an addr wire message and is used to @@ -4413,7 +4416,7 @@ func newServer(ctx context.Context, profiler *profileServer, switch addrType { case addrmgr.IPv4Address, addrmgr.IPv6Address: return true - case addrmgr.TORv3Address: + case addrmgr.TorV3Address: // Require .onion reachability. return !cfg.NoOnion && (cfg.Proxy != "" || cfg.OnionProxy != "") } @@ -4673,7 +4676,7 @@ func addrStringToNetAddr(addr string) (net.Addr, error) { // a DNS lookup should not be performed for the address. addrType, _ := addrmgr.EncodeHost(host) switch addrType { - case addrmgr.TORv3Address: + case addrmgr.TorV3Address: return &simpleAddr{ net: "tcp", addr: addr, diff --git a/server_test.go b/server_test.go index 36fd29044..ce0d644bd 100644 --- a/server_test.go +++ b/server_test.go @@ -32,7 +32,7 @@ func TestHostToNetAddress(t *testing.T) { wantErr bool want *addrmgr.NetAddress }{{ - name: "valid TORv3 address", + name: "valid TorV3 address", host: torv3Host, port: 9108, lookupFunc: nil, diff --git a/wire/common.go b/wire/common.go index 3fc667a78..4f9dd35ab 100644 --- a/wire/common.go +++ b/wire/common.go @@ -492,6 +492,13 @@ func writeElement(w io.Writer, element interface{}) error { } return nil + case *NetAddressType: + err := writeUint8(w, uint8(*e)) + if err != nil { + return err + } + return nil + case *uint16: err := writeUint16LE(w, *e) if err != nil { @@ -527,6 +534,13 @@ func writeElement(w io.Writer, element interface{}) error { } return nil + case *uint64Time: + err := writeUint64LE(w, uint64(time.Time(*e).Unix())) + if err != nil { + return err + } + return nil + case *bool: var err error if *e { diff --git a/wire/message_test.go b/wire/message_test.go index 43f55a2bc..58ad7bbe6 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2025 The Decred developers +// Copyright (c) 2015-2026 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -59,9 +59,9 @@ func TestMessage(t *testing.T) { msgVerack := NewMsgVerAck() msgGetAddr := NewMsgGetAddr() msgAddr := NewMsgAddr() - msgAddrV2 := NewMsgAddrV2() - msgAddrV2.AddAddress(NewNetAddressV2IPPort(net.ParseIP("127.0.0.1").To4(), - 8333, SFNodeNetwork)) + v2Addr := NewNetAddressV2IPPort(net.ParseIP("127.0.0.1").To4(), 8333, + SFNodeNetwork) + msgAddrV2 := NewMsgAddrV2([]NetAddressV2{v2Addr}) msgGetBlocks := NewMsgGetBlocks(&chainhash.Hash{}) msgBlock := &testBlock msgInv := NewMsgInv() diff --git a/wire/msgaddrv2.go b/wire/msgaddrv2.go index a30cc1b2e..cda7ec64c 100644 --- a/wire/msgaddrv2.go +++ b/wire/msgaddrv2.go @@ -1,4 +1,4 @@ -// Copyright (c) 2025 The Decred developers +// Copyright (c) 2025-2026 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -7,7 +7,6 @@ package wire import ( "fmt" "io" - "net" ) // MaxAddrPerV2Msg is the maximum number of addresses that can be in a single @@ -22,43 +21,11 @@ const MaxAddrPerV2Msg = 1000 // addresses. type MsgAddrV2 struct { // AddrList contains the addresses that will be sent to or have been - // received from a peer. Instead of manually appending addresses to this - // field directly, consumers should use the convenience functions on an - // instance of this message to add addresses. + // received from a peer. This MUST have a maximum of [MaxAddrPerV2Msg] + // entries or the message will error during encode and decode. AddrList []NetAddressV2 } -// AddAddress adds a known address to the message. If the maximum number of -// addresses has been reached, then an error is returned. -func (msg *MsgAddrV2) AddAddress(na NetAddressV2) error { - const op = "MsgAddrV2.AddAddress" - if len(msg.AddrList)+1 > MaxAddrPerV2Msg { - msg := fmt.Sprintf("too many addresses in message [max %v]", - MaxAddrPerV2Msg) - return messageError(op, ErrTooManyAddrs, msg) - } - - msg.AddrList = append(msg.AddrList, na) - return nil -} - -// AddAddresses adds multiple known addresses to the message. If the number of -// addresses exceeds the maximum allowed then an error is returned. -func (msg *MsgAddrV2) AddAddresses(netAddrs ...NetAddressV2) error { - for _, na := range netAddrs { - err := msg.AddAddress(na) - if err != nil { - return err - } - } - return nil -} - -// ClearAddresses removes all addresses from the message. -func (msg *MsgAddrV2) ClearAddresses() { - msg.AddrList = []NetAddressV2{} -} - // readNetAddressV2 reads an encoded version 2 wire network address from the // provided reader into the provided NetAddressV2. func readNetAddressV2(op string, r io.Reader, pver uint32, na *NetAddressV2) error { @@ -87,7 +54,7 @@ func readNetAddressV2(op string, r io.Reader, pver uint32, na *NetAddressV2) err if err != nil { return err } - na.IP = ip[:] + na.EncodedAddr = ip[:] case IPv6Address: var ip [16]byte @@ -95,20 +62,15 @@ func readNetAddressV2(op string, r io.Reader, pver uint32, na *NetAddressV2) err if err != nil { return err } - na.IP = ip[:] + na.EncodedAddr = ip[:] - case TORv3Address: - if pver < TORv3Version { - msg := fmt.Sprintf("TORv3 addresses require protocol version %d "+ - "or higher", TORv3Version) - return messageError(op, ErrMsgInvalidForPVer, msg) - } - var ip [32]byte - err := readElement(r, &ip) + case TorV3Address: + var addr [32]byte + err := readElement(r, &addr) if err != nil { return err } - na.IP = ip[:] + na.EncodedAddr = addr[:] default: msg := fmt.Sprintf("cannot decode unknown network address type %v", @@ -124,21 +86,21 @@ func readNetAddressV2(op string, r io.Reader, pver uint32, na *NetAddressV2) err return nil } -// writeNetAddressV2 serializes an address manager network address to the -// provided writer. -func writeNetAddressV2(op string, w io.Writer, pver uint32, na NetAddressV2) error { - err := writeElement(w, uint64(na.Timestamp.Unix())) +// writeNetAddressV2 serializes a version 2 network address to the provided +// writer. +func writeNetAddressV2(op string, w io.Writer, pver uint32, na *NetAddressV2) error { + err := writeElement(w, (*uint64Time)(&na.Timestamp)) if err != nil { return err } - err = writeElements(w, na.Services, na.Type) + err = writeElements(w, &na.Services, &na.Type) if err != nil { return err } - netAddrIP := na.IP - addrLen := len(netAddrIP) + encodedAddr := na.EncodedAddr + addrLen := len(encodedAddr) switch na.Type { case IPv4Address: @@ -146,41 +108,18 @@ func writeNetAddressV2(op string, w io.Writer, pver uint32, na NetAddressV2) err msg := fmt.Sprintf("invalid IPv4 address length: %d", addrLen) return messageError(op, ErrInvalidMsg, msg) } - var ip [4]byte - copy(ip[:], netAddrIP) - err = writeElement(w, ip) - if err != nil { - return err - } case IPv6Address: if addrLen != 16 { msg := fmt.Sprintf("invalid IPv6 address length: %d", addrLen) return messageError(op, ErrInvalidMsg, msg) } - var ip [16]byte - copy(ip[:], net.IP(netAddrIP).To16()) - err = writeElement(w, ip) - if err != nil { - return err - } - case TORv3Address: - if pver < TORv3Version { - msg := fmt.Sprintf("TORv3 addresses require protocol version %d "+ - "or higher", TORv3Version) - return messageError(op, ErrMsgInvalidForPVer, msg) - } - if len(netAddrIP) != 32 { - msg := fmt.Sprintf("invalid TORv3 address length: %d", len(netAddrIP)) + case TorV3Address: + if len(encodedAddr) != 32 { + msg := fmt.Sprintf("invalid TorV3 address length: %d", len(encodedAddr)) return messageError(op, ErrInvalidMsg, msg) } - var ip [32]byte - copy(ip[:], netAddrIP) - err = writeElement(w, ip) - if err != nil { - return err - } default: msg := fmt.Sprintf("cannot encode unknown network address type %v", @@ -188,7 +127,12 @@ func writeNetAddressV2(op string, w io.Writer, pver uint32, na NetAddressV2) err return messageError(op, ErrUnknownNetAddrType, msg) } - return writeElement(w, na.Port) + _, err = w.Write(encodedAddr) + if err != nil { + return err + } + + return writeElement(w, &na.Port) } // BtcDecode decodes r using the wire protocol encoding into the receiver. @@ -209,9 +153,10 @@ func (msg *MsgAddrV2) BtcDecode(r io.Reader, pver uint32) error { return err } + // Require at least one address per message. if count == 0 { - return messageError(op, ErrTooFewAddrs, - "no addresses for message [count 0, min 1]") + const msg = "no addresses for message [count 0, min 1]" + return messageError(op, ErrTooFewAddrs, msg) } // Limit to max addresses per message. @@ -243,25 +188,27 @@ func (msg *MsgAddrV2) BtcEncode(w io.Writer, pver uint32) error { return messageError(op, ErrMsgInvalidForPVer, msg) } + // Require at least one address per message. count := len(msg.AddrList) + if count == 0 { + const msg = "no addresses for message [count 0, min 1]" + return messageError(op, ErrTooFewAddrs, msg) + } + + // Limit to max addresses per message. if count > MaxAddrPerV2Msg { msg := fmt.Sprintf("too many addresses for message [count %v, max %v]", count, MaxAddrPerV2Msg) return messageError(op, ErrTooManyAddrs, msg) } - if count == 0 { - return messageError(op, ErrTooFewAddrs, - "no addresses for message [count 0, min 1]") - } - err := WriteVarInt(w, pver, uint64(count)) if err != nil { return err } - for _, na := range msg.AddrList { - err = writeNetAddressV2(op, w, pver, na) + for i := range msg.AddrList { + err = writeNetAddressV2(op, w, pver, &msg.AddrList[i]) if err != nil { return err } @@ -276,9 +223,9 @@ func (msg *MsgAddrV2) Command() string { return CmdAddrV2 } -// maxNetAddressPayloadV2 returns the max payload size for an address manager -// network address based on the protocol version. -func maxNetAddressPayloadV2(pver uint32) uint32 { +// maxNetAddressPayloadV2 returns the max payload size for a network address +// based on the protocol version. +func maxNetAddressPayloadV2() uint32 { const ( timestampSize = 8 servicesSize = 8 @@ -286,13 +233,9 @@ func maxNetAddressPayloadV2(pver uint32) uint32 { portSize = 2 ) - maxAddressSize := uint32(16) // IPv6 is 16 bytes - if pver >= TORv3Version { - maxAddressSize = 32 - } - - return timestampSize + servicesSize + addressTypeSize + - maxAddressSize + portSize + const maxAddressSize = 32 // TorV3 is a 32-byte pubkey + return timestampSize + servicesSize + addressTypeSize + maxAddressSize + + portSize } // MaxPayloadLength returns the maximum length the payload can be for the @@ -302,13 +245,15 @@ func (msg *MsgAddrV2) MaxPayloadLength(pver uint32) uint32 { return 0 } return uint32(VarIntSerializeSize(MaxAddrPerV2Msg)) + - (MaxAddrPerV2Msg * maxNetAddressPayloadV2(pver)) + (MaxAddrPerV2Msg * maxNetAddressPayloadV2()) } // NewMsgAddrV2 returns a new wire addrv2 message that conforms to the // Message interface. See MsgAddrV2 for details. -func NewMsgAddrV2() *MsgAddrV2 { - return &MsgAddrV2{ - AddrList: make([]NetAddressV2, 0, MaxAddrPerV2Msg), - } +// +// The provided slice is expected to have a minimum of one address and a maximum +// of [MaxAddrPerV2Msg]. The message will fail to decode and encode if it does +// not satisfy those requirements at the time of decoding and encoding. +func NewMsgAddrV2(addrs []NetAddressV2) *MsgAddrV2 { + return &MsgAddrV2{addrs} } diff --git a/wire/msgaddrv2_test.go b/wire/msgaddrv2_test.go index b342cf56c..664480426 100644 --- a/wire/msgaddrv2_test.go +++ b/wire/msgaddrv2_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2025 The Decred developers +// Copyright (c) 2025-2026 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -39,7 +39,7 @@ var ( ipv4NetAddress = newNetAddressV2(IPv4Address, ipv4IpBytes, 8333) ipv6NetAddress = newNetAddressV2(IPv6Address, ipv6IpBytes, 8333) - torv3NetAddress = newNetAddressV2(TORv3Address, torV3IpBytes, 8333) + torv3NetAddress = newNetAddressV2(TorV3Address, torV3IpBytes, 8333) serializedIPv4NetAddressBytes = []byte{ 0x29, 0xab, 0x5f, 0x49, 0x00, 0x00, 0x00, 0x00, // Timestamp @@ -60,17 +60,17 @@ var ( 0x29, 0xab, 0x5f, 0x49, 0x00, 0x00, 0x00, 0x00, // Timestamp 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Services 0x00, // Type (Unknown) - 0x7f, 0x00, 0x00, 0x01, // IP + 0x7f, 0x00, 0x00, 0x01, // EncodedAddr 0x8d, 0x20, // Port 8333 (little-endian) } - serializedTORv3NetAddressBytes = []byte{ + serializedTorV3NetAddressBytes = []byte{ 0x29, 0xab, 0x5f, 0x49, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, // Type (TORv3) - 0xb8, 0x39, 0x1d, 0x20, 0x03, 0xbb, 0x3b, 0xd2, // IP - 0x85, 0xb0, 0x35, 0xac, 0x8e, 0xb3, 0x0c, 0x80, // IP - 0xc4, 0xe2, 0xa2, 0x9b, 0xb7, 0xa2, 0xf0, 0xce, // IP - 0x0d, 0xf8, 0x74, 0x3c, 0x37, 0xec, 0x35, 0x93, // IP + 0x03, // Type (TorV3) + 0xb8, 0x39, 0x1d, 0x20, 0x03, 0xbb, 0x3b, 0xd2, // EncodedAddr + 0x85, 0xb0, 0x35, 0xac, 0x8e, 0xb3, 0x0c, 0x80, // EncodedAddr + 0xc4, 0xe2, 0xa2, 0x9b, 0xb7, 0xa2, 0xf0, 0xce, // EncodedAddr + 0x0d, 0xf8, 0x74, 0x3c, 0x37, 0xec, 0x35, 0x93, // EncodedAddr 0x8d, 0x20, // Port 8333 (little-endian) } ) @@ -90,7 +90,7 @@ func TestAddrV2MaxPayloadLength(t *testing.T) { }, { name: "protocol version 12", pver: AddrV2Version, - want: 35003, + want: 51003, }, { name: "latest protocol version", pver: ProtocolVersion, @@ -99,7 +99,7 @@ func TestAddrV2MaxPayloadLength(t *testing.T) { for _, test := range tests { // Ensure max payload is expected value for latest protocol version. - msg := NewMsgAddrV2() + msg := NewMsgAddrV2(nil) result := msg.MaxPayloadLength(test.pver) if result != test.want { t.Errorf("%s: wrong max payload length - got %v, want %d", @@ -122,45 +122,11 @@ func TestAddrV2MaxPayloadLength(t *testing.T) { func TestAddrV2(t *testing.T) { // Ensure the command is expected value. wantCmd := "addrv2" - msg := NewMsgAddrV2() + msg := NewMsgAddrV2(nil) if cmd := msg.Command(); cmd != wantCmd { t.Errorf("NewMsgAddrV2: wrong command - got %v want %v", cmd, wantCmd) } - - // Ensure NetAddresses are added properly. - err := msg.AddAddress(ipv4NetAddress) - if err != nil { - t.Errorf("AddAddress: %v", err) - } - if !reflect.DeepEqual(msg.AddrList[0], ipv4NetAddress) { - t.Errorf("AddAddress: wrong address added - got %v, want %v", - spew.Sprint(msg.AddrList[0]), spew.Sprint(ipv4NetAddress)) - } - - // Ensure the address list is cleared properly. - msg.ClearAddresses() - if len(msg.AddrList) != 0 { - t.Errorf("ClearAddresses: address list is not empty - "+ - "got %v [%v], want %v", len(msg.AddrList), - spew.Sprint(msg.AddrList[0]), 0) - } - - // Ensure adding more than the max allowed addresses per message returns - // error. - for i := 0; i < MaxAddrPerV2Msg+1; i++ { - err = msg.AddAddress(ipv4NetAddress) - } - if !errors.Is(err, ErrTooManyAddrs) { - t.Errorf("AddAddress: expected ErrTooManyAddrs, got %v", err) - } - - // Make sure adding multiple addresses also returns an error when the - // message is at max capacity. - err = msg.AddAddresses(ipv4NetAddress) - if !errors.Is(err, ErrTooManyAddrs) { - t.Errorf("AddAddresses: expected ErrTooManyAddrs, got %v", err) - } } // TestAddrV2Wire tests the MsgAddrV2 wire encode and decode for various @@ -179,7 +145,7 @@ func TestAddrV2Wire(t *testing.T) { wantBytes: bytes.Join([][]byte{ {0x01}, serializedIPv4NetAddressBytes, - }, []byte{}), + }, nil), }, { name: "latest protocol version with multiple addresses", addrs: []NetAddressV2{ @@ -191,8 +157,8 @@ func TestAddrV2Wire(t *testing.T) { {0x03}, serializedIPv4NetAddressBytes, serializedIPv6NetAddressBytes, - serializedTORv3NetAddressBytes, - }, []byte{}), + serializedTorV3NetAddressBytes, + }, nil), }, { name: "latest protocol version with maximum addresses", addrs: func() []NetAddressV2 { @@ -207,14 +173,13 @@ func TestAddrV2Wire(t *testing.T) { for i := 0; i < MaxAddrPerV2Msg; i++ { parts = append(parts, serializedIPv6NetAddressBytes) } - return bytes.Join(parts, []byte{}) + return bytes.Join(parts, nil) }(), }} t.Logf("Running %d tests", len(tests)) for i, test := range tests { - subject := NewMsgAddrV2() - subject.AddAddresses(test.addrs...) + subject := NewMsgAddrV2(test.addrs) // Encode the message to the wire format and ensure it serializes // correctly. @@ -263,7 +228,7 @@ func TestAddrV2BtcDecode(t *testing.T) { wireBytes: bytes.Join([][]byte{ {0x01}, serializedIPv4NetAddressBytes, - }, []byte{}), + }, nil), wantAddrs: nil, wantErr: ErrMsgInvalidForPVer, }, { @@ -310,20 +275,11 @@ func TestAddrV2BtcDecode(t *testing.T) { {0x04}, serializedIPv4NetAddressBytes, serializedIPv6NetAddressBytes, - serializedTORv3NetAddressBytes, + serializedTorV3NetAddressBytes, serializedUnknownNetAddressBytes, - }, []byte{}), + }, nil), wantAddrs: nil, wantErr: ErrUnknownNetAddrType, - }, { - name: "message with TORv3 address invalid on pver 12", - pver: AddrV2Version, - wireBytes: bytes.Join([][]byte{ - {0x01}, - serializedTORv3NetAddressBytes, - }, []byte{}), - wantAddrs: nil, - wantErr: ErrMsgInvalidForPVer, }, { name: "message with multiple valid addresses", pver: pver, @@ -331,8 +287,8 @@ func TestAddrV2BtcDecode(t *testing.T) { {0x03}, serializedIPv4NetAddressBytes, serializedIPv6NetAddressBytes, - serializedTORv3NetAddressBytes, - }, []byte{}), + serializedTorV3NetAddressBytes, + }, nil), wantAddrs: []NetAddressV2{ ipv4NetAddress, ipv6NetAddress, @@ -347,7 +303,8 @@ func TestAddrV2BtcDecode(t *testing.T) { err := msg.BtcDecode(rbuf, test.pver) if !errors.Is(err, test.wantErr) { - t.Errorf("%q: wrong error - got: %v, want: %v", test.name, err, test.wantErr) + t.Errorf("%q: wrong error - got: %v, want: %v", test.name, err, + test.wantErr) continue } @@ -373,11 +330,11 @@ func TestAddrV2BtcEncode(t *testing.T) { name: "addrv2 message invalid for pver 11", pver: AddrV2Version - 1, addrs: []NetAddressV2{{ - Timestamp: time.Unix(0x495fab29, 0), - Services: SFNodeNetwork, - Type: IPv4Address, - IP: ipv4IpBytes, - Port: 8333, + Timestamp: time.Unix(0x495fab29, 0), + Services: SFNodeNetwork, + Type: IPv4Address, + EncodedAddr: ipv4IpBytes, + Port: 8333, }}, wantErr: ErrMsgInvalidForPVer, }, { @@ -394,62 +351,50 @@ func TestAddrV2BtcEncode(t *testing.T) { name: "message with wrong size IPv4 address", pver: pver, addrs: []NetAddressV2{{ - Timestamp: time.Unix(0x495fab29, 0), - Services: SFNodeNetwork, - Type: IPv4Address, - IP: make([]byte, 1), - Port: 8333, + Timestamp: time.Unix(0x495fab29, 0), + Services: SFNodeNetwork, + Type: IPv4Address, + EncodedAddr: make([]byte, 1), + Port: 8333, }}, wantErr: ErrInvalidMsg, }, { name: "message with wrong size IPv6 address", pver: pver, addrs: []NetAddressV2{{ - Timestamp: time.Unix(0x495fab29, 0), - Services: SFNodeNetwork, - Type: IPv6Address, - IP: make([]byte, 1), - Port: 8333, + Timestamp: time.Unix(0x495fab29, 0), + Services: SFNodeNetwork, + Type: IPv6Address, + EncodedAddr: make([]byte, 1), + Port: 8333, }}, wantErr: ErrInvalidMsg, }, { - name: "message with wrong size TORv3 address", + name: "message with wrong size TorV3 address", pver: pver, addrs: []NetAddressV2{{ - Timestamp: time.Unix(0x495fab29, 0), - Services: SFNodeNetwork, - Type: TORv3Address, - IP: make([]byte, 1), - Port: 8333, + Timestamp: time.Unix(0x495fab29, 0), + Services: SFNodeNetwork, + Type: TorV3Address, + EncodedAddr: make([]byte, 1), + Port: 8333, }}, wantErr: ErrInvalidMsg, - }, { - name: "message with TORv3 address invalid on pver 12", - pver: AddrV2Version, - addrs: []NetAddressV2{{ - Timestamp: time.Unix(0x495fab29, 0), - Services: SFNodeNetwork, - Type: TORv3Address, - IP: torV3IpBytes, - Port: 8333, - }}, - wantErr: ErrMsgInvalidForPVer, }, { name: "message with unknown address type", pver: pver, addrs: []NetAddressV2{{ - Timestamp: time.Unix(0x495fab29, 0), - Services: SFNodeNetwork, - Type: UnknownAddressType, - IP: make([]byte, 1), - Port: 8333, + Timestamp: time.Unix(0x495fab29, 0), + Services: SFNodeNetwork, + Type: UnknownAddressType, + EncodedAddr: make([]byte, 1), + Port: 8333, }}, wantErr: ErrUnknownNetAddrType, }} for _, test := range tests { - msg := NewMsgAddrV2() - msg.AddrList = test.addrs + msg := NewMsgAddrV2(test.addrs) ioLimit := int(msg.MaxPayloadLength(test.pver)) // Encode to wire format. diff --git a/wire/netaddressv2.go b/wire/netaddressv2.go index 251d20e1f..ecbaffa93 100644 --- a/wire/netaddressv2.go +++ b/wire/netaddressv2.go @@ -1,4 +1,4 @@ -// Copyright (c) 2025 The Decred developers +// Copyright (c) 2025-2026 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -16,7 +16,7 @@ const ( UnknownAddressType NetAddressType = 0 IPv4Address NetAddressType = 1 IPv6Address NetAddressType = 2 - TORv3Address NetAddressType = 3 + TorV3Address NetAddressType = 3 ) // NetAddressV2 defines information about a peer on the network. @@ -32,24 +32,24 @@ type NetAddressV2 struct { // Type represents the type of network that the network address belongs to. Type NetAddressType - // IP address of the peer. It is defined as a byte array to support various - // address types that are not standard to the net package and therefore not - // entirely appropriate to store as a net.IP. - IP []byte + // EncodedAddr is the encoded network address. Its contents varies + // depending on the address type discriminator. + EncodedAddr []byte - // Port is the port of the remote peer. + // Port is the port of the remote peer. It will be 0 if a port does not + // apply for the specified address type discriminator. Port uint16 } -// NewNetAddressV2 creates a new network address using the provided -// parameters without validation. +// NewNetAddressV2 creates a new network address using the provided parameters +// without validation. func NewNetAddressV2(netAddressType NetAddressType, addrBytes []byte, port uint16, timestamp time.Time, services ServiceFlag) NetAddressV2 { return NetAddressV2{ - Timestamp: timestamp, - Services: services, - Type: netAddressType, - IP: addrBytes, - Port: port, + Timestamp: timestamp, + Services: services, + Type: netAddressType, + EncodedAddr: addrBytes, + Port: port, } } @@ -72,10 +72,10 @@ func NewNetAddressV2IPPort(ip net.IP, port uint16, services ServiceFlag) NetAddr // doesn't support better. timestamp := time.Unix(time.Now().Unix(), 0) return NetAddressV2{ - Timestamp: timestamp, - Services: services, - Type: addrType, - IP: addrBytes, - Port: port, + Timestamp: timestamp, + Services: services, + Type: addrType, + EncodedAddr: addrBytes, + Port: port, } } diff --git a/wire/protocol.go b/wire/protocol.go index ab779d913..0c02d6b68 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2025 The Decred developers +// Copyright (c) 2015-2026 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -17,7 +17,7 @@ const ( InitialProcotolVersion uint32 = 1 // ProtocolVersion is the latest protocol version this package supports. - ProtocolVersion uint32 = 13 + ProtocolVersion uint32 = 12 // NodeBloomVersion is the protocol version which added the SFNodeBloom // service flag (unused). @@ -61,10 +61,6 @@ const ( // AddrV2Version is the protocol version which adds the addrv2 message. AddrV2Version uint32 = 12 - - // TORv3Version is the protocol version which adds support for TORv3 - // network addresses to the addrv2 message. - TORv3Version uint32 = 13 ) // ServiceFlag identifies services supported by a Decred peer.