diff --git a/core/peer/addrinfo.go b/core/peer/addrinfo.go index 397de274c9..0c0d34fdae 100644 --- a/core/peer/addrinfo.go +++ b/core/peer/addrinfo.go @@ -109,7 +109,7 @@ func AddrInfoToP2pAddrs(pi *AddrInfo) ([]ma.Multiaddr, error) { return nil, err } if len(pi.Addrs) == 0 { - return []ma.Multiaddr{p2ppart}, nil + return []ma.Multiaddr{p2ppart.Multiaddr()}, nil } addrs := make([]ma.Multiaddr, 0, len(pi.Addrs)) for _, addr := range pi.Addrs { diff --git a/go.mod b/go.mod index c5a18fbbfa..05b521928d 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-base32 v0.1.0 - github.com/multiformats/go-multiaddr v0.14.0 + github.com/multiformats/go-multiaddr v0.15.0 github.com/multiformats/go-multiaddr-dns v0.4.1 github.com/multiformats/go-multiaddr-fmt v0.1.0 github.com/multiformats/go-multibase v0.2.0 diff --git a/go.sum b/go.sum index eef6dd3d0e..76eb9c8953 100644 --- a/go.sum +++ b/go.sum @@ -230,8 +230,8 @@ github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYg github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.14.0 h1:bfrHrJhrRuh/NXH5mCnemjpbGjzRw/b+tJFOD41g2tU= -github.com/multiformats/go-multiaddr v0.14.0/go.mod h1:6EkVAxtznq2yC3QT5CM1UTAwG0GTP3EWAIcjHuzQ+r4= +github.com/multiformats/go-multiaddr v0.15.0 h1:zB/HeaI/apcZiTDwhY5YqMvNVl/oQYvs3XySU+qeAVo= +github.com/multiformats/go-multiaddr v0.15.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M= github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= diff --git a/p2p/host/autonat/svc.go b/p2p/host/autonat/svc.go index d29355014e..bf84c841aa 100644 --- a/p2p/host/autonat/svc.go +++ b/p2p/host/autonat/svc.go @@ -167,8 +167,8 @@ func (as *autoNATService) handleDial(p peer.ID, obsaddr ma.Multiaddr, mpi *pb.Me default: continue } - addr = hostIP - if rest != nil { + addr = hostIP.Multiaddr() + if len(rest) > 0 { addr = addr.Encapsulate(rest) } } diff --git a/p2p/host/autorelay/addrsplosion_test.go b/p2p/host/autorelay/addrsplosion_test.go index 1bbd910c54..19425c555e 100644 --- a/p2p/host/autorelay/addrsplosion_test.go +++ b/p2p/host/autorelay/addrsplosion_test.go @@ -4,7 +4,7 @@ import ( "testing" ma "github.com/multiformats/go-multiaddr" - "github.com/stretchr/testify/require" + matest "github.com/multiformats/go-multiaddr/matest" ) func TestCleanupAddrs(t *testing.T) { @@ -21,7 +21,7 @@ func TestCleanupAddrs(t *testing.T) { "/ip4/1.2.3.4/udp/4002/quic-v1", "/dnsaddr/somedomain.com/tcp/4002/ws", ) - require.ElementsMatch(t, clean, cleanupAddressSet(addrs), "cleaned up set doesn't match expected") + matest.AssertMultiaddrsMatch(t, clean, cleanupAddressSet(addrs)) }) t.Run("with default port", func(t *testing.T) { @@ -38,7 +38,7 @@ func TestCleanupAddrs(t *testing.T) { "/ip4/1.2.3.4/tcp/4001", "/ip4/1.2.3.4/udp/4002/quic-v1", ) - require.ElementsMatch(t, clean, cleanupAddressSet(addrs), "cleaned up set doesn't match expected") + matest.AssertMultiaddrsMatch(t, clean, cleanupAddressSet(addrs)) }) t.Run("with default port, but no private addrs", func(t *testing.T) { @@ -54,7 +54,7 @@ func TestCleanupAddrs(t *testing.T) { "/ip4/1.2.3.4/tcp/4001", "/ip4/1.2.3.4/udp/4002/quic-v1", ) - require.ElementsMatch(t, clean, cleanupAddressSet(addrs), "cleaned up set doesn't match expected") + matest.AssertMultiaddrsMatch(t, clean, cleanupAddressSet(addrs)) }) t.Run("with non-standard port", func(t *testing.T) { @@ -68,7 +68,9 @@ func TestCleanupAddrs(t *testing.T) { clean := makeAddrList( "/ip4/1.2.3.4/tcp/12345", ) - require.ElementsMatch(t, clean, cleanupAddressSet(addrs), "cleaned up set doesn't match expected") + if !matest.AssertEqualMultiaddrs(t, clean, cleanupAddressSet(addrs)) { + t.Log("cleaned up set doesn't match expected") + } }) t.Run("with a clean address set", func(t *testing.T) { @@ -77,7 +79,7 @@ func TestCleanupAddrs(t *testing.T) { "/ip4/1.2.3.4/tcp/4001", "/ip4/1.2.3.4/udp/4001/quic-v1", ) - require.ElementsMatch(t, addrs, cleanupAddressSet(addrs), "cleaned up set doesn't match expected") + matest.AssertMultiaddrsMatch(t, addrs, cleanupAddressSet(addrs)) }) } diff --git a/p2p/host/basic/basic_host.go b/p2p/host/basic/basic_host.go index bae6027214..a1e0aa4243 100644 --- a/p2p/host/basic/basic_host.go +++ b/p2p/host/basic/basic_host.go @@ -975,11 +975,11 @@ func (h *BasicHost) AllAddrs() []ma.Multiaddr { for _, obsMaddr := range observed { // Extract a public observed addr. ip, _ := ma.SplitFirst(obsMaddr) - if ip == nil || !manet.IsPublicAddr(ip) { + if ip == nil || !manet.IsPublicAddr(ip.Multiaddr()) { continue } - finalAddrs = append(finalAddrs, ma.Join(ip, extMaddrNoIP)) + finalAddrs = append(finalAddrs, ip.Encapsulate(extMaddrNoIP)) } } } diff --git a/p2p/host/basic/basic_host_test.go b/p2p/host/basic/basic_host_test.go index 2a7a772976..895c554884 100644 --- a/p2p/host/basic/basic_host_test.go +++ b/p2p/host/basic/basic_host_test.go @@ -25,6 +25,7 @@ import ( "github.com/libp2p/go-libp2p/p2p/protocol/identify" ma "github.com/multiformats/go-multiaddr" + "github.com/multiformats/go-multiaddr/matest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -300,7 +301,7 @@ func TestAllAddrsUnique(t *testing.T) { }() close(sendNewAddrs) require.Len(t, h.Addrs(), 2) - require.ElementsMatch(t, []ma.Multiaddr{ma.StringCast("/ip4/1.2.3.4/tcp/1"), ma.StringCast("/ip4/1.2.3.4/udp/1/quic-v1")}, h.Addrs()) + matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{ma.StringCast("/ip4/1.2.3.4/tcp/1"), ma.StringCast("/ip4/1.2.3.4/udp/1/quic-v1")}, h.Addrs()) time.Sleep(2*addrChangeTickrInterval + 1*time.Second) // the background loop runs every 5 seconds. Wait for 2x that time. close(done) cnt := <-out @@ -650,13 +651,13 @@ func TestAddrChangeImmediatelyIfAddressNonEmpty(t *testing.T) { // assert it's on the signed record rc := peerRecordFromEnvelope(t, evt.SignedPeerRecord) - require.Equal(t, taddrs, rc.Addrs) + matest.AssertEqualMultiaddrs(t, taddrs, rc.Addrs) // assert it's in the peerstore ev := h.Peerstore().(peerstore.CertifiedAddrBook).GetPeerRecord(h.ID()) require.NotNil(t, ev) rc = peerRecordFromEnvelope(t, ev) - require.Equal(t, taddrs, rc.Addrs) + matest.AssertEqualMultiaddrs(t, taddrs, rc.Addrs) } func TestStatefulAddrEvents(t *testing.T) { @@ -759,13 +760,13 @@ func TestHostAddrChangeDetection(t *testing.T) { // assert it's on the signed record rc := peerRecordFromEnvelope(t, evt.SignedPeerRecord) - require.Equal(t, addrSets[i], rc.Addrs) + matest.AssertMultiaddrsMatch(t, addrSets[i], rc.Addrs) // assert it's in the peerstore ev := h.Peerstore().(peerstore.CertifiedAddrBook).GetPeerRecord(h.ID()) require.NotNil(t, ev) rc = peerRecordFromEnvelope(t, ev) - require.Equal(t, addrSets[i], rc.Addrs) + matest.AssertMultiaddrsMatch(t, addrSets[i], rc.Addrs) } } diff --git a/p2p/host/basic/natmgr.go b/p2p/host/basic/natmgr.go index bc55e4d76d..4abe8dd08b 100644 --- a/p2p/host/basic/natmgr.go +++ b/p2p/host/basic/natmgr.go @@ -151,7 +151,7 @@ func (nmgr *natManager) doSync() { for _, maddr := range nmgr.net.ListenAddresses() { // Strip the IP maIP, rest := ma.SplitFirst(maddr) - if maIP == nil || rest == nil { + if maIP == nil || len(rest) == 0 { continue } diff --git a/p2p/host/basic/natmgr_test.go b/p2p/host/basic/natmgr_test.go index 8cbe8618e1..c216e4f6d1 100644 --- a/p2p/host/basic/natmgr_test.go +++ b/p2p/host/basic/natmgr_test.go @@ -42,11 +42,11 @@ func TestMapping(t *testing.T) { externalAddr := netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 2, 3, 4}), 4321) // pretend that we have a TCP mapping mockNAT.EXPECT().GetMapping("tcp", 1234).Return(externalAddr, true) - require.Equal(t, ma.StringCast("/ip4/1.2.3.4/tcp/4321"), m.GetMapping(ma.StringCast("/ip4/0.0.0.0/tcp/1234"))) + require.Equal(t, "/ip4/1.2.3.4/tcp/4321", m.GetMapping(ma.StringCast("/ip4/0.0.0.0/tcp/1234")).String()) // pretend that we have a QUIC mapping mockNAT.EXPECT().GetMapping("udp", 1234).Return(externalAddr, true) - require.Equal(t, ma.StringCast("/ip4/1.2.3.4/udp/4321/quic-v1"), m.GetMapping(ma.StringCast("/ip4/0.0.0.0/udp/1234/quic-v1"))) + require.Equal(t, "/ip4/1.2.3.4/udp/4321/quic-v1", m.GetMapping(ma.StringCast("/ip4/0.0.0.0/udp/1234/quic-v1")).String()) // pretend that there's no mapping mockNAT.EXPECT().GetMapping("tcp", 1234).Return(netip.AddrPort{}, false) @@ -54,11 +54,11 @@ func TestMapping(t *testing.T) { // make sure this works for WebSocket addresses as well mockNAT.EXPECT().GetMapping("tcp", 1234).Return(externalAddr, true) - require.Equal(t, ma.StringCast("/ip4/1.2.3.4/tcp/4321/ws"), m.GetMapping(ma.StringCast("/ip4/0.0.0.0/tcp/1234/ws"))) + require.Equal(t, "/ip4/1.2.3.4/tcp/4321/ws", m.GetMapping(ma.StringCast("/ip4/0.0.0.0/tcp/1234/ws")).String()) // make sure this works for WebTransport addresses as well mockNAT.EXPECT().GetMapping("udp", 1234).Return(externalAddr, true) - require.Equal(t, ma.StringCast("/ip4/1.2.3.4/udp/4321/quic-v1/webtransport"), m.GetMapping(ma.StringCast("/ip4/0.0.0.0/udp/1234/quic-v1/webtransport"))) + require.Equal(t, "/ip4/1.2.3.4/udp/4321/quic-v1/webtransport", m.GetMapping(ma.StringCast("/ip4/0.0.0.0/udp/1234/quic-v1/webtransport")).String()) } func TestAddAndRemoveListeners(t *testing.T) { diff --git a/p2p/http/libp2phttp.go b/p2p/http/libp2phttp.go index 4dad47dd43..f61eda4d63 100644 --- a/p2p/http/libp2phttp.go +++ b/p2p/http/libp2phttp.go @@ -532,7 +532,7 @@ func relativeMultiaddrURIToAbs(original *url.URL, relative *url.URL) (*url.URL, withoutPath, _ := ma.SplitFunc(originalMa, func(c ma.Component) bool { return c.Protocol().Code == ma.P_HTTP_PATH }) - withNewPath := withoutPath.Encapsulate(relativePathComponent) + withNewPath := withoutPath.AppendComponent(relativePathComponent) return url.Parse("multiaddr:" + withNewPath.String()) } @@ -937,10 +937,12 @@ func normalizeHTTPMultiaddr(addr ma.Multiaddr) (ma.Multiaddr, bool) { _, afterHTTPS := ma.SplitFirst(afterIncludingHTTPS) if afterHTTPS == nil { - return ma.Join(beforeHTTPS, tlsComponent, httpComponent), isHTTPMultiaddr + return beforeHTTPS.AppendComponent(tlsComponent, httpComponent), isHTTPMultiaddr } - return ma.Join(beforeHTTPS, tlsComponent, httpComponent, afterHTTPS), isHTTPMultiaddr + t := beforeHTTPS.AppendComponent(tlsComponent, httpComponent) + t = append(t, afterHTTPS...) + return t, isHTTPMultiaddr } // getAndStorePeerMetadata looks up the protocol path in the well-known mapping and diff --git a/p2p/metricshelper/conn.go b/p2p/metricshelper/conn.go index 5fd8a114a5..28050eb2f4 100644 --- a/p2p/metricshelper/conn.go +++ b/p2p/metricshelper/conn.go @@ -8,9 +8,12 @@ func GetTransport(a ma.Multiaddr) string { if a == nil { return "other" } - for _, t := range transports { - if _, err := a.ValueForProtocol(t); err == nil { - return ma.ProtocolWithCode(t).Name + for i := len(a) - 1; i >= 0; i-- { + p := a[i].Protocol() + for _, t := range transports { + if p.Code == t { + return p.Name + } } } return "other" diff --git a/p2p/net/swarm/dial_worker_test.go b/p2p/net/swarm/dial_worker_test.go index d264fd1230..c7298fb61e 100644 --- a/p2p/net/swarm/dial_worker_test.go +++ b/p2p/net/swarm/dial_worker_test.go @@ -578,11 +578,11 @@ func checkDialWorkerLoopScheduling(t *testing.T, s1, s2 *Swarm, tc schedulingTes // failDials is used to track dials which should fail in the future // at appropriate moment a message is sent to dialState.ch to trigger // failure - failDials := make(map[ma.Multiaddr]dialState) + failDials := make(map[*ma.Multiaddr]dialState) // recvCh is used to receive dial notifications for dials that will fail recvCh := make(chan struct{}, 100) // allDials tracks all pending dials - allDials := make(map[ma.Multiaddr]dialState) + allDials := make(map[*ma.Multiaddr]dialState) // addrs are the peer addresses the swarm will use for dialing addrs := make([]ma.Multiaddr, 0) // create pending dials @@ -610,7 +610,7 @@ func checkDialWorkerLoopScheduling(t *testing.T, s1, s2 *Swarm, tc schedulingTes } addrs = append(addrs, inp.addr) // add to pending dials - allDials[inp.addr] = dialState{ + allDials[&inp.addr] = dialState{ ch: failCh, addr: inp.addr, delay: inp.delay, @@ -695,7 +695,7 @@ loop: failDials[a] = dialState{ ch: ds.ch, failAt: cl.Now().Add(ds.failAfter), - addr: a, + addr: *a, delay: ds.delay, } } diff --git a/p2p/net/swarm/swarm_dial_test.go b/p2p/net/swarm/swarm_dial_test.go index d3586ca5d9..6d14730b68 100644 --- a/p2p/net/swarm/swarm_dial_test.go +++ b/p2p/net/swarm/swarm_dial_test.go @@ -26,6 +26,7 @@ import ( ma "github.com/multiformats/go-multiaddr" madns "github.com/multiformats/go-multiaddr-dns" + matest "github.com/multiformats/go-multiaddr/matest" "github.com/stretchr/testify/require" ) @@ -188,12 +189,12 @@ func TestAddrResolution(t *testing.T) { require.NoError(t, err) require.Len(t, mas, 1) - require.Contains(t, mas, addr2) + matest.AssertMultiaddrsContain(t, mas, addr2) addrs := s.peers.Addrs(p1) require.Len(t, addrs, 2) - require.Contains(t, addrs, addr1) - require.Contains(t, addrs, addr2) + matest.AssertMultiaddrsContain(t, addrs, addr1) + matest.AssertMultiaddrsContain(t, addrs, addr2) } func TestAddrResolutionRecursive(t *testing.T) { @@ -234,8 +235,8 @@ func TestAddrResolutionRecursive(t *testing.T) { addrs1 := s.Peerstore().Addrs(pi1.ID) require.Len(t, addrs1, 2) - require.Contains(t, addrs1, addr1) - require.Contains(t, addrs1, addr2) + matest.AssertMultiaddrsContain(t, addrs1, addr1) + matest.AssertMultiaddrsContain(t, addrs1, addr2) pi2, err := peer.AddrInfoFromP2pAddr(p2paddr2) require.NoError(t, err) @@ -247,7 +248,7 @@ func TestAddrResolutionRecursive(t *testing.T) { addrs2 := s.Peerstore().Addrs(pi2.ID) require.Len(t, addrs2, 1) - require.Contains(t, addrs2, addr1) + matest.AssertMultiaddrsContain(t, addrs2, addr1) } // see https://github.com/libp2p/go-libp2p/issues/2562 diff --git a/p2p/protocol/circuitv2/client/conn.go b/p2p/protocol/circuitv2/client/conn.go index ed01be3b33..e7a25d81a9 100644 --- a/p2p/protocol/circuitv2/client/conn.go +++ b/p2p/protocol/circuitv2/client/conn.go @@ -83,9 +83,10 @@ func (c *Conn) RemoteMultiaddr() ma.Multiaddr { c.stream.Conn().RemotePeer().String(), ) if err != nil { - panic(err) + log.Error(err) + return ma.Join(c.stream.Conn().RemoteMultiaddr(), circuitAddr) } - return ma.Join(c.stream.Conn().RemoteMultiaddr(), relayAddr, circuitAddr) + return ma.Join(c.stream.Conn().RemoteMultiaddr(), relayAddr.Multiaddr(), circuitAddr) } func (c *Conn) LocalMultiaddr() ma.Multiaddr { diff --git a/p2p/protocol/identify/id_test.go b/p2p/protocol/identify/id_test.go index 994f042b3e..0720e15101 100644 --- a/p2p/protocol/identify/id_test.go +++ b/p2p/protocol/identify/id_test.go @@ -34,13 +34,13 @@ import ( "github.com/libp2p/go-libp2p-testing/race" "github.com/libp2p/go-msgio/pbio" ma "github.com/multiformats/go-multiaddr" - "github.com/stretchr/testify/assert" + matest "github.com/multiformats/go-multiaddr/matest" "github.com/stretchr/testify/require" ) func testKnowsAddrs(t *testing.T, h host.Host, p peer.ID, expected []ma.Multiaddr) { t.Helper() - require.True(t, assert.ElementsMatchf(t, expected, h.Peerstore().Addrs(p), fmt.Sprintf("%s did not have addr for %s", h.ID(), p))) + require.True(t, matest.AssertMultiaddrsMatch(t, expected, h.Peerstore().Addrs(p)), fmt.Sprintf("%s did not have addr for %s", h.ID(), p)) } func testHasAgentVersion(t *testing.T, h host.Host, p peer.ID) { @@ -257,7 +257,7 @@ func assertCorrectEvtPeerIdentificationCompleted(t *testing.T, evtAny interface{ var peerRecord peer.PeerRecord evt.SignedPeerRecord.TypedRecord(&peerRecord) require.Equal(t, other.ID(), peerRecord.PeerID) - require.Equal(t, other.Addrs(), peerRecord.Addrs) + matest.AssertMultiaddrsMatch(t, other.Addrs(), peerRecord.Addrs) } func TestProtoMatching(t *testing.T) { @@ -486,7 +486,7 @@ func TestIdentifyPushOnAddrChange(t *testing.T) { // change addr on host 1 and ensure host2 gets a push lad := ma.StringCast("/ip4/127.0.0.1/tcp/1234") require.NoError(t, h1.Network().Listen(lad)) - require.Contains(t, h1.Addrs(), lad) + matest.AssertMultiaddrsContain(t, h1.Addrs(), lad) h2AddrStream := h2.Peerstore().AddrStream(ctx, h1p) @@ -500,7 +500,7 @@ func TestIdentifyPushOnAddrChange(t *testing.T) { // change addr on host2 and ensure host 1 gets a pus lad = ma.StringCast("/ip4/127.0.0.1/tcp/1235") require.NoError(t, h2.Network().Listen(lad)) - require.Contains(t, h2.Addrs(), lad) + matest.AssertMultiaddrsContain(t, h2.Addrs(), lad) h1AddrStream := h1.Peerstore().AddrStream(ctx, h2p) emitAddrChangeEvt(t, h2) @@ -512,7 +512,7 @@ func TestIdentifyPushOnAddrChange(t *testing.T) { // change addr on host2 again lad2 := ma.StringCast("/ip4/127.0.0.1/tcp/1236") require.NoError(t, h2.Network().Listen(lad2)) - require.Contains(t, h2.Addrs(), lad2) + matest.AssertMultiaddrsContain(t, h2.Addrs(), lad2) emitAddrChangeEvt(t, h2) // Wait for h1 to process the new addr @@ -788,7 +788,7 @@ func TestLargePushMessage(t *testing.T) { // change addr on host 1 and ensure host2 gets a push lad := ma.StringCast("/ip4/127.0.0.1/tcp/1234") require.NoError(t, h1.Network().Listen(lad)) - require.Contains(t, h1.Addrs(), lad) + matest.AssertMultiaddrsContain(t, h1.Addrs(), lad) emitAddrChangeEvt(t, h1) require.Eventually(t, func() bool { @@ -798,7 +798,7 @@ func TestLargePushMessage(t *testing.T) { // change addr on host2 and ensure host 1 gets a pus lad = ma.StringCast("/ip4/127.0.0.1/tcp/1235") require.NoError(t, h2.Network().Listen(lad)) - require.Contains(t, h2.Addrs(), lad) + matest.AssertMultiaddrsContain(t, h2.Addrs(), lad) emitAddrChangeEvt(t, h2) require.Eventually(t, func() bool { @@ -808,7 +808,7 @@ func TestLargePushMessage(t *testing.T) { // change addr on host2 again lad2 := ma.StringCast("/ip4/127.0.0.1/tcp/1236") require.NoError(t, h2.Network().Listen(lad2)) - require.Contains(t, h2.Addrs(), lad2) + matest.AssertMultiaddrsContain(t, h2.Addrs(), lad2) emitAddrChangeEvt(t, h2) require.Eventually(t, func() bool { diff --git a/p2p/protocol/identify/obsaddr_glass_test.go b/p2p/protocol/identify/obsaddr_glass_test.go index 3211aa5f54..d596be9ba8 100644 --- a/p2p/protocol/identify/obsaddr_glass_test.go +++ b/p2p/protocol/identify/obsaddr_glass_test.go @@ -9,6 +9,7 @@ import ( "testing" ma "github.com/multiformats/go-multiaddr" + "github.com/multiformats/go-multiaddr/matest" "github.com/stretchr/testify/require" ) @@ -168,9 +169,9 @@ func TestThinWaistForm(t *testing.T) { if tt.rest != "" { restTW = ma.StringCast(tt.rest) } - require.Equal(t, tw.Addr, inputAddr, "%s %s", tw.Addr, inputAddr) - require.Equal(t, wantTW, tw.TW, "%s %s", tw.TW, wantTW) - require.Equal(t, restTW, tw.Rest, "%s %s", restTW, tw.Rest) + matest.AssertEqualMultiaddr(t, inputAddr, tw.Addr) + matest.AssertEqualMultiaddr(t, wantTW, tw.TW) + matest.AssertEqualMultiaddr(t, restTW, tw.Rest) }) } diff --git a/p2p/protocol/identify/obsaddr_test.go b/p2p/protocol/identify/obsaddr_test.go index 5087c935ad..aad55bb375 100644 --- a/p2p/protocol/identify/obsaddr_test.go +++ b/p2p/protocol/identify/obsaddr_test.go @@ -4,6 +4,7 @@ import ( crand "crypto/rand" "fmt" "net" + "slices" "testing" "time" @@ -14,11 +15,31 @@ import ( swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing" ma "github.com/multiformats/go-multiaddr" + matest "github.com/multiformats/go-multiaddr/matest" manet "github.com/multiformats/go-multiaddr/net" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +func requireAddrsMatch(t *testing.T, a, b []ma.Multiaddr) { + t.Helper() + slices.SortFunc(a, func(a, b ma.Multiaddr) int { return a.Compare(b) }) + slices.SortFunc(b, func(a, b ma.Multiaddr) int { return a.Compare(b) }) + requireEqualAddrs(t, a, b) +} + +func requireEqualAddrs(t *testing.T, a, b []ma.Multiaddr) { + t.Helper() + if len(a) != len(b) { + t.Fatalf("length mismatch: %d != %d", len(a), len(b)) + } + for i, addr := range a { + if !addr.Equal(b[i]) { + t.Fatalf("addr mismatch: %s != %s", addr, b[i]) + } + } +} + func newConn(local, remote ma.Multiaddr) *mockConn { return &mockConn{local: local, remote: remote} } @@ -51,20 +72,6 @@ func subtractFrom(a, b []ma.Multiaddr) []string { return out } -func multiaddrsToStrings(a []ma.Multiaddr) []string { - out := make([]string, len(a)) - for i, addr := range a { - out[i] = addr.String() - } - return out -} - -func addrsEqual(t assert.TestingT, a, b []ma.Multiaddr) bool { - aStr := multiaddrsToStrings(a) - bStr := multiaddrsToStrings(b) - return assert.ElementsMatch(t, aStr, bStr) -} - func TestObservedAddrManager(t *testing.T) { tcp4ListenAddr := ma.StringCast("/ip4/192.168.1.100/tcp/1") quic4ListenAddr := ma.StringCast("/ip4/0.0.0.0/udp/1/quic-v1") @@ -106,7 +113,7 @@ func TestObservedAddrManager(t *testing.T) { o.Record(c3, observed) o.Record(c4, observed) require.Eventually(t, func() bool { - return addrsEqual(t, o.Addrs(), []ma.Multiaddr{observed}) + return matest.AssertEqualMultiaddrs(t, o.Addrs(), []ma.Multiaddr{observed}) }, 1*time.Second, 100*time.Millisecond) o.removeConn(c1) o.removeConn(c2) @@ -131,8 +138,8 @@ func TestObservedAddrManager(t *testing.T) { o.Record(c3, observedWebTransport) o.Record(c4, observedWebTransport) require.EventuallyWithT(t, func(t *assert.CollectT) { - addrsEqual(t, o.Addrs(), []ma.Multiaddr{observedQuic, observedWebTransport}) - addrsEqual(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{}) + matest.AssertEqualMultiaddrs(t, o.Addrs(), []ma.Multiaddr{observedQuic, observedWebTransport}) + matest.AssertEqualMultiaddrs(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{}) }, 1*time.Second, 100*time.Millisecond) o.removeConn(c1) o.removeConn(c2) @@ -157,8 +164,8 @@ func TestObservedAddrManager(t *testing.T) { o.Record(c3, observedQuic) o.Record(c4, observedQuic) require.EventuallyWithT(t, func(t *assert.CollectT) { - addrsEqual(t, o.Addrs(), []ma.Multiaddr{observedQuic, inferredWebTransport}) - addrsEqual(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{inferredWebTransport}) + matest.AssertEqualMultiaddrs(t, o.Addrs(), []ma.Multiaddr{observedQuic, inferredWebTransport}) + matest.AssertEqualMultiaddrs(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{inferredWebTransport}) }, 1*time.Second, 100*time.Millisecond) o.removeConn(c1) o.removeConn(c2) @@ -193,8 +200,8 @@ func TestObservedAddrManager(t *testing.T) { o.Record(ob1[N-1], observedQuic) o.Record(ob2[N-1], observedQuic) require.EventuallyWithT(t, func(t *assert.CollectT) { - addrsEqual(t, o.Addrs(), []ma.Multiaddr{observedQuic, inferredWebTransport}) - addrsEqual(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{inferredWebTransport}) + matest.AssertEqualMultiaddrs(t, o.Addrs(), []ma.Multiaddr{observedQuic, inferredWebTransport}) + matest.AssertEqualMultiaddrs(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{inferredWebTransport}) }, 2*time.Second, 100*time.Millisecond) // Now disconnect first observer group @@ -202,7 +209,7 @@ func TestObservedAddrManager(t *testing.T) { o.removeConn(ob1[i]) } time.Sleep(100 * time.Millisecond) - if !addrsEqual(t, o.Addrs(), []ma.Multiaddr{observedQuic, inferredWebTransport}) { + if !matest.AssertEqualMultiaddrs(t, o.Addrs(), []ma.Multiaddr{observedQuic, inferredWebTransport}) { t.Fatalf("address removed too earyl %v %v", o.Addrs(), observedQuic) } @@ -241,8 +248,8 @@ func TestObservedAddrManager(t *testing.T) { o.Record(ob1[N-1], observedQuic1) o.Record(ob2[N-1], observedQuic2) require.EventuallyWithT(t, func(t *assert.CollectT) { - addrsEqual(t, o.Addrs(), []ma.Multiaddr{observedQuic1, observedQuic2, inferredWebTransport1, inferredWebTransport2}) - addrsEqual(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{inferredWebTransport1, inferredWebTransport2}) + matest.AssertEqualMultiaddrs(t, o.Addrs(), []ma.Multiaddr{observedQuic1, observedQuic2, inferredWebTransport1, inferredWebTransport2}) + matest.AssertEqualMultiaddrs(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{inferredWebTransport1, inferredWebTransport2}) }, 2*time.Second, 100*time.Millisecond) // Now disconnect first observer group @@ -250,7 +257,7 @@ func TestObservedAddrManager(t *testing.T) { o.removeConn(ob1[i]) } time.Sleep(100 * time.Millisecond) - if !addrsEqual(t, o.Addrs(), []ma.Multiaddr{observedQuic2, inferredWebTransport2}) { + if !matest.AssertEqualMultiaddrs(t, o.Addrs(), []ma.Multiaddr{observedQuic2, inferredWebTransport2}) { t.Fatalf("address removed too early %v %v", o.Addrs(), observedQuic2) } @@ -286,24 +293,24 @@ func TestObservedAddrManager(t *testing.T) { } require.EventuallyWithT(t, func(t *assert.CollectT) { - addrsEqual(t, o.Addrs(), []ma.Multiaddr{observedQuic, observedWebTransport}) + matest.AssertEqualMultiaddrs(t, o.Addrs(), []ma.Multiaddr{observedQuic, observedWebTransport}) }, 1*time.Second, 100*time.Millisecond) tw, err := thinWaistForm(quic4ListenAddr) require.NoError(t, err) require.Less(t, len(o.externalAddrs[string(tw.TW.Bytes())]), 2) - require.Equal(t, []ma.Multiaddr{observedWebTransport}, o.AddrsFor(webTransport4ListenAddr)) - require.Equal(t, []ma.Multiaddr{observedQuic}, o.AddrsFor(quic4ListenAddr)) - require.ElementsMatch(t, []ma.Multiaddr{observedQuic, observedWebTransport}, o.Addrs()) + requireEqualAddrs(t, []ma.Multiaddr{observedWebTransport}, o.AddrsFor(webTransport4ListenAddr)) + requireEqualAddrs(t, []ma.Multiaddr{observedQuic}, o.AddrsFor(quic4ListenAddr)) + requireAddrsMatch(t, []ma.Multiaddr{observedQuic, observedWebTransport}, o.Addrs()) for i := 0; i < 3; i++ { // remove non-recorded connection o.removeConn(c6) } - require.Equal(t, []ma.Multiaddr{observedWebTransport}, o.AddrsFor(webTransport4ListenAddr)) - require.Equal(t, []ma.Multiaddr{observedQuic}, o.AddrsFor(quic4ListenAddr)) - require.ElementsMatch(t, []ma.Multiaddr{observedQuic, observedWebTransport}, o.Addrs()) + requireEqualAddrs(t, []ma.Multiaddr{observedWebTransport}, o.AddrsFor(webTransport4ListenAddr)) + requireEqualAddrs(t, []ma.Multiaddr{observedQuic}, o.AddrsFor(quic4ListenAddr)) + requireAddrsMatch(t, []ma.Multiaddr{observedQuic, observedWebTransport}, o.Addrs()) o.removeConn(c1) o.removeConn(c2) @@ -365,7 +372,7 @@ func TestObservedAddrManager(t *testing.T) { allAddrs = append(allAddrs, resQuicAddrs[:]...) allAddrs = append(allAddrs, resWebTransportAddrs[:]...) require.EventuallyWithT(t, func(t *assert.CollectT) { - addrsEqual(t, o.Addrs(), allAddrs) + matest.AssertMultiaddrsMatch(t, o.Addrs(), allAddrs) }, 1*time.Second, 100*time.Millisecond) for i := 0; i < N; i++ { @@ -391,7 +398,7 @@ func TestObservedAddrManager(t *testing.T) { o.Record(c3, observedWebTransport) o.Record(c4, observedWebTransport) require.EventuallyWithT(t, func(t *assert.CollectT) { - addrsEqual(t, o.Addrs(), []ma.Multiaddr{observedWebTransport, inferredQUIC}) + matest.AssertEqualMultiaddrs(t, o.Addrs(), []ma.Multiaddr{observedWebTransport, inferredQUIC}) }, 1*time.Second, 100*time.Millisecond) o.removeConn(c1) o.removeConn(c2) @@ -415,8 +422,8 @@ func TestObservedAddrManager(t *testing.T) { time.Sleep(10 * time.Millisecond) } require.EventuallyWithT(t, func(t *assert.CollectT) { - addrsEqual(t, o.Addrs(), []ma.Multiaddr{observedWebTransport, inferredQUIC}) - addrsEqual(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{inferredQUIC}) + matest.AssertEqualMultiaddrs(t, o.Addrs(), []ma.Multiaddr{observedWebTransport, inferredQUIC}) + matest.AssertEqualMultiaddrs(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{inferredQUIC}) }, 1*time.Second, 100*time.Millisecond) tcpNAT, udpNAT := o.getNATType() @@ -499,8 +506,8 @@ func TestObservedAddrManager(t *testing.T) { time.Sleep(10 * time.Millisecond) } require.EventuallyWithT(t, func(t *assert.CollectT) { - addrsEqual(t, o.Addrs(), []ma.Multiaddr{observedWebTransport, inferredQUIC}) - addrsEqual(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{inferredQUIC}) + matest.AssertEqualMultiaddrs(t, o.Addrs(), []ma.Multiaddr{observedWebTransport, inferredQUIC}) + matest.AssertEqualMultiaddrs(t, o.appendInferredAddrs(nil, nil), []ma.Multiaddr{inferredQUIC}) }, 1*time.Second, 100*time.Millisecond) var e interface{} @@ -588,7 +595,7 @@ func TestObservedAddrManager(t *testing.T) { allAddrs = append(allAddrs, resQuicAddrs[:]...) allAddrs = append(allAddrs, resWebTransportAddrs[:]...) require.EventuallyWithT(t, func(t *assert.CollectT) { - addrsEqual(t, o.Addrs(), allAddrs) + matest.AssertMultiaddrsMatch(t, o.Addrs(), allAddrs) }, 1*time.Second, 100*time.Millisecond) for i := 0; i < N; i++ { diff --git a/p2p/test/transport/gating_test.go b/p2p/test/transport/gating_test.go index a26378357a..52f6477c69 100644 --- a/p2p/test/transport/gating_test.go +++ b/p2p/test/transport/gating_test.go @@ -16,6 +16,7 @@ import ( "github.com/libp2p/go-libp2p-testing/race" ma "github.com/multiformats/go-multiaddr" + "github.com/multiformats/go-multiaddr/matest" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ) @@ -32,16 +33,16 @@ func normalize(addr ma.Multiaddr) ma.Multiaddr { } // replace /wss with /tls/ws - components := []ma.Multiaddr{} + var components ma.Multiaddr ma.ForEach(addr, func(c ma.Component) bool { if c.Protocol().Code == ma.P_WSS { - components = append(components, ma.StringCast("/tls/ws")) + components = append(components, ma.StringCast("/tls/ws")...) } else { - components = append(components, &c) + components = append(components, c) } return true }) - return ma.Join(components...) + return components } func addrPort(addr ma.Multiaddr) netip.AddrPort { @@ -101,7 +102,7 @@ func TestInterceptAddrDial(t *testing.T) { defer cancel() gomock.InOrder( connGater.EXPECT().InterceptPeerDial(h2.ID()).Return(true), - connGater.EXPECT().InterceptAddrDial(h2.ID(), h2.Addrs()[0]), + connGater.EXPECT().InterceptAddrDial(h2.ID(), matest.MultiaddrMatcher{Multiaddr: h2.Addrs()[0]}), ) require.ErrorIs(t, h1.Connect(ctx, peer.AddrInfo{ID: h2.ID(), Addrs: h2.Addrs()}), swarm.ErrNoGoodAddresses) }) @@ -165,7 +166,8 @@ func TestInterceptUpgradedOutgoing(t *testing.T) { connGater.EXPECT().InterceptAddrDial(h2.ID(), gomock.Any()).Return(true), connGater.EXPECT().InterceptSecured(network.DirOutbound, h2.ID(), gomock.Any()).Return(true), connGater.EXPECT().InterceptUpgraded(gomock.Any()).Do(func(c network.Conn) { - require.Equal(t, normalize(h2.Addrs()[0]), normalize(c.RemoteMultiaddr())) + // remove the certhash component from WebTransport addresses + require.Equal(t, normalize(h2.Addrs()[0]).String(), normalize(c.RemoteMultiaddr()).String()) require.Equal(t, h1.ID(), c.LocalPeer()) require.Equal(t, h2.ID(), c.RemotePeer()) })) @@ -207,7 +209,8 @@ func TestInterceptAccept(t *testing.T) { }) } else { connGater.EXPECT().InterceptAccept(gomock.Any()).Do(func(addrs network.ConnMultiaddrs) { - require.Equal(t, normalize(h2.Addrs()[0]), normalize(addrs.LocalMultiaddr())) + // remove the certhash component from WebTransport addresses + matest.AssertEqualMultiaddr(t, normalize(h2.Addrs()[0]), normalize(addrs.LocalMultiaddr())) }) } @@ -244,7 +247,8 @@ func TestInterceptSecuredIncoming(t *testing.T) { gomock.InOrder( connGater.EXPECT().InterceptAccept(gomock.Any()).Return(true), connGater.EXPECT().InterceptSecured(network.DirInbound, h1.ID(), gomock.Any()).Do(func(_ network.Direction, _ peer.ID, addrs network.ConnMultiaddrs) { - require.Equal(t, normalize(h2.Addrs()[0]), normalize(addrs.LocalMultiaddr())) + // remove the certhash component from WebTransport addresses + matest.AssertEqualMultiaddr(t, normalize(h2.Addrs()[0]), normalize(addrs.LocalMultiaddr())) }), ) h1.Peerstore().AddAddrs(h2.ID(), h2.Addrs(), time.Hour) @@ -277,7 +281,8 @@ func TestInterceptUpgradedIncoming(t *testing.T) { connGater.EXPECT().InterceptAccept(gomock.Any()).Return(true), connGater.EXPECT().InterceptSecured(network.DirInbound, h1.ID(), gomock.Any()).Return(true), connGater.EXPECT().InterceptUpgraded(gomock.Any()).Do(func(c network.Conn) { - require.Equal(t, normalize(h2.Addrs()[0]), normalize(c.LocalMultiaddr())) + // remove the certhash component from WebTransport addresses + require.Equal(t, normalize(h2.Addrs()[0]).String(), normalize(c.LocalMultiaddr()).String()) require.Equal(t, h1.ID(), c.RemotePeer()) require.Equal(t, h2.ID(), c.LocalPeer()) }), diff --git a/p2p/test/transport/rcmgr_test.go b/p2p/test/transport/rcmgr_test.go index c19a05dfc1..9a6a09b87d 100644 --- a/p2p/test/transport/rcmgr_test.go +++ b/p2p/test/transport/rcmgr_test.go @@ -15,6 +15,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/p2p/protocol/identify" "github.com/libp2p/go-libp2p/p2p/protocol/ping" + "github.com/multiformats/go-multiaddr/matest" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" @@ -40,13 +41,13 @@ func TestResourceManagerIsUsed(t *testing.T) { var listener, dialer host.Host var expectedPeer peer.ID var expectedDir network.Direction - var expectedAddr interface{} + var expectedAddr gomock.Matcher if testDialer { listener = tc.HostGenerator(t, TransportTestCaseOpts{NoRcmgr: true}) dialer = tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true, ResourceManager: rcmgr}) expectedPeer = listener.ID() expectedDir = network.DirOutbound - expectedAddr = listener.Addrs()[0] + expectedAddr = matest.MultiaddrMatcher{Multiaddr: listener.Addrs()[0]} } else { listener = tc.HostGenerator(t, TransportTestCaseOpts{ResourceManager: rcmgr}) dialer = tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true, NoRcmgr: true}) diff --git a/p2p/transport/quic/cmd/lib/lib_test.go b/p2p/transport/quic/cmd/lib/lib_test.go index 1058b078e7..2175874322 100644 --- a/p2p/transport/quic/cmd/lib/lib_test.go +++ b/p2p/transport/quic/cmd/lib/lib_test.go @@ -17,13 +17,14 @@ func TestCmd(t *testing.T) { if ip.Protocol().Code == multiaddr.P_IP4 && ip.Value() == "0.0.0.0" { // Windows can't dial to 0.0.0.0 so replace with localhost var err error - ip, err = multiaddr.NewComponent("ip4", "127.0.0.1") + c, err := multiaddr.NewComponent("ip4", "127.0.0.1") if err != nil { t.Fatal(err) } + ip = c } - err := RunClient(multiaddr.Join(ip, rest).String(), l.ID.String()) + err := RunClient(ip.Encapsulate(rest).String(), l.ID.String()) if err != nil { t.Fatal(err) } diff --git a/p2p/transport/quicreuse/quic_multiaddr.go b/p2p/transport/quicreuse/quic_multiaddr.go index 85b282df2e..af16547357 100644 --- a/p2p/transport/quicreuse/quic_multiaddr.go +++ b/p2p/transport/quicreuse/quic_multiaddr.go @@ -28,17 +28,17 @@ func ToQuicMultiaddr(na net.Addr, version quic.Version) (ma.Multiaddr, error) { func FromQuicMultiaddr(addr ma.Multiaddr) (*net.UDPAddr, quic.Version, error) { var version quic.Version - var partsBeforeQUIC []ma.Multiaddr - ma.ForEach(addr, func(c ma.Component) bool { + partsBeforeQUIC := make([]ma.Component, 0, 2) +loop: + for _, c := range addr { switch c.Protocol().Code { case ma.P_QUIC_V1: version = quic.Version1 - return false + break loop default: - partsBeforeQUIC = append(partsBeforeQUIC, &c) - return true + partsBeforeQUIC = append(partsBeforeQUIC, c) } - }) + } if len(partsBeforeQUIC) == 0 { return nil, version, errors.New("no addr before QUIC component") } @@ -46,7 +46,7 @@ func FromQuicMultiaddr(addr ma.Multiaddr) (*net.UDPAddr, quic.Version, error) { // Not found return nil, version, errors.New("unknown QUIC version") } - netAddr, err := manet.ToNetAddr(ma.Join(partsBeforeQUIC...)) + netAddr, err := manet.ToNetAddr(partsBeforeQUIC) if err != nil { return nil, version, err } diff --git a/p2p/transport/webrtc/transport.go b/p2p/transport/webrtc/transport.go index c54865fc57..6f16fb729d 100644 --- a/p2p/transport/webrtc/transport.go +++ b/p2p/transport/webrtc/transport.go @@ -233,7 +233,7 @@ func (t *WebRTCTransport) listenSocket(socket net.PacketConn) (tpt.Listener, err if err != nil { return nil, err } - listenerMultiaddr = listenerMultiaddr.Encapsulate(webrtcComponent).Encapsulate(certComp) + listenerMultiaddr = listenerMultiaddr.AppendComponent(webrtcComponent, certComp) return newListener( t, @@ -531,7 +531,7 @@ func (t *WebRTCTransport) AddCertHashes(addr ma.Multiaddr) (ma.Multiaddr, bool) if err != nil { return nil, false } - return addr.Encapsulate(certComp), true + return addr.AppendComponent(certComp), true } type netConnWrapper struct { diff --git a/p2p/transport/websocket/addrs.go b/p2p/transport/websocket/addrs.go index 5fea8567b5..6fbd852636 100644 --- a/p2p/transport/websocket/addrs.go +++ b/p2p/transport/websocket/addrs.go @@ -141,13 +141,13 @@ type parsedWebsocketMultiaddr struct { func parseWebsocketMultiaddr(a ma.Multiaddr) (parsedWebsocketMultiaddr, error) { out := parsedWebsocketMultiaddr{} // First check if we have a WSS component. If so we'll canonicalize it into a /tls/ws - withoutWss := a.Decapsulate(wssComponent) + withoutWss := a.Decapsulate(wssComponent.Multiaddr()) if !withoutWss.Equal(a) { - a = withoutWss.Encapsulate(tlsWsComponent) + a = withoutWss.Encapsulate(tlsWsAddr) } // Remove the ws component - withoutWs := a.Decapsulate(wsComponent) + withoutWs := a.Decapsulate(wsComponent.Multiaddr()) if withoutWs.Equal(a) { return out, fmt.Errorf("not a websocket multiaddr") } @@ -158,7 +158,7 @@ func parseWebsocketMultiaddr(a ma.Multiaddr) (parsedWebsocketMultiaddr, error) { for { var head *ma.Component rest, head = ma.SplitLast(rest) - if head == nil || rest == nil { + if head == nil || len(rest) == 0 { break } diff --git a/p2p/transport/websocket/listener.go b/p2p/transport/websocket/listener.go index 93131a2e07..e72e7dabd3 100644 --- a/p2p/transport/websocket/listener.go +++ b/p2p/transport/websocket/listener.go @@ -40,14 +40,14 @@ type listener struct { func (pwma *parsedWebsocketMultiaddr) toMultiaddr() ma.Multiaddr { if !pwma.isWSS { - return pwma.restMultiaddr.Encapsulate(wsComponent) + return pwma.restMultiaddr.AppendComponent(wsComponent) } if pwma.sni == nil { - return pwma.restMultiaddr.Encapsulate(tlsComponent).Encapsulate(wsComponent) + return pwma.restMultiaddr.AppendComponent(tlsComponent, wsComponent) } - return pwma.restMultiaddr.Encapsulate(tlsComponent).Encapsulate(pwma.sni).Encapsulate(wsComponent) + return pwma.restMultiaddr.AppendComponent(tlsComponent, pwma.sni, wsComponent) } // newListener creates a new listener from a raw net.Listener. diff --git a/p2p/transport/websocket/websocket.go b/p2p/transport/websocket/websocket.go index 97402b9a3b..0ddf19050e 100644 --- a/p2p/transport/websocket/websocket.go +++ b/p2p/transport/websocket/websocket.go @@ -39,10 +39,10 @@ var dialMatcher = mafmt.And( mafmt.Base(ma.P_WSS))) var ( - wssComponent = ma.StringCast("/wss") - tlsWsComponent = ma.StringCast("/tls/ws") - tlsComponent = ma.StringCast("/tls") - wsComponent = ma.StringCast("/ws") + wssComponent, _ = ma.NewComponent("wss", "") + tlsComponent, _ = ma.NewComponent("tls", "") + wsComponent, _ = ma.NewComponent("ws", "") + tlsWsAddr = ma.Multiaddr{*tlsComponent, *wsComponent} ) func init() { @@ -138,15 +138,15 @@ func (t *WebsocketTransport) Resolve(_ context.Context, maddr ma.Multiaddr) ([]m if parsed.sni == nil { var err error // We don't have an sni component, we'll use dns - ma.ForEach(parsed.restMultiaddr, func(c ma.Component) bool { + loop: + for _, c := range parsed.restMultiaddr { switch c.Protocol().Code { case ma.P_DNS, ma.P_DNS4, ma.P_DNS6: // err shouldn't happen since this means we couldn't parse a dns hostname for an sni value. parsed.sni, err = ma.NewComponent("sni", c.Value()) - return false + break loop } - return true - }) + } if err != nil { return nil, err } diff --git a/p2p/transport/websocket/websocket_test.go b/p2p/transport/websocket/websocket_test.go index b112ebaea4..f83576ba2f 100644 --- a/p2p/transport/websocket/websocket_test.go +++ b/p2p/transport/websocket/websocket_test.go @@ -82,7 +82,7 @@ func newSecureMuxer(t *testing.T) (peer.ID, []sec.SecureTransport) { return id, []sec.SecureTransport{noiseTpt} } -func lastComponent(t *testing.T, a ma.Multiaddr) ma.Multiaddr { +func lastComponent(t *testing.T, a ma.Multiaddr) *ma.Component { t.Helper() _, wscomponent := ma.SplitLast(a) require.NotNil(t, wscomponent) @@ -335,7 +335,7 @@ func connectAndExchangeData(t *testing.T, laddr ma.Multiaddr, secure bool) { if secure { require.Contains(t, l.Multiaddr().String(), "tls") } else { - require.Equal(t, lastComponent(t, l.Multiaddr()), wsComponent) + require.Equal(t, lastComponent(t, l.Multiaddr()).String(), wsComponent.String()) } defer l.Close() @@ -428,8 +428,8 @@ func TestWebsocketListenSecureAndInsecure(t *testing.T) { conn, err := client.Dial(context.Background(), lnSecure.Multiaddr(), serverID) require.NoError(t, err) defer conn.Close() - require.Equal(t, lastComponent(t, conn.RemoteMultiaddr()), wssComponent) - require.Equal(t, lastComponent(t, conn.LocalMultiaddr()), wssComponent) + require.Equal(t, lastComponent(t, conn.RemoteMultiaddr()).String(), wssComponent.String()) + require.Equal(t, lastComponent(t, conn.LocalMultiaddr()).String(), wssComponent.String()) // dialing the insecure address should fail _, err = client.Dial(context.Background(), lnInsecure.Multiaddr(), serverID) diff --git a/p2p/transport/webtransport/cert_manager.go b/p2p/transport/webtransport/cert_manager.go index 4401175363..494d5e7616 100644 --- a/p2p/transport/webtransport/cert_manager.go +++ b/p2p/transport/webtransport/cert_manager.go @@ -191,16 +191,18 @@ func (m *certManager) cacheSerializedCertHashes() error { } func (m *certManager) cacheAddrComponent() error { - addr, err := addrComponentForCert(m.currentConfig.sha256[:]) + var addr ma.Multiaddr + c, err := addrComponentForCert(m.currentConfig.sha256[:]) if err != nil { return err } + addr = addr.AppendComponent(c) if m.nextConfig != nil { comp, err := addrComponentForCert(m.nextConfig.sha256[:]) if err != nil { return err } - addr = addr.Encapsulate(comp) + addr = addr.AppendComponent(comp) } m.addrComp = addr return nil diff --git a/p2p/transport/webtransport/multiaddr.go b/p2p/transport/webtransport/multiaddr.go index bd90638b63..6b7b37f487 100644 --- a/p2p/transport/webtransport/multiaddr.go +++ b/p2p/transport/webtransport/multiaddr.go @@ -64,7 +64,7 @@ func extractCertHashes(addr ma.Multiaddr) ([]multihash.DecodedMultihash, error) return certHashes, nil } -func addrComponentForCert(hash []byte) (ma.Multiaddr, error) { +func addrComponentForCert(hash []byte) (*ma.Component, error) { mh, err := multihash.Encode(hash, multihash.SHA2_256) if err != nil { return nil, err diff --git a/p2p/transport/webtransport/transport.go b/p2p/transport/webtransport/transport.go index 0e35b44398..8818c7b8a7 100644 --- a/p2p/transport/webtransport/transport.go +++ b/p2p/transport/webtransport/transport.go @@ -414,12 +414,21 @@ func (t *transport) Resolve(_ context.Context, maddr ma.Multiaddr) ([]ma.Multiad beforeQuicMA, afterIncludingQuicMA := ma.SplitFunc(maddr, func(c ma.Component) bool { return c.Protocol().Code == ma.P_QUIC_V1 }) + if len(afterIncludingQuicMA) == 0 { + return nil, fmt.Errorf("no quic component found in %s", maddr) + } quicComponent, afterQuicMA := ma.SplitFirst(afterIncludingQuicMA) + if quicComponent == nil { + // Should not happen since we split on P_QUIC_V1 already + return nil, fmt.Errorf("no quic component found in %s", maddr) + } sniComponent, err := ma.NewComponent(ma.ProtocolWithCode(ma.P_SNI).Name, sni) if err != nil { return nil, err } - return []ma.Multiaddr{beforeQuicMA.Encapsulate(quicComponent).Encapsulate(sniComponent).Encapsulate(afterQuicMA)}, nil + result := beforeQuicMA.AppendComponent(quicComponent, sniComponent) + result = append(result, afterQuicMA...) + return []ma.Multiaddr{result}, nil } // AddCertHashes adds the current certificate hashes to a multiaddress. diff --git a/p2p/transport/webtransport/transport_test.go b/p2p/transport/webtransport/transport_test.go index 9eda2810a5..38968b110d 100644 --- a/p2p/transport/webtransport/transport_test.go +++ b/p2p/transport/webtransport/transport_test.go @@ -84,7 +84,7 @@ func stripCertHashes(addr ma.Multiaddr) ma.Multiaddr { } // create a /certhash multiaddr component using the SHA256 of foobar -func getCerthashComponent(t *testing.T, b []byte) ma.Multiaddr { +func getCerthashComponent(t *testing.T, b []byte) *ma.Component { t.Helper() h := sha256.Sum256(b) mh, err := multihash.Encode(h[:], multihash.SHA2_256) @@ -133,7 +133,7 @@ func TestTransport(t *testing.T) { require.NoError(t, err) _, port, err := net.SplitHostPort(addr) require.NoError(t, err) - require.Equal(t, ma.StringCast(fmt.Sprintf("/ip4/127.0.0.1/udp/%s/quic-v1/webtransport", port)), conn.RemoteMultiaddr()) + require.Equal(t, fmt.Sprintf("/ip4/127.0.0.1/udp/%s/quic-v1/webtransport", port), conn.RemoteMultiaddr().String()) addrChan <- conn.RemoteMultiaddr() }() @@ -145,7 +145,7 @@ func TestTransport(t *testing.T) { data, err := io.ReadAll(str) require.NoError(t, err) require.Equal(t, "foobar", string(data)) - require.Equal(t, <-addrChan, conn.LocalMultiaddr()) + require.Equal(t, (<-addrChan).String(), conn.LocalMultiaddr().String()) require.NoError(t, conn.Close()) require.True(t, conn.IsClosed()) } @@ -381,7 +381,7 @@ func TestConnectionGaterDialing(t *testing.T) { defer ln.Close() connGater.EXPECT().InterceptSecured(network.DirOutbound, serverID, gomock.Any()).Do(func(_ network.Direction, _ peer.ID, addrs network.ConnMultiaddrs) { - require.Equal(t, stripCertHashes(ln.Multiaddr()), addrs.RemoteMultiaddr()) + require.Equal(t, stripCertHashes(ln.Multiaddr()).String(), addrs.RemoteMultiaddr().String()) }) _, key := newIdentity(t) cl, err := libp2pwebtransport.New(key, nil, newConnManager(t), connGater, &network.NullResourceManager{}) @@ -405,8 +405,8 @@ func TestConnectionGaterInterceptAccept(t *testing.T) { defer ln.Close() connGater.EXPECT().InterceptAccept(gomock.Any()).Do(func(addrs network.ConnMultiaddrs) { - require.Equal(t, stripCertHashes(ln.Multiaddr()), addrs.LocalMultiaddr()) - require.NotEqual(t, stripCertHashes(ln.Multiaddr()), addrs.RemoteMultiaddr()) + require.Equal(t, stripCertHashes(ln.Multiaddr()).String(), addrs.LocalMultiaddr().String()) + require.NotEqual(t, stripCertHashes(ln.Multiaddr()).String(), addrs.RemoteMultiaddr().String()) }) _, key := newIdentity(t) @@ -437,8 +437,8 @@ func TestConnectionGaterInterceptSecured(t *testing.T) { connGater.EXPECT().InterceptAccept(gomock.Any()).Return(true) connGater.EXPECT().InterceptSecured(network.DirInbound, clientID, gomock.Any()).Do(func(_ network.Direction, _ peer.ID, addrs network.ConnMultiaddrs) { - require.Equal(t, stripCertHashes(ln.Multiaddr()), addrs.LocalMultiaddr()) - require.NotEqual(t, stripCertHashes(ln.Multiaddr()), addrs.RemoteMultiaddr()) + require.Equal(t, stripCertHashes(ln.Multiaddr()).String(), addrs.LocalMultiaddr().String()) + require.NotEqual(t, stripCertHashes(ln.Multiaddr()).String(), addrs.RemoteMultiaddr().String()) }) // The handshake will complete, but the server will immediately close the connection. conn, err := cl.Dial(context.Background(), ln.Multiaddr(), serverID) @@ -597,16 +597,12 @@ func TestFlowControlWindowIncrease(t *testing.T) { defer tr2.(io.Closer).Close() var addr ma.Multiaddr - for _, comp := range ma.Split(ln.Multiaddr()) { + for _, comp := range ln.Multiaddr() { if _, err := comp.ValueForProtocol(ma.P_UDP); err == nil { addr = addr.Encapsulate(ma.StringCast(fmt.Sprintf("/udp/%d", proxy.LocalAddr().(*net.UDPAddr).Port))) continue } - if addr == nil { - addr = comp - continue - } - addr = addr.Encapsulate(comp) + addr = append(addr, comp) } conn, err := tr2.Dial(context.Background(), addr, serverID) diff --git a/test-plans/go.mod b/test-plans/go.mod index 1216be75f5..8555b45eef 100644 --- a/test-plans/go.mod +++ b/test-plans/go.mod @@ -5,7 +5,7 @@ go 1.23 require ( github.com/go-redis/redis/v8 v8.11.5 github.com/libp2p/go-libp2p v0.0.0 - github.com/multiformats/go-multiaddr v0.14.0 + github.com/multiformats/go-multiaddr v0.15.0 ) require ( diff --git a/test-plans/go.sum b/test-plans/go.sum index 54e929b91f..4bb35cd8d3 100644 --- a/test-plans/go.sum +++ b/test-plans/go.sum @@ -180,8 +180,8 @@ github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYg github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.14.0 h1:bfrHrJhrRuh/NXH5mCnemjpbGjzRw/b+tJFOD41g2tU= -github.com/multiformats/go-multiaddr v0.14.0/go.mod h1:6EkVAxtznq2yC3QT5CM1UTAwG0GTP3EWAIcjHuzQ+r4= +github.com/multiformats/go-multiaddr v0.15.0 h1:zB/HeaI/apcZiTDwhY5YqMvNVl/oQYvs3XySU+qeAVo= +github.com/multiformats/go-multiaddr v0.15.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M= github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=