Files
go-libp2p/p2p/host/basic/addrs_manager_test.go
sukun fb1d9512e8 basichost: use autonatv2 to verify reachability (#3231)
This introduces addrsReachabilityTracker that tracks reachability on
a set of addresses. It probes reachability for addresses periodically
and has an exponential backoff in case there are too many errors
or we don't have any valid autonatv2 peer.

There's no smartness in the address selection logic currently. We just
test all provided addresses. It also doesn't use the addresses provided
by `AddrsFactory`, so currently there's no way to get a user provided
address tested for reachability, something that would be a problem for
dns addresses. I intend to introduce an alternative to
`AddrsFactory`, something like, `AnnounceAddrs(addrs []ma.Multiaddr)`
that's just appended to the set of addresses that we have, and check
reachability for those addresses.

There's only one method exposed in the BasicHost right now that's
`ReachableAddrs() []ma.Multiadd`r that returns the host's reachable
addrs. Users can also use the event `EvtHostReachableAddrsChanged`
to be notified when any addrs reachability changes.
2025-06-03 17:13:56 +05:30

530 lines
18 KiB
Go

package basichost
import (
"context"
"errors"
"fmt"
"slices"
"testing"
"time"
"github.com/libp2p/go-libp2p/core/event"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
"github.com/libp2p/go-libp2p/p2p/protocol/autonatv2"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAppendNATAddrs(t *testing.T) {
if1, if2 := ma.StringCast("/ip4/192.168.0.100"), ma.StringCast("/ip4/1.1.1.1")
ifaceAddrs := []ma.Multiaddr{if1, if2}
tcpListenAddr, udpListenAddr := ma.StringCast("/ip4/0.0.0.0/tcp/1"), ma.StringCast("/ip4/0.0.0.0/udp/2/quic-v1")
cases := []struct {
Name string
Listen ma.Multiaddr
Nat ma.Multiaddr
ObsAddrFunc func(ma.Multiaddr) []ma.Multiaddr
Expected []ma.Multiaddr
}{
{
Name: "nat map success",
// nat mapping success, obsaddress ignored
Listen: ma.StringCast("/ip4/0.0.0.0/udp/1/quic-v1"),
Nat: ma.StringCast("/ip4/1.1.1.1/udp/10/quic-v1"),
ObsAddrFunc: func(_ ma.Multiaddr) []ma.Multiaddr {
return []ma.Multiaddr{ma.StringCast("/ip4/2.2.2.2/udp/100/quic-v1")}
},
Expected: []ma.Multiaddr{ma.StringCast("/ip4/1.1.1.1/udp/10/quic-v1")},
},
{
Name: "nat map failure",
// nat mapping fails, obs addresses added
Listen: ma.StringCast("/ip4/0.0.0.0/tcp/1"),
Nat: nil,
ObsAddrFunc: func(a ma.Multiaddr) []ma.Multiaddr {
ipC, _ := ma.SplitFirst(a)
ip := ipC.Multiaddr()
switch {
case ip.Equal(if1):
return []ma.Multiaddr{ma.StringCast("/ip4/2.2.2.2/tcp/100")}
case ip.Equal(if2):
return []ma.Multiaddr{ma.StringCast("/ip4/3.3.3.3/tcp/100")}
default:
return []ma.Multiaddr{}
}
},
Expected: []ma.Multiaddr{ma.StringCast("/ip4/2.2.2.2/tcp/100"), ma.StringCast("/ip4/3.3.3.3/tcp/100")},
},
{
Name: "if addrs ignored if not listening on unspecified",
// nat mapping fails, obs addresses added
Listen: ma.StringCast("/ip4/192.168.1.1/tcp/1"),
Nat: nil,
ObsAddrFunc: func(a ma.Multiaddr) []ma.Multiaddr {
ipC, _ := ma.SplitFirst(a)
ip := ipC.Multiaddr()
switch {
case ip.Equal(if1):
return []ma.Multiaddr{ma.StringCast("/ip4/2.2.2.2/tcp/100")}
case ip.Equal(if2):
return []ma.Multiaddr{ma.StringCast("/ip4/3.3.3.3/tcp/100")}
case ip.Equal(ma.StringCast("/ip4/192.168.1.1")):
return []ma.Multiaddr{ma.StringCast("/ip4/4.4.4.4/tcp/100")}
default:
return []ma.Multiaddr{}
}
},
Expected: []ma.Multiaddr{ma.StringCast("/ip4/4.4.4.4/tcp/100")},
},
{
Name: "nat map success but CGNAT",
// nat addr added, obs address added with nat provided port
Listen: tcpListenAddr,
Nat: ma.StringCast("/ip4/100.100.1.1/tcp/100"),
ObsAddrFunc: func(a ma.Multiaddr) []ma.Multiaddr {
ipC, _ := ma.SplitFirst(a)
ip := ipC.Multiaddr()
if ip.Equal(if1) {
return []ma.Multiaddr{ma.StringCast("/ip4/2.2.2.2/tcp/20")}
}
return []ma.Multiaddr{ma.StringCast("/ip4/3.3.3.3/tcp/30")}
},
Expected: []ma.Multiaddr{
ma.StringCast("/ip4/100.100.1.1/tcp/100"),
ma.StringCast("/ip4/2.2.2.2/tcp/20"),
ma.StringCast("/ip4/3.3.3.3/tcp/30"),
},
},
{
Name: "uses unspecified address for obs address",
// observed address manager should be queries with both specified and unspecified addresses
// udp observed addresses are mapped to unspecified addresses
Listen: udpListenAddr,
Nat: nil,
ObsAddrFunc: func(a ma.Multiaddr) []ma.Multiaddr {
if manet.IsIPUnspecified(a) {
return []ma.Multiaddr{ma.StringCast("/ip4/3.3.3.3/udp/20/quic-v1")}
}
return []ma.Multiaddr{ma.StringCast("/ip4/2.2.2.2/udp/20/quic-v1")}
},
Expected: []ma.Multiaddr{
ma.StringCast("/ip4/2.2.2.2/udp/20/quic-v1"),
ma.StringCast("/ip4/3.3.3.3/udp/20/quic-v1"),
},
},
}
for _, tc := range cases {
t.Run(tc.Name, func(t *testing.T) {
as := &addrsManager{
natManager: &mockNatManager{
GetMappingFunc: func(_ ma.Multiaddr) ma.Multiaddr {
return tc.Nat
},
},
observedAddrsManager: &mockObservedAddrs{
ObservedAddrsForFunc: tc.ObsAddrFunc,
},
}
res := as.appendNATAddrs(nil, []ma.Multiaddr{tc.Listen}, ifaceAddrs)
res = ma.Unique(res)
require.ElementsMatch(t, tc.Expected, res, "%s\n%s", tc.Expected, res)
})
}
}
type mockNatManager struct {
GetMappingFunc func(addr ma.Multiaddr) ma.Multiaddr
}
func (*mockNatManager) Close() error {
return nil
}
func (m *mockNatManager) GetMapping(addr ma.Multiaddr) ma.Multiaddr {
if m.GetMappingFunc == nil {
return nil
}
return m.GetMappingFunc(addr)
}
func (*mockNatManager) HasDiscoveredNAT() bool {
return true
}
var _ NATManager = &mockNatManager{}
type mockObservedAddrs struct {
OwnObservedAddrsFunc func() []ma.Multiaddr
ObservedAddrsForFunc func(ma.Multiaddr) []ma.Multiaddr
}
func (m *mockObservedAddrs) OwnObservedAddrs() []ma.Multiaddr {
return m.OwnObservedAddrsFunc()
}
func (m *mockObservedAddrs) ObservedAddrsFor(local ma.Multiaddr) []ma.Multiaddr {
return m.ObservedAddrsForFunc(local)
}
type addrsManagerArgs struct {
NATManager NATManager
AddrsFactory AddrsFactory
ObservedAddrsManager observedAddrsManager
ListenAddrs func() []ma.Multiaddr
AutoNATClient autonatv2Client
Bus event.Bus
}
type addrsManagerTestCase struct {
*addrsManager
PushRelay func(relayAddrs []ma.Multiaddr)
PushReachability func(rch network.Reachability)
}
func newAddrsManagerTestCase(t *testing.T, args addrsManagerArgs) addrsManagerTestCase {
eb := args.Bus
if eb == nil {
eb = eventbus.NewBus()
}
if args.AddrsFactory == nil {
args.AddrsFactory = func(addrs []ma.Multiaddr) []ma.Multiaddr { return addrs }
}
addrsUpdatedChan := make(chan struct{}, 1)
am, err := newAddrsManager(
eb, args.NATManager, args.AddrsFactory, args.ListenAddrs, nil, args.ObservedAddrsManager, addrsUpdatedChan, args.AutoNATClient,
)
require.NoError(t, err)
require.NoError(t, am.Start())
raEm, err := eb.Emitter(new(event.EvtAutoRelayAddrsUpdated), eventbus.Stateful)
require.NoError(t, err)
rchEm, err := eb.Emitter(new(event.EvtLocalReachabilityChanged), eventbus.Stateful)
require.NoError(t, err)
t.Cleanup(am.Close)
return addrsManagerTestCase{
addrsManager: am,
PushRelay: func(relayAddrs []ma.Multiaddr) {
err := raEm.Emit(event.EvtAutoRelayAddrsUpdated{RelayAddrs: relayAddrs})
require.NoError(t, err)
},
PushReachability: func(rch network.Reachability) {
err := rchEm.Emit(event.EvtLocalReachabilityChanged{Reachability: rch})
require.NoError(t, err)
},
}
}
func TestAddrsManager(t *testing.T) {
lhquic := ma.StringCast("/ip4/127.0.0.1/udp/1/quic-v1")
lhtcp := ma.StringCast("/ip4/127.0.0.1/tcp/1")
publicQUIC := ma.StringCast("/ip4/1.2.3.4/udp/1/quic-v1")
publicTCP := ma.StringCast("/ip4/1.2.3.4/tcp/1")
t.Run("only nat", func(t *testing.T) {
am := newAddrsManagerTestCase(t, addrsManagerArgs{
NATManager: &mockNatManager{
GetMappingFunc: func(addr ma.Multiaddr) ma.Multiaddr {
if _, err := addr.ValueForProtocol(ma.P_UDP); err == nil {
return publicQUIC
}
return nil
},
},
ListenAddrs: func() []ma.Multiaddr { return []ma.Multiaddr{lhquic, lhtcp} },
})
am.triggerAddrsUpdate()
require.EventuallyWithT(t, func(collect *assert.CollectT) {
expected := []ma.Multiaddr{publicQUIC, lhquic, lhtcp}
assert.ElementsMatch(collect, am.Addrs(), expected, "%s\n%s", am.Addrs(), expected)
}, 5*time.Second, 50*time.Millisecond)
})
t.Run("nat and observed addrs", func(t *testing.T) {
// nat mapping for udp, observed addrs for tcp
am := newAddrsManagerTestCase(t, addrsManagerArgs{
NATManager: &mockNatManager{
GetMappingFunc: func(addr ma.Multiaddr) ma.Multiaddr {
if _, err := addr.ValueForProtocol(ma.P_UDP); err == nil {
return publicQUIC
}
return nil
},
},
ObservedAddrsManager: &mockObservedAddrs{
ObservedAddrsForFunc: func(addr ma.Multiaddr) []ma.Multiaddr {
if _, err := addr.ValueForProtocol(ma.P_TCP); err == nil {
return []ma.Multiaddr{publicTCP}
}
return nil
},
},
ListenAddrs: func() []ma.Multiaddr { return []ma.Multiaddr{lhquic, lhtcp} },
})
require.EventuallyWithT(t, func(collect *assert.CollectT) {
expected := []ma.Multiaddr{lhquic, lhtcp, publicQUIC, publicTCP}
assert.ElementsMatch(collect, am.Addrs(), expected, "%s\n%s", am.Addrs(), expected)
}, 5*time.Second, 50*time.Millisecond)
})
t.Run("nat returns unspecified addr", func(t *testing.T) {
quicPort1 := ma.StringCast("/ip4/3.3.3.3/udp/1/quic-v1")
quicPort2 := ma.StringCast("/ip4/3.3.3.3/udp/2/quic-v1")
// port from nat, IP from observed addr
am := newAddrsManagerTestCase(t, addrsManagerArgs{
NATManager: &mockNatManager{
GetMappingFunc: func(addr ma.Multiaddr) ma.Multiaddr {
if addr.Equal(lhquic) {
return ma.StringCast("/ip4/0.0.0.0/udp/2/quic-v1")
}
return nil
},
},
ObservedAddrsManager: &mockObservedAddrs{
ObservedAddrsForFunc: func(addr ma.Multiaddr) []ma.Multiaddr {
if addr.Equal(lhquic) {
return []ma.Multiaddr{quicPort1}
}
return nil
},
},
ListenAddrs: func() []ma.Multiaddr { return []ma.Multiaddr{lhquic} },
})
expected := []ma.Multiaddr{lhquic, quicPort2}
require.EventuallyWithT(t, func(collect *assert.CollectT) {
assert.ElementsMatch(collect, am.Addrs(), expected, "%s\n%s", am.Addrs(), expected)
}, 5*time.Second, 50*time.Millisecond)
})
t.Run("only observed addrs", func(t *testing.T) {
am := newAddrsManagerTestCase(t, addrsManagerArgs{
ObservedAddrsManager: &mockObservedAddrs{
ObservedAddrsForFunc: func(addr ma.Multiaddr) []ma.Multiaddr {
if addr.Equal(lhtcp) {
return []ma.Multiaddr{publicTCP}
}
if addr.Equal(lhquic) {
return []ma.Multiaddr{publicQUIC}
}
return nil
},
},
ListenAddrs: func() []ma.Multiaddr { return []ma.Multiaddr{lhquic, lhtcp} },
})
am.triggerAddrsUpdate()
expected := []ma.Multiaddr{lhquic, lhtcp, publicTCP, publicQUIC}
require.EventuallyWithT(t, func(collect *assert.CollectT) {
assert.ElementsMatch(collect, am.Addrs(), expected, "%s\n%s", am.Addrs(), expected)
}, 5*time.Second, 50*time.Millisecond)
})
t.Run("observed addrs limit", func(t *testing.T) {
quicAddrs := []ma.Multiaddr{
ma.StringCast("/ip4/1.2.3.4/udp/1/quic-v1"),
ma.StringCast("/ip4/1.2.3.4/udp/2/quic-v1"),
ma.StringCast("/ip4/1.2.3.4/udp/3/quic-v1"),
ma.StringCast("/ip4/1.2.3.4/udp/4/quic-v1"),
ma.StringCast("/ip4/1.2.3.4/udp/5/quic-v1"),
ma.StringCast("/ip4/1.2.3.4/udp/6/quic-v1"),
ma.StringCast("/ip4/1.2.3.4/udp/7/quic-v1"),
ma.StringCast("/ip4/1.2.3.4/udp/8/quic-v1"),
ma.StringCast("/ip4/1.2.3.4/udp/9/quic-v1"),
ma.StringCast("/ip4/1.2.3.4/udp/10/quic-v1"),
}
am := newAddrsManagerTestCase(t, addrsManagerArgs{
ObservedAddrsManager: &mockObservedAddrs{
ObservedAddrsForFunc: func(_ ma.Multiaddr) []ma.Multiaddr {
return quicAddrs
},
},
ListenAddrs: func() []ma.Multiaddr { return []ma.Multiaddr{lhquic} },
})
am.triggerAddrsUpdate()
expected := []ma.Multiaddr{lhquic}
expected = append(expected, quicAddrs[:maxObservedAddrsPerListenAddr]...)
require.EventuallyWithT(t, func(collect *assert.CollectT) {
assert.ElementsMatch(collect, am.Addrs(), expected, "%s\n%s", am.Addrs(), expected)
}, 5*time.Second, 50*time.Millisecond)
})
t.Run("public addrs removed when private", func(t *testing.T) {
am := newAddrsManagerTestCase(t, addrsManagerArgs{
ObservedAddrsManager: &mockObservedAddrs{
ObservedAddrsForFunc: func(_ ma.Multiaddr) []ma.Multiaddr {
return []ma.Multiaddr{publicQUIC}
},
},
ListenAddrs: func() []ma.Multiaddr { return []ma.Multiaddr{lhquic, lhtcp} },
})
// remove public addrs
am.PushReachability(network.ReachabilityPrivate)
relayAddr := ma.StringCast("/ip4/1.2.3.4/udp/1/quic-v1/p2p/QmdXGaeGiVA745XorV1jr11RHxB9z4fqykm6xCUPX1aTJo/p2p-circuit")
am.PushRelay([]ma.Multiaddr{relayAddr})
expectedAddrs := []ma.Multiaddr{relayAddr, lhquic, lhtcp}
expectedAllAddrs := []ma.Multiaddr{publicQUIC, lhquic, lhtcp}
require.EventuallyWithT(t, func(collect *assert.CollectT) {
assert.ElementsMatch(collect, am.Addrs(), expectedAddrs, "%s\n%s", am.Addrs(), expectedAddrs)
assert.ElementsMatch(collect, am.DirectAddrs(), expectedAllAddrs, "%s\n%s", am.DirectAddrs(), expectedAllAddrs)
}, 5*time.Second, 50*time.Millisecond)
// add public addrs
am.PushReachability(network.ReachabilityPublic)
expectedAddrs = expectedAllAddrs
require.EventuallyWithT(t, func(collect *assert.CollectT) {
assert.ElementsMatch(collect, am.Addrs(), expectedAddrs, "%s\n%s", am.Addrs(), expectedAddrs)
assert.ElementsMatch(collect, am.DirectAddrs(), expectedAllAddrs, "%s\n%s", am.DirectAddrs(), expectedAllAddrs)
}, 5*time.Second, 50*time.Millisecond)
})
t.Run("addrs factory gets relay addrs", func(t *testing.T) {
relayAddr := ma.StringCast("/ip4/1.2.3.4/udp/1/quic-v1/p2p/QmdXGaeGiVA745XorV1jr11RHxB9z4fqykm6xCUPX1aTJo/p2p-circuit")
publicQUIC2 := ma.StringCast("/ip4/1.2.3.4/udp/2/quic-v1")
am := newAddrsManagerTestCase(t, addrsManagerArgs{
AddrsFactory: func(addrs []ma.Multiaddr) []ma.Multiaddr {
for _, a := range addrs {
if a.Equal(relayAddr) {
return []ma.Multiaddr{publicQUIC2}
}
}
return nil
},
ObservedAddrsManager: &mockObservedAddrs{
ObservedAddrsForFunc: func(_ ma.Multiaddr) []ma.Multiaddr {
return []ma.Multiaddr{publicQUIC}
},
},
ListenAddrs: func() []ma.Multiaddr { return []ma.Multiaddr{lhquic, lhtcp} },
})
am.PushReachability(network.ReachabilityPrivate)
am.PushRelay([]ma.Multiaddr{relayAddr})
expectedAddrs := []ma.Multiaddr{publicQUIC2}
expectedAllAddrs := []ma.Multiaddr{publicQUIC, lhquic, lhtcp}
require.EventuallyWithT(t, func(collect *assert.CollectT) {
assert.ElementsMatch(collect, am.Addrs(), expectedAddrs, "%s\n%s", am.Addrs(), expectedAddrs)
assert.ElementsMatch(collect, am.DirectAddrs(), expectedAllAddrs, "%s\n%s", am.DirectAddrs(), expectedAllAddrs)
}, 5*time.Second, 50*time.Millisecond)
})
t.Run("updates addresses on signaling", func(t *testing.T) {
updateChan := make(chan struct{})
am := newAddrsManagerTestCase(t, addrsManagerArgs{
AddrsFactory: func(_ []ma.Multiaddr) []ma.Multiaddr {
select {
case <-updateChan:
return []ma.Multiaddr{publicQUIC}
default:
return []ma.Multiaddr{publicTCP}
}
},
ListenAddrs: func() []ma.Multiaddr { return []ma.Multiaddr{lhquic, lhtcp} },
})
require.Contains(t, am.Addrs(), publicTCP)
require.NotContains(t, am.Addrs(), publicQUIC)
close(updateChan)
am.triggerAddrsUpdate()
require.EventuallyWithT(t, func(collect *assert.CollectT) {
assert.Contains(collect, am.Addrs(), publicQUIC)
assert.NotContains(collect, am.Addrs(), publicTCP)
}, 1*time.Second, 50*time.Millisecond)
})
}
func TestAddrsManagerReachabilityEvent(t *testing.T) {
publicQUIC, _ := ma.NewMultiaddr("/ip4/1.2.3.4/udp/1234/quic-v1")
publicQUIC2, _ := ma.NewMultiaddr("/ip4/1.2.3.4/udp/1235/quic-v1")
publicTCP, _ := ma.NewMultiaddr("/ip4/1.2.3.4/tcp/1234")
bus := eventbus.NewBus()
sub, err := bus.Subscribe(new(event.EvtHostReachableAddrsChanged))
require.NoError(t, err)
defer sub.Close()
am := newAddrsManagerTestCase(t, addrsManagerArgs{
Bus: bus,
// currently they aren't being passed to the reachability tracker
ListenAddrs: func() []ma.Multiaddr { return []ma.Multiaddr{publicQUIC, publicQUIC2, publicTCP} },
AutoNATClient: mockAutoNATClient{
F: func(_ context.Context, reqs []autonatv2.Request) (autonatv2.Result, error) {
if reqs[0].Addr.Equal(publicQUIC) {
return autonatv2.Result{Addr: reqs[0].Addr, Idx: 0, Reachability: network.ReachabilityPublic}, nil
} else if reqs[0].Addr.Equal(publicTCP) || reqs[0].Addr.Equal(publicQUIC2) {
return autonatv2.Result{Addr: reqs[0].Addr, Idx: 0, Reachability: network.ReachabilityPrivate}, nil
}
return autonatv2.Result{}, errors.New("invalid")
},
},
})
reachableAddrs := []ma.Multiaddr{publicQUIC}
unreachableAddrs := []ma.Multiaddr{publicTCP, publicQUIC2}
select {
case e := <-sub.Out():
evt := e.(event.EvtHostReachableAddrsChanged)
require.ElementsMatch(t, reachableAddrs, evt.Reachable)
require.ElementsMatch(t, unreachableAddrs, evt.Unreachable)
require.ElementsMatch(t, reachableAddrs, am.ReachableAddrs())
case <-time.After(5 * time.Second):
t.Fatal("expected event for reachability change")
}
}
func TestRemoveIfNotInSource(t *testing.T) {
var addrs []ma.Multiaddr
for i := 0; i < 10; i++ {
addrs = append(addrs, ma.StringCast(fmt.Sprintf("/ip4/1.2.3.4/tcp/%d", i)))
}
slices.SortFunc(addrs, func(a, b ma.Multiaddr) int { return a.Compare(b) })
cases := []struct {
addrs []ma.Multiaddr
source []ma.Multiaddr
expected []ma.Multiaddr
}{
{},
{addrs: slices.Clone(addrs[:5]), source: nil, expected: nil},
{addrs: nil, source: addrs, expected: nil},
{addrs: []ma.Multiaddr{addrs[0]}, source: []ma.Multiaddr{addrs[0]}, expected: []ma.Multiaddr{addrs[0]}},
{addrs: slices.Clone(addrs), source: []ma.Multiaddr{addrs[0]}, expected: []ma.Multiaddr{addrs[0]}},
{addrs: slices.Clone(addrs), source: slices.Clone(addrs[5:]), expected: slices.Clone(addrs[5:])},
{addrs: slices.Clone(addrs[:5]), source: []ma.Multiaddr{addrs[0], addrs[2], addrs[8]}, expected: []ma.Multiaddr{addrs[0], addrs[2]}},
}
for i, tc := range cases {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
addrs := removeNotInSource(tc.addrs, tc.source)
require.ElementsMatch(t, tc.expected, addrs, "%s\n%s", tc.expected, tc.addrs)
})
}
}
func BenchmarkAreAddrsDifferent(b *testing.B) {
var addrs [10]ma.Multiaddr
for i := 0; i < len(addrs); i++ {
addrs[i] = ma.StringCast(fmt.Sprintf("/ip4/1.1.1.%d/tcp/1", i))
}
b.Run("areAddrsDifferent", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
areAddrsDifferent(addrs[:], addrs[:])
}
})
}
func BenchmarkRemoveIfNotInSource(b *testing.B) {
var addrs [10]ma.Multiaddr
for i := 0; i < len(addrs); i++ {
addrs[i] = ma.StringCast(fmt.Sprintf("/ip4/1.1.1.%d/tcp/1", i))
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
removeNotInSource(slices.Clone(addrs[:5]), addrs[:])
}
}