multi: update addrmgr, server to use NetAddressV2 instead of legacy

This commit is contained in:
eugene 2022-02-03 14:02:46 -05:00
parent 1ec4a1e77f
commit 201c0836ec
No known key found for this signature in database
GPG Key ID: 118759E83439A9B1
12 changed files with 382 additions and 196 deletions

View File

@ -70,7 +70,7 @@ type serializedAddrManager struct {
}
type localAddress struct {
na *wire.NetAddress
na *wire.NetAddressV2
score AddressPriority
}
@ -163,7 +163,7 @@ const (
// updateAddress is a helper function to either update an address already known
// to the address manager, or to add the address if not already known.
func (a *AddrManager) updateAddress(netAddr, srcAddr *wire.NetAddress) {
func (a *AddrManager) updateAddress(netAddr, srcAddr *wire.NetAddressV2) {
// Filter out non-routable addresses. Note that non-routable
// also includes invalid and local addresses.
if !IsRoutable(netAddr) {
@ -296,7 +296,7 @@ func (a *AddrManager) pickTried(bucket int) *list.Element {
return oldestElem
}
func (a *AddrManager) getNewBucket(netAddr, srcAddr *wire.NetAddress) int {
func (a *AddrManager) getNewBucket(netAddr, srcAddr *wire.NetAddressV2) int {
// bitcoind:
// doublesha256(key + sourcegroup + int64(doublesha256(key + group + sourcegroup))%bucket_per_source_group) % num_new_buckets
@ -318,7 +318,7 @@ func (a *AddrManager) getNewBucket(netAddr, srcAddr *wire.NetAddress) int {
return int(binary.LittleEndian.Uint64(hash2) % newBucketCount)
}
func (a *AddrManager) getTriedBucket(netAddr *wire.NetAddress) int {
func (a *AddrManager) getTriedBucket(netAddr *wire.NetAddressV2) int {
// bitcoind hashes this as:
// doublesha256(key + group + truncate_to_64bits(doublesha256(key)) % buckets_per_group) % num_buckets
data1 := []byte{}
@ -550,7 +550,7 @@ func (a *AddrManager) deserializePeers(filePath string) error {
// DeserializeNetAddress converts a given address string to a *wire.NetAddress.
func (a *AddrManager) DeserializeNetAddress(addr string,
services wire.ServiceFlag) (*wire.NetAddress, error) {
services wire.ServiceFlag) (*wire.NetAddressV2, error) {
host, portStr, err := net.SplitHostPort(addr)
if err != nil {
@ -599,7 +599,7 @@ func (a *AddrManager) Stop() error {
// AddAddresses adds new addresses to the address manager. It enforces a max
// number of addresses and silently ignores duplicate addresses. It is
// safe for concurrent access.
func (a *AddrManager) AddAddresses(addrs []*wire.NetAddress, srcAddr *wire.NetAddress) {
func (a *AddrManager) AddAddresses(addrs []*wire.NetAddressV2, srcAddr *wire.NetAddressV2) {
a.mtx.Lock()
defer a.mtx.Unlock()
@ -611,7 +611,7 @@ func (a *AddrManager) AddAddresses(addrs []*wire.NetAddress, srcAddr *wire.NetAd
// AddAddress adds a new address to the address manager. It enforces a max
// number of addresses and silently ignores duplicate addresses. It is
// safe for concurrent access.
func (a *AddrManager) AddAddress(addr, srcAddr *wire.NetAddress) {
func (a *AddrManager) AddAddress(addr, srcAddr *wire.NetAddressV2) {
a.mtx.Lock()
defer a.mtx.Unlock()
@ -635,7 +635,7 @@ func (a *AddrManager) AddAddressByIP(addrIP string) error {
if err != nil {
return fmt.Errorf("invalid port %s: %v", portStr, err)
}
na := wire.NewNetAddressIPPort(ip, uint16(port), 0)
na := wire.NetAddressV2FromBytes(time.Now(), 0, ip, uint16(port))
a.AddAddress(na, na) // XXX use correct src address
return nil
}
@ -664,7 +664,7 @@ func (a *AddrManager) NeedMoreAddresses() bool {
// AddressCache returns the current address cache. It must be treated as
// read-only (but since it is a copy now, this is not as dangerous).
func (a *AddrManager) AddressCache() []*wire.NetAddress {
func (a *AddrManager) AddressCache() []*wire.NetAddressV2 {
allAddr := a.getAddresses()
numAddresses := len(allAddr) * getAddrPercent / 100
@ -686,7 +686,7 @@ func (a *AddrManager) AddressCache() []*wire.NetAddress {
// getAddresses returns all of the addresses currently found within the
// manager's address cache.
func (a *AddrManager) getAddresses() []*wire.NetAddress {
func (a *AddrManager) getAddresses() []*wire.NetAddressV2 {
a.mtx.RLock()
defer a.mtx.RUnlock()
@ -695,7 +695,7 @@ func (a *AddrManager) getAddresses() []*wire.NetAddress {
return nil
}
addrs := make([]*wire.NetAddress, 0, addrIndexLen)
addrs := make([]*wire.NetAddressV2, 0, addrIndexLen)
for _, v := range a.addrIndex {
addrs = append(addrs, v.na)
}
@ -722,20 +722,43 @@ func (a *AddrManager) reset() {
// HostToNetAddress returns a netaddress given a host address. If the address
// is a Tor .onion address this will be taken care of. Else if the host is
// not an IP address it will be resolved (via Tor if required).
func (a *AddrManager) HostToNetAddress(host string, port uint16, services wire.ServiceFlag) (*wire.NetAddress, error) {
// Tor address is 16 char base32 + ".onion"
var ip net.IP
if len(host) == 22 && host[16:] == ".onion" {
func (a *AddrManager) HostToNetAddress(host string, port uint16,
services wire.ServiceFlag) (*wire.NetAddressV2, error) {
var (
na *wire.NetAddressV2
ip net.IP
)
// Tor v2 address is 16 char base32 + ".onion"
if len(host) == wire.TorV2EncodedSize && host[wire.TorV2EncodedSize-6:] == ".onion" {
// go base32 encoding uses capitals (as does the rfc
// but Tor and bitcoind tend to user lowercase, so we switch
// case here.
data, err := base32.StdEncoding.DecodeString(
strings.ToUpper(host[:16]))
strings.ToUpper(host[:wire.TorV2EncodedSize-6]))
if err != nil {
return nil, err
}
prefix := []byte{0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43}
ip = net.IP(append(prefix, data...))
na = wire.NetAddressV2FromBytes(
time.Now(), services, data, port,
)
} else if len(host) == wire.TorV3EncodedSize && host[wire.TorV3EncodedSize-6:] == ".onion" {
// Tor v3 addresses are 56 base32 characters with the 6 byte
// onion suffix.
data, err := base32.StdEncoding.DecodeString(
strings.ToUpper(host[:wire.TorV3EncodedSize-6]),
)
if err != nil {
return nil, err
}
// The first 32 bytes is the ed25519 public key and is enough
// to reconstruct the .onion address.
na = wire.NetAddressV2FromBytes(
time.Now(), services, data[:wire.TorV3Size], port,
)
} else if ip = net.ParseIP(host); ip == nil {
ips, err := a.lookupFunc(host)
if err != nil {
@ -745,30 +768,23 @@ func (a *AddrManager) HostToNetAddress(host string, port uint16, services wire.S
return nil, fmt.Errorf("no addresses found for %s", host)
}
ip = ips[0]
na = wire.NetAddressV2FromBytes(time.Now(), services, ip, port)
} else {
// This is an non-nil IP address that was parsed in the else if
// above.
na = wire.NetAddressV2FromBytes(time.Now(), services, ip, port)
}
return wire.NewNetAddressIPPort(ip, port, services), nil
}
// ipString returns a string for the ip from the provided NetAddress. If the
// ip is in the range used for Tor addresses then it will be transformed into
// the relevant .onion address.
func ipString(na *wire.NetAddress) string {
if IsOnionCatTor(na) {
// We know now that na.IP is long enough.
base32 := base32.StdEncoding.EncodeToString(na.IP[6:])
return strings.ToLower(base32) + ".onion"
}
return na.IP.String()
return na, nil
}
// NetAddressKey returns a string key in the form of ip:port for IPv4 addresses
// or [ip]:port for IPv6 addresses.
func NetAddressKey(na *wire.NetAddress) string {
// or [ip]:port for IPv6 addresses. It also handles onion v2 and v3 addresses.
func NetAddressKey(na *wire.NetAddressV2) string {
port := strconv.FormatUint(uint64(na.Port), 10)
return net.JoinHostPort(ipString(na), port)
return net.JoinHostPort(na.Addr.String(), port)
}
// GetAddress returns a single address that should be routable. It picks a
@ -842,13 +858,13 @@ func (a *AddrManager) GetAddress() *KnownAddress {
}
}
func (a *AddrManager) find(addr *wire.NetAddress) *KnownAddress {
func (a *AddrManager) find(addr *wire.NetAddressV2) *KnownAddress {
return a.addrIndex[NetAddressKey(addr)]
}
// Attempt increases the given address' attempt counter and updates
// the last attempt time.
func (a *AddrManager) Attempt(addr *wire.NetAddress) {
func (a *AddrManager) Attempt(addr *wire.NetAddressV2) {
a.mtx.Lock()
defer a.mtx.Unlock()
@ -869,7 +885,7 @@ func (a *AddrManager) Attempt(addr *wire.NetAddress) {
// Connected Marks the given address as currently connected and working at the
// current time. The address must already be known to AddrManager else it will
// be ignored.
func (a *AddrManager) Connected(addr *wire.NetAddress) {
func (a *AddrManager) Connected(addr *wire.NetAddressV2) {
a.mtx.Lock()
defer a.mtx.Unlock()
@ -894,7 +910,7 @@ func (a *AddrManager) Connected(addr *wire.NetAddress) {
// Good marks the given address as good. To be called after a successful
// connection and version exchange. If the address is unknown to the address
// manager it will be ignored.
func (a *AddrManager) Good(addr *wire.NetAddress) {
func (a *AddrManager) Good(addr *wire.NetAddressV2) {
a.mtx.Lock()
defer a.mtx.Unlock()
@ -983,7 +999,7 @@ func (a *AddrManager) Good(addr *wire.NetAddress) {
}
// SetServices sets the services for the giiven address to the provided value.
func (a *AddrManager) SetServices(addr *wire.NetAddress, services wire.ServiceFlag) {
func (a *AddrManager) SetServices(addr *wire.NetAddressV2, services wire.ServiceFlag) {
a.mtx.Lock()
defer a.mtx.Unlock()
@ -1005,9 +1021,11 @@ func (a *AddrManager) SetServices(addr *wire.NetAddress, services wire.ServiceFl
// AddLocalAddress adds na to the list of known local addresses to advertise
// with the given priority.
func (a *AddrManager) AddLocalAddress(na *wire.NetAddress, priority AddressPriority) error {
func (a *AddrManager) AddLocalAddress(na *wire.NetAddressV2, priority AddressPriority) error {
if !IsRoutable(na) {
return fmt.Errorf("address %s is not routable", na.IP)
return fmt.Errorf(
"address %s is not routable", na.Addr.String(),
)
}
a.lamtx.Lock()
@ -1030,7 +1048,7 @@ func (a *AddrManager) AddLocalAddress(na *wire.NetAddress, priority AddressPrior
// getReachabilityFrom returns the relative reachability of the provided local
// address to the provided remote address.
func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int {
func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddressV2) int {
const (
Unreachable = 0
Default = iota
@ -1045,36 +1063,66 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int {
return Unreachable
}
if IsOnionCatTor(remoteAddr) {
if IsOnionCatTor(localAddr) {
if remoteAddr.IsTorV3() {
if localAddr.IsTorV3() {
return Private
}
if IsRoutable(localAddr) && IsIPv4(localAddr) {
lna := localAddr.ToLegacy()
if IsOnionCatTor(lna) {
// Modern v3 clients should not be able to connect to
// deprecated v2 hidden services.
return Unreachable
}
if IsRoutable(localAddr) && IsIPv4(lna) {
return Ipv4
}
return Default
}
if IsRFC4380(remoteAddr) {
// We can't be sure if the remote party can actually connect to this
// address or not.
if localAddr.IsTorV3() {
return Default
}
// Convert the V2 addresses into legacy to access the network
// functions.
remoteLna := remoteAddr.ToLegacy()
localLna := localAddr.ToLegacy()
if IsOnionCatTor(remoteLna) {
if IsOnionCatTor(localLna) {
return Private
}
if IsRoutable(localAddr) && IsIPv4(localLna) {
return Ipv4
}
return Default
}
if IsRFC4380(remoteLna) {
if !IsRoutable(localAddr) {
return Default
}
if IsRFC4380(localAddr) {
if IsRFC4380(localLna) {
return Teredo
}
if IsIPv4(localAddr) {
if IsIPv4(localLna) {
return Ipv4
}
return Ipv6Weak
}
if IsIPv4(remoteAddr) {
if IsRoutable(localAddr) && IsIPv4(localAddr) {
if IsIPv4(remoteLna) {
if IsRoutable(localAddr) && IsIPv4(localLna) {
return Ipv4
}
return Unreachable
@ -1083,7 +1131,7 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int {
/* ipv6 */
var tunnelled bool
// Is our v6 is tunnelled?
if IsRFC3964(localAddr) || IsRFC6052(localAddr) || IsRFC6145(localAddr) {
if IsRFC3964(localLna) || IsRFC6052(localLna) || IsRFC6145(localLna) {
tunnelled = true
}
@ -1091,11 +1139,11 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int {
return Default
}
if IsRFC4380(localAddr) {
if IsRFC4380(localLna) {
return Teredo
}
if IsIPv4(localAddr) {
if IsIPv4(localLna) {
return Ipv4
}
@ -1109,13 +1157,13 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int {
// GetBestLocalAddress returns the most appropriate local address to use
// for the given remote address.
func (a *AddrManager) GetBestLocalAddress(remoteAddr *wire.NetAddress) *wire.NetAddress {
func (a *AddrManager) GetBestLocalAddress(remoteAddr *wire.NetAddressV2) *wire.NetAddressV2 {
a.lamtx.Lock()
defer a.lamtx.Unlock()
bestreach := 0
var bestscore AddressPriority
var bestAddress *wire.NetAddress
var bestAddress *wire.NetAddressV2
for _, la := range a.localAddresses {
reach := getReachabilityFrom(la.na, remoteAddr)
if reach > bestreach ||
@ -1126,21 +1174,29 @@ func (a *AddrManager) GetBestLocalAddress(remoteAddr *wire.NetAddress) *wire.Net
}
}
if bestAddress != nil {
log.Debugf("Suggesting address %s:%d for %s:%d", bestAddress.IP,
bestAddress.Port, remoteAddr.IP, remoteAddr.Port)
log.Debugf("Suggesting address %s:%d for %s:%d",
bestAddress.Addr.String(), bestAddress.Port,
remoteAddr.Addr.String(), remoteAddr.Port)
} else {
log.Debugf("No worthy address for %s:%d", remoteAddr.IP,
remoteAddr.Port)
log.Debugf("No worthy address for %s:%d",
remoteAddr.Addr.String(), remoteAddr.Port)
// Send something unroutable if nothing suitable.
var ip net.IP
if !IsIPv4(remoteAddr) && !IsOnionCatTor(remoteAddr) {
ip = net.IPv6zero
} else {
if remoteAddr.IsTorV3() {
ip = net.IPv4zero
} else {
remoteLna := remoteAddr.ToLegacy()
if !IsIPv4(remoteLna) && !IsOnionCatTor(remoteLna) {
ip = net.IPv6zero
} else {
ip = net.IPv4zero
}
}
services := wire.SFNodeNetwork | wire.SFNodeWitness | wire.SFNodeBloom
bestAddress = wire.NewNetAddressIPPort(ip, 0, services)
bestAddress = wire.NetAddressV2FromBytes(
time.Now(), services, ip, 0,
)
}
return bestAddress

View File

@ -6,12 +6,14 @@ import (
"net"
"os"
"testing"
"time"
"github.com/btcsuite/btcd/wire"
)
// randAddr generates a *wire.NetAddress backed by a random IPv4/IPv6 address.
func randAddr(t *testing.T) *wire.NetAddress {
// randAddr generates a *wire.NetAddressV2 backed by a random IPv4/IPv6
// address.
func randAddr(t *testing.T) *wire.NetAddressV2 {
t.Helper()
ipv4 := rand.Intn(2) == 0
@ -30,22 +32,26 @@ func randAddr(t *testing.T) *wire.NetAddress {
ip = b[:]
}
return &wire.NetAddress{
Services: wire.ServiceFlag(rand.Uint64()),
IP: ip,
Port: uint16(rand.Uint32()),
}
services := wire.ServiceFlag(rand.Uint64())
port := uint16(rand.Uint32())
return wire.NetAddressV2FromBytes(
time.Now(), services, ip, port,
)
}
// assertAddr ensures that the two addresses match. The timestamp is not
// checked as it does not affect uniquely identifying a specific address.
func assertAddr(t *testing.T, got, expected *wire.NetAddress) {
func assertAddr(t *testing.T, got, expected *wire.NetAddressV2) {
if got.Services != expected.Services {
t.Fatalf("expected address services %v, got %v",
expected.Services, got.Services)
}
if !got.IP.Equal(expected.IP) {
t.Fatalf("expected address IP %v, got %v", expected.IP, got.IP)
gotAddr := got.Addr.String()
expectedAddr := expected.Addr.String()
if gotAddr != expectedAddr {
t.Fatalf("expected address IP %v, got %v", expectedAddr,
gotAddr)
}
if got.Port != expected.Port {
t.Fatalf("expected address port %d, got %d", expected.Port,
@ -56,7 +62,7 @@ func assertAddr(t *testing.T, got, expected *wire.NetAddress) {
// assertAddrs ensures that the manager's address cache matches the given
// expected addresses.
func assertAddrs(t *testing.T, addrMgr *AddrManager,
expectedAddrs map[string]*wire.NetAddress) {
expectedAddrs map[string]*wire.NetAddressV2) {
t.Helper()
@ -96,7 +102,7 @@ func TestAddrManagerSerialization(t *testing.T) {
// We'll be adding 5 random addresses to the manager.
const numAddrs = 5
expectedAddrs := make(map[string]*wire.NetAddress, numAddrs)
expectedAddrs := make(map[string]*wire.NetAddressV2, numAddrs)
for i := 0; i < numAddrs; i++ {
addr := randAddr(t)
expectedAddrs[NetAddressKey(addr)] = addr
@ -141,7 +147,7 @@ func TestAddrManagerV1ToV2(t *testing.T) {
// each addresses' services will not be stored.
const numAddrs = 5
expectedAddrs := make(map[string]*wire.NetAddress, numAddrs)
expectedAddrs := make(map[string]*wire.NetAddressV2, numAddrs)
for i := 0; i < numAddrs; i++ {
addr := randAddr(t)
expectedAddrs[NetAddressKey(addr)] = addr

View File

@ -19,7 +19,7 @@ import (
// naTest is used to describe a test to be performed against the NetAddressKey
// method.
type naTest struct {
in wire.NetAddress
in wire.NetAddressV2
want string
}
@ -93,8 +93,10 @@ func addNaTests() {
func addNaTest(ip string, port uint16, want string) {
nip := net.ParseIP(ip)
na := *wire.NewNetAddressIPPort(nip, port, wire.SFNodeNetwork)
test := naTest{na, want}
na := wire.NetAddressV2FromBytes(
time.Now(), wire.SFNodeNetwork, nip, port,
)
test := naTest{*na, want}
naTests = append(naTests, test)
}
@ -157,37 +159,49 @@ func TestAddAddressByIP(t *testing.T) {
func TestAddLocalAddress(t *testing.T) {
var tests = []struct {
address wire.NetAddress
address wire.NetAddressV2
priority addrmgr.AddressPriority
valid bool
}{
{
wire.NetAddress{IP: net.ParseIP("192.168.0.100")},
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("192.168.0.100"), 0,
),
addrmgr.InterfacePrio,
false,
},
{
wire.NetAddress{IP: net.ParseIP("204.124.1.1")},
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("204.124.1.1"), 0,
),
addrmgr.InterfacePrio,
true,
},
{
wire.NetAddress{IP: net.ParseIP("204.124.1.1")},
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("204.124.1.1"), 0,
),
addrmgr.BoundPrio,
true,
},
{
wire.NetAddress{IP: net.ParseIP("::1")},
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("::1"), 0,
),
addrmgr.InterfacePrio,
false,
},
{
wire.NetAddress{IP: net.ParseIP("fe80::1")},
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("fe80::1"), 0,
),
addrmgr.InterfacePrio,
false,
},
{
wire.NetAddress{IP: net.ParseIP("2620:100::1")},
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("2620:100::1"), 0,
),
addrmgr.InterfacePrio,
true,
},
@ -197,12 +211,12 @@ func TestAddLocalAddress(t *testing.T) {
result := amgr.AddLocalAddress(&test.address, test.priority)
if result == nil && !test.valid {
t.Errorf("TestAddLocalAddress test #%d failed: %s should have "+
"been accepted", x, test.address.IP)
"been accepted", x, test.address.Addr.String())
continue
}
if result != nil && test.valid {
t.Errorf("TestAddLocalAddress test #%d failed: %s should not have "+
"been accepted", x, test.address.IP)
"been accepted", x, test.address.Addr.String())
continue
}
}
@ -257,7 +271,7 @@ func TestNeedMoreAddresses(t *testing.T) {
if !b {
t.Errorf("Expected that we need more addresses")
}
addrs := make([]*wire.NetAddress, addrsToAdd)
addrs := make([]*wire.NetAddressV2, addrsToAdd)
var err error
for i := 0; i < addrsToAdd; i++ {
@ -268,7 +282,9 @@ func TestNeedMoreAddresses(t *testing.T) {
}
}
srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
srcAddr := wire.NetAddressV2FromBytes(
time.Now(), 0, net.IPv4(173, 144, 173, 111), 8333,
)
n.AddAddresses(addrs, srcAddr)
numAddrs := n.NumAddresses()
@ -285,7 +301,7 @@ func TestNeedMoreAddresses(t *testing.T) {
func TestGood(t *testing.T) {
n := addrmgr.New("testgood", lookupFunc)
addrsToAdd := 64 * 64
addrs := make([]*wire.NetAddress, addrsToAdd)
addrs := make([]*wire.NetAddressV2, addrsToAdd)
var err error
for i := 0; i < addrsToAdd; i++ {
@ -296,7 +312,9 @@ func TestGood(t *testing.T) {
}
}
srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
srcAddr := wire.NetAddressV2FromBytes(
time.Now(), 0, net.IPv4(173, 144, 173, 111), 8333,
)
n.AddAddresses(addrs, srcAddr)
for _, addr := range addrs {
@ -331,8 +349,8 @@ func TestGetAddress(t *testing.T) {
if ka == nil {
t.Fatalf("Did not get an address where there is one in the pool")
}
if ka.NetAddress().IP.String() != someIP {
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP)
if ka.NetAddress().Addr.String() != someIP {
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().Addr.String(), someIP)
}
// Mark this as a good address and get it
@ -341,8 +359,8 @@ func TestGetAddress(t *testing.T) {
if ka == nil {
t.Fatalf("Did not get an address where there is one in the pool")
}
if ka.NetAddress().IP.String() != someIP {
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP)
if ka.NetAddress().Addr.String() != someIP {
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().Addr.String(), someIP)
}
numAddrs := n.NumAddresses()
@ -352,43 +370,83 @@ func TestGetAddress(t *testing.T) {
}
func TestGetBestLocalAddress(t *testing.T) {
localAddrs := []wire.NetAddress{
{IP: net.ParseIP("192.168.0.100")},
{IP: net.ParseIP("::1")},
{IP: net.ParseIP("fe80::1")},
{IP: net.ParseIP("2001:470::1")},
localAddrs := []wire.NetAddressV2{
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("192.168.0.100"), 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("::1"), 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("fe80::1"), 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("2001:470::1"), 0,
),
}
var tests = []struct {
remoteAddr wire.NetAddress
want0 wire.NetAddress
want1 wire.NetAddress
want2 wire.NetAddress
want3 wire.NetAddress
remoteAddr wire.NetAddressV2
want0 wire.NetAddressV2
want1 wire.NetAddressV2
want2 wire.NetAddressV2
want3 wire.NetAddressV2
}{
{
// Remote connection from public IPv4
wire.NetAddress{IP: net.ParseIP("204.124.8.1")},
wire.NetAddress{IP: net.IPv4zero},
wire.NetAddress{IP: net.IPv4zero},
wire.NetAddress{IP: net.ParseIP("204.124.8.100")},
wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")},
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("204.124.8.1"), 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.IPv4zero, 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.IPv4zero, 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("204.124.8.100"), 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0,
net.ParseIP("fd87:d87e:eb43:25::1"), 0,
),
},
{
// Remote connection from private IPv4
wire.NetAddress{IP: net.ParseIP("172.16.0.254")},
wire.NetAddress{IP: net.IPv4zero},
wire.NetAddress{IP: net.IPv4zero},
wire.NetAddress{IP: net.IPv4zero},
wire.NetAddress{IP: net.IPv4zero},
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("172.16.0.254"), 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.IPv4zero, 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.IPv4zero, 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.IPv4zero, 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.IPv4zero, 0,
),
},
{
// Remote connection from public IPv6
wire.NetAddress{IP: net.ParseIP("2602:100:abcd::102")},
wire.NetAddress{IP: net.IPv6zero},
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
*wire.NetAddressV2FromBytes(
time.Now(), 0,
net.ParseIP("2602:100:abcd::102"), 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.IPv6zero, 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("2001:470::1"), 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("2001:470::1"), 0,
),
*wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("2001:470::1"), 0,
),
},
/* XXX
{
@ -406,9 +464,12 @@ func TestGetBestLocalAddress(t *testing.T) {
// Test against default when there's no address
for x, test := range tests {
got := amgr.GetBestLocalAddress(&test.remoteAddr)
if !test.want0.IP.Equal(got.IP) {
wantAddr := test.want0.Addr.String()
gotAddr := got.Addr.String()
if wantAddr != gotAddr {
remoteAddr := test.remoteAddr.Addr.String()
t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s",
x, test.remoteAddr.IP, test.want1.IP, got.IP)
x, remoteAddr, wantAddr, gotAddr)
continue
}
}
@ -420,23 +481,31 @@ func TestGetBestLocalAddress(t *testing.T) {
// Test against want1
for x, test := range tests {
got := amgr.GetBestLocalAddress(&test.remoteAddr)
if !test.want1.IP.Equal(got.IP) {
wantAddr := test.want1.Addr.String()
gotAddr := got.Addr.String()
if wantAddr != gotAddr {
remoteAddr := test.remoteAddr.Addr.String()
t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s",
x, test.remoteAddr.IP, test.want1.IP, got.IP)
x, remoteAddr, wantAddr, gotAddr)
continue
}
}
// Add a public IP to the list of local addresses.
localAddr := wire.NetAddress{IP: net.ParseIP("204.124.8.100")}
amgr.AddLocalAddress(&localAddr, addrmgr.InterfacePrio)
localAddr := wire.NetAddressV2FromBytes(
time.Now(), 0, net.ParseIP("204.124.8.100"), 0,
)
amgr.AddLocalAddress(localAddr, addrmgr.InterfacePrio)
// Test against want2
for x, test := range tests {
got := amgr.GetBestLocalAddress(&test.remoteAddr)
if !test.want2.IP.Equal(got.IP) {
wantAddr := test.want2.Addr.String()
gotAddr := got.Addr.String()
if wantAddr != gotAddr {
remoteAddr := test.remoteAddr.Addr.String()
t.Errorf("TestGetBestLocalAddress test2 #%d failed for remote address %s: want %s got %s",
x, test.remoteAddr.IP, test.want2.IP, got.IP)
x, remoteAddr, wantAddr, gotAddr)
continue
}
}

View File

@ -18,7 +18,7 @@ func TstKnownAddressChance(ka *KnownAddress) float64 {
return ka.chance()
}
func TstNewKnownAddress(na *wire.NetAddress, attempts int,
func TstNewKnownAddress(na *wire.NetAddressV2, attempts int,
lastattempt, lastsuccess time.Time, tried bool, refs int) *KnownAddress {
return &KnownAddress{na: na, attempts: attempts, lastattempt: lastattempt,
lastsuccess: lastsuccess, tried: tried, refs: refs}

View File

@ -15,8 +15,8 @@ import (
// to determine how viable an address is.
type KnownAddress struct {
mtx sync.RWMutex // na and lastattempt
na *wire.NetAddress
srcAddr *wire.NetAddress
na *wire.NetAddressV2
srcAddr *wire.NetAddressV2
attempts int
lastattempt time.Time
lastsuccess time.Time
@ -24,9 +24,9 @@ type KnownAddress struct {
refs int // reference count of new buckets
}
// NetAddress returns the underlying wire.NetAddress associated with the
// NetAddress returns the underlying wire.NetAddressV2 associated with the
// known address.
func (ka *KnownAddress) NetAddress() *wire.NetAddress {
func (ka *KnownAddress) NetAddress() *wire.NetAddressV2 {
ka.mtx.RLock()
defer ka.mtx.RUnlock()
return ka.na

View File

@ -21,27 +21,27 @@ func TestChance(t *testing.T) {
}{
{
//Test normal case
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)},
0, time.Now().Add(-30*time.Minute), time.Now(), false, 0),
1.0,
}, {
//Test case in which lastseen < 0
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(20 * time.Second)},
addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(20 * time.Second)},
0, time.Now().Add(-30*time.Minute), time.Now(), false, 0),
1.0,
}, {
//Test case in which lastattempt < 0
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)},
0, time.Now().Add(30*time.Minute), time.Now(), false, 0),
1.0 * .01,
}, {
//Test case in which lastattempt < ten minutes
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)},
0, time.Now().Add(-5*time.Minute), time.Now(), false, 0),
1.0 * .01,
}, {
//Test case with several failed attempts.
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)},
2, time.Now().Add(-30*time.Minute), time.Now(), false, 0),
1 / 1.5 / 1.5,
},
@ -65,10 +65,10 @@ func TestIsBad(t *testing.T) {
hoursOld := now.Add(-5 * time.Hour)
zeroTime := time.Time{}
futureNa := &wire.NetAddress{Timestamp: future}
minutesOldNa := &wire.NetAddress{Timestamp: minutesOld}
monthOldNa := &wire.NetAddress{Timestamp: monthOld}
currentNa := &wire.NetAddress{Timestamp: secondsOld}
futureNa := &wire.NetAddressV2{Timestamp: future}
minutesOldNa := &wire.NetAddressV2{Timestamp: minutesOld}
monthOldNa := &wire.NetAddressV2{Timestamp: monthOld}
currentNa := &wire.NetAddressV2{Timestamp: secondsOld}
//Test addresses that have been tried in the last minute.
if addrmgr.TstKnownAddressIsBad(addrmgr.TstNewKnownAddress(futureNa, 3, secondsOld, zeroTime, false, 0)) {

View File

@ -222,11 +222,20 @@ func IsValid(na *wire.NetAddress) bool {
// IsRoutable returns whether or not the passed address is routable over
// the public internet. This is true as long as the address is valid and is not
// in any reserved ranges.
func IsRoutable(na *wire.NetAddress) bool {
return IsValid(na) && !(IsRFC1918(na) || IsRFC2544(na) ||
IsRFC3927(na) || IsRFC4862(na) || IsRFC3849(na) ||
IsRFC4843(na) || IsRFC5737(na) || IsRFC6598(na) ||
IsLocal(na) || (IsRFC4193(na) && !IsOnionCatTor(na)))
func IsRoutable(na *wire.NetAddressV2) bool {
if na.IsTorV3() {
// na is a torv3 address, return true.
return true
}
// Else na can be represented as a legacy NetAddress since i2p and
// cjdns are unsupported.
lna := na.ToLegacy()
return IsValid(lna) && !(IsRFC1918(lna) || IsRFC2544(lna) ||
IsRFC3927(lna) || IsRFC4862(lna) || IsRFC3849(lna) ||
IsRFC4843(lna) || IsRFC5737(lna) || IsRFC6598(lna) ||
IsLocal(lna) || (IsRFC4193(lna) &&
!IsOnionCatTor(lna)))
}
// GroupKey returns a string representing the network group an address is part
@ -234,48 +243,56 @@ func IsRoutable(na *wire.NetAddress) bool {
// "local" for a local address, the string "tor:key" where key is the /4 of the
// onion address for Tor address, and the string "unroutable" for an unroutable
// address.
func GroupKey(na *wire.NetAddress) string {
if IsLocal(na) {
func GroupKey(na *wire.NetAddressV2) string {
if na.IsTorV3() {
// na is a torv3 address. Use the same network group keying as
// for torv2.
return fmt.Sprintf("tor:%d", na.TorV3Key()&((1<<4)-1))
}
lna := na.ToLegacy()
if IsLocal(lna) {
return "local"
}
if !IsRoutable(na) {
return "unroutable"
}
if IsIPv4(na) {
return na.IP.Mask(net.CIDRMask(16, 32)).String()
if IsIPv4(lna) {
return lna.IP.Mask(net.CIDRMask(16, 32)).String()
}
if IsRFC6145(na) || IsRFC6052(na) {
if IsRFC6145(lna) || IsRFC6052(lna) {
// last four bytes are the ip address
ip := na.IP[12:16]
ip := lna.IP[12:16]
return ip.Mask(net.CIDRMask(16, 32)).String()
}
if IsRFC3964(na) {
ip := na.IP[2:6]
if IsRFC3964(lna) {
ip := lna.IP[2:6]
return ip.Mask(net.CIDRMask(16, 32)).String()
}
if IsRFC4380(na) {
if IsRFC4380(lna) {
// teredo tunnels have the last 4 bytes as the v4 address XOR
// 0xff.
ip := net.IP(make([]byte, 4))
for i, byte := range na.IP[12:16] {
for i, byte := range lna.IP[12:16] {
ip[i] = byte ^ 0xff
}
return ip.Mask(net.CIDRMask(16, 32)).String()
}
if IsOnionCatTor(na) {
if IsOnionCatTor(lna) {
// group is keyed off the first 4 bits of the actual onion key.
return fmt.Sprintf("tor:%d", na.IP[6]&((1<<4)-1))
return fmt.Sprintf("tor:%d", lna.IP[6]&((1<<4)-1))
}
// OK, so now we know ourselves to be a IPv6 address.
// bitcoind uses /32 for everything, except for Hurricane Electric's
// (he.net) IP range, which it uses /36 for.
bits := 32
if heNet.Contains(na.IP) {
if heNet.Contains(lna.IP) {
bits = 36
}
return na.IP.Mask(net.CIDRMask(bits, 128)).String()
return lna.IP.Mask(net.CIDRMask(bits, 128)).String()
}

View File

@ -7,6 +7,7 @@ package addrmgr_test
import (
"net"
"testing"
"time"
"github.com/btcsuite/btcd/addrmgr"
"github.com/btcsuite/btcd/wire"
@ -136,7 +137,10 @@ func TestIPTypes(t *testing.T) {
t.Errorf("IsValid %s\n got: %v want: %v", test.in.IP, rv, test.valid)
}
if rv := addrmgr.IsRoutable(&test.in); rv != test.routable {
currentNa := wire.NetAddressV2FromBytes(
time.Now(), test.in.Services, test.in.IP, test.in.Port,
)
if rv := addrmgr.IsRoutable(currentNa); rv != test.routable {
t.Errorf("IsRoutable %s\n got: %v want: %v", test.in.IP, rv, test.routable)
}
}
@ -192,8 +196,10 @@ func TestGroupKey(t *testing.T) {
for i, test := range tests {
nip := net.ParseIP(test.ip)
na := *wire.NewNetAddressIPPort(nip, 8333, wire.SFNodeNetwork)
if key := addrmgr.GroupKey(&na); key != test.expected {
na := wire.NetAddressV2FromBytes(
time.Now(), wire.SFNodeNetwork, nip, 8333,
)
if key := addrmgr.GroupKey(na); key != test.expected {
t.Errorf("TestGroupKey #%d (%s): unexpected group key "+
"- got '%s', want '%s'", i, test.name,
key, test.expected)

View File

@ -24,7 +24,7 @@ const (
// OnSeed is the signature of the callback function which is invoked when DNS
// seeding is succesfull.
type OnSeed func(addrs []*wire.NetAddress)
type OnSeed func(addrs []*wire.NetAddressV2)
// LookupFunc is the signature of the DNS lookup function.
type LookupFunc func(string) ([]net.IP, error)
@ -56,11 +56,11 @@ func SeedFromDNS(chainParams *chaincfg.Params, reqServices wire.ServiceFlag,
if numPeers == 0 {
return
}
addresses := make([]*wire.NetAddress, len(seedpeers))
addresses := make([]*wire.NetAddressV2, len(seedpeers))
// if this errors then we have *real* problems
intPort, _ := strconv.Atoi(chainParams.DefaultPort)
for i, peer := range seedpeers {
addresses[i] = wire.NewNetAddressTimestamp(
addresses[i] = wire.NetAddressV2FromBytes(
// bitcoind seeds with addresses from
// a time randomly selected between 3
// and 7 days ago.

View File

@ -228,7 +228,7 @@ func (cm *rpcConnManager) RelayTransactions(txns []*mempool.TxDesc) {
//
// This function is safe for concurrent access and is part of the
// rpcserverConnManager interface implementation.
func (cm *rpcConnManager) NodeAddresses() []*wire.NetAddress {
func (cm *rpcConnManager) NodeAddresses() []*wire.NetAddressV2 {
return cm.server.addrManager.AddressCache()
}

View File

@ -2518,7 +2518,7 @@ func handleGetNodeAddresses(s *rpcServer, cmd interface{}, closeChan <-chan stru
address := &btcjson.GetNodeAddressesResult{
Time: node.Timestamp.Unix(),
Services: uint64(node.Services),
Address: node.IP.String(),
Address: node.Addr.String(),
Port: node.Port,
}
addresses = append(addresses, address)
@ -4524,7 +4524,7 @@ type rpcserverConnManager interface {
// NodeAddresses returns an array consisting node addresses which can
// potentially be used to find new nodes in the network.
NodeAddresses() []*wire.NetAddress
NodeAddresses() []*wire.NetAddressV2
}
// rpcserverSyncManager represents a sync manager for use with the RPC server.

View File

@ -25,6 +25,8 @@ import (
"github.com/btcsuite/btcd/addrmgr"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/blockchain/indexers"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/btcutil/bloom"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/connmgr"
@ -36,8 +38,7 @@ import (
"github.com/btcsuite/btcd/peer"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/btcutil/bloom"
"github.com/decred/dcrd/lru"
)
const (
@ -274,7 +275,7 @@ type serverPeer struct {
isWhitelisted bool
filter *bloom.Filter
addressesMtx sync.RWMutex
knownAddresses map[string]struct{}
knownAddresses lru.Cache
banScore connmgr.DynamicBanScore
quit chan struct{}
// The following chans are used to sync blockmanager and server.
@ -289,7 +290,7 @@ func newServerPeer(s *server, isPersistent bool) *serverPeer {
server: s,
persistent: isPersistent,
filter: bloom.LoadFilter(nil),
knownAddresses: make(map[string]struct{}),
knownAddresses: lru.NewCache(5000),
quit: make(chan struct{}),
txProcessed: make(chan struct{}, 1),
blockProcessed: make(chan struct{}, 1),
@ -305,18 +306,18 @@ func (sp *serverPeer) newestBlock() (*chainhash.Hash, int32, error) {
// addKnownAddresses adds the given addresses to the set of known addresses to
// the peer to prevent sending duplicate addresses.
func (sp *serverPeer) addKnownAddresses(addresses []*wire.NetAddress) {
func (sp *serverPeer) addKnownAddresses(addresses []*wire.NetAddressV2) {
sp.addressesMtx.Lock()
for _, na := range addresses {
sp.knownAddresses[addrmgr.NetAddressKey(na)] = struct{}{}
sp.knownAddresses.Add(addrmgr.NetAddressKey(na))
}
sp.addressesMtx.Unlock()
}
// addressKnown true if the given address is already known to the peer.
func (sp *serverPeer) addressKnown(na *wire.NetAddress) bool {
func (sp *serverPeer) addressKnown(na *wire.NetAddressV2) bool {
sp.addressesMtx.RLock()
_, exists := sp.knownAddresses[addrmgr.NetAddressKey(na)]
exists := sp.knownAddresses.Contains(addrmgr.NetAddressKey(na))
sp.addressesMtx.RUnlock()
return exists
}
@ -340,23 +341,45 @@ func (sp *serverPeer) relayTxDisabled() bool {
return isDisabled
}
// pushAddrMsg sends an addr message to the connected peer using the provided
// addresses.
func (sp *serverPeer) pushAddrMsg(addresses []*wire.NetAddress) {
// Filter addresses already known to the peer.
// pushAddrMsg sends a legacy addr message to the connected peer using the
// provided addresses.
func (sp *serverPeer) pushAddrMsg(addresses []*wire.NetAddressV2) {
addrs := make([]*wire.NetAddress, 0, len(addresses))
for _, addr := range addresses {
if !sp.addressKnown(addr) {
addrs = append(addrs, addr)
// Filter addresses already known to the peer.
if sp.addressKnown(addr) {
continue
}
// Must skip the V3 addresses for legacy ADDR messages.
if addr.IsTorV3() {
continue
}
// Convert the NetAddressV2 to a legacy address.
addrs = append(addrs, addr.ToLegacy())
}
known, err := sp.PushAddrMsg(addrs)
if err != nil {
peerLog.Errorf("Can't push address message to %s: %v", sp.Peer, err)
peerLog.Errorf(
"Can't push address message to %s: %v", sp.Peer, err,
)
sp.Disconnect()
return
}
sp.addKnownAddresses(known)
// Convert all of the known addresses to NetAddressV2 to add them to
// the set of known addresses.
knownAddrs := make([]*wire.NetAddressV2, 0, len(known))
for _, knownAddr := range known {
currentKna := wire.NetAddressV2FromBytes(
knownAddr.Timestamp, knownAddr.Services,
knownAddr.IP, knownAddr.Port,
)
knownAddrs = append(knownAddrs, currentKna)
}
sp.addKnownAddresses(knownAddrs)
}
// addBanScore increases the persistent and decaying ban score fields by the
@ -1272,6 +1295,7 @@ func (sp *serverPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) {
return
}
addrs := make([]*wire.NetAddressV2, 0, len(msg.AddrList))
for _, na := range msg.AddrList {
// Don't add more address if we're disconnecting.
if !sp.Connected() {
@ -1286,8 +1310,14 @@ func (sp *serverPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) {
na.Timestamp = now.Add(-1 * time.Hour * 24 * 5)
}
// Add address to known addresses for this peer.
sp.addKnownAddresses([]*wire.NetAddress{na})
// Add address to known addresses for this peer. This is
// converted to NetAddressV2 since that's what the address
// manager uses.
currentNa := wire.NetAddressV2FromBytes(
na.Timestamp, na.Services, na.IP, na.Port,
)
addrs = append(addrs, currentNa)
sp.addKnownAddresses([]*wire.NetAddressV2{currentNa})
}
// Add addresses to server address manager. The address manager handles
@ -1295,7 +1325,7 @@ func (sp *serverPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) {
// addresses, and last seen updates.
// XXX bitcoind gives a 2 hour time penalty here, do we want to do the
// same?
sp.server.addrManager.AddAddresses(msg.AddrList, sp.NA())
sp.server.addrManager.AddAddresses(addrs, sp.NA())
}
// OnRead is invoked when a peer receives a message and it is used to update
@ -1700,7 +1730,7 @@ func (s *server) handleAddPeerMsg(state *peerState, sp *serverPeer) bool {
lna := s.addrManager.GetBestLocalAddress(sp.NA())
if addrmgr.IsRoutable(lna) {
// Filter addresses the peer already knows about.
addresses := []*wire.NetAddress{lna}
addresses := []*wire.NetAddressV2{lna}
sp.pushAddrMsg(addresses)
}
}
@ -2152,7 +2182,7 @@ func (s *server) peerHandler() {
if !cfg.DisableDNSSeed {
// Add peers discovered through DNS to the address manager.
connmgr.SeedFromDNS(activeNetParams.Params, defaultRequiredServices,
btcdLookup, func(addrs []*wire.NetAddress) {
btcdLookup, func(addrs []*wire.NetAddressV2) {
// Bitcoind uses a lookup of the dns seeder here. This
// is rather strange since the values looked up by the
// DNS seed lookups will vary quite a lot.
@ -2543,8 +2573,8 @@ out:
srvrLog.Warnf("UPnP can't get external address: %v", err)
continue out
}
na := wire.NewNetAddressIPPort(externalip, uint16(listenPort),
s.services)
na := wire.NetAddressV2FromBytes(time.Now(), s.services,
externalip, uint16(listenPort))
err = s.addrManager.AddLocalAddress(na, addrmgr.UpnpPrio)
if err != nil {
// XXX DeletePortMapping?
@ -3117,7 +3147,9 @@ func addLocalAddress(addrMgr *addrmgr.AddrManager, addr string, services wire.Se
continue
}
netAddr := wire.NewNetAddressIPPort(ifaceIP, uint16(port), services)
netAddr := wire.NetAddressV2FromBytes(
time.Now(), services, ifaceIP, uint16(port),
)
addrMgr.AddLocalAddress(netAddr, addrmgr.BoundPrio)
}
} else {