From f465254d1a519a89f0a52560dfcb9a04b9d35bb3 Mon Sep 17 00:00:00 2001 From: asmit27rai Date: Tue, 23 Sep 2025 03:10:16 +0530 Subject: [PATCH 1/3] integration: add circuit v2 transport integration test --- .../transport/circuitv2_integration_test.go | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 p2p/test/transport/circuitv2_integration_test.go diff --git a/p2p/test/transport/circuitv2_integration_test.go b/p2p/test/transport/circuitv2_integration_test.go new file mode 100644 index 0000000000..3f03cae219 --- /dev/null +++ b/p2p/test/transport/circuitv2_integration_test.go @@ -0,0 +1,116 @@ +package transport_integration + +import ( + "bytes" + "context" + "fmt" + "io" + "testing" + "time" + + libp2p "github.com/libp2p/go-libp2p" + crypto "github.com/libp2p/go-libp2p/core/crypto" + peer "github.com/libp2p/go-libp2p/core/peer" + peerstore "github.com/libp2p/go-libp2p/core/peerstore" + network "github.com/libp2p/go-libp2p/core/network" + + ma "github.com/multiformats/go-multiaddr" +) + +func TestCircuitV2Integration(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + relay, err := libp2p.New( + libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"), + libp2p.EnableRelayService(), + ) + if err != nil { + t.Fatalf("failed to start relay host: %v", err) + } + defer func() { _ = relay.Close() }() + + relayAddrs := relay.Addrs() + if len(relayAddrs) == 0 { + t.Fatalf("relay has no addresses") + } + relayAddr := relayAddrs[0] + + privB, pubB, err := crypto.GenerateKeyPair(crypto.Ed25519, -1) + if err != nil { + t.Fatalf("failed to generate keypair for host B: %v", err) + } + pidB, err := peer.IDFromPublicKey(pubB) + if err != nil { + t.Fatalf("failed to compute peer id from pubkey: %v", err) + } + + relayID := relay.ID() + addrFactory := func(_ []ma.Multiaddr) []ma.Multiaddr { + out := make([]ma.Multiaddr, 0, 1) + relayAddrStr := relayAddr.String() + circuitStr := fmt.Sprintf("%s/p2p/%s/p2p-circuit/p2p/%s", relayAddrStr, relayID.String(), pidB.String()) + maddr, err := ma.NewMultiaddr(circuitStr) + if err != nil { + t.Fatalf("failed to create circuit multiaddr: %v", err) + } + out = append(out, maddr) + return out + } + + hostB, err := libp2p.New( + libp2p.Identity(privB), + libp2p.NoListenAddrs, + libp2p.AddrsFactory(addrFactory), + ) + if err != nil { + t.Fatalf("failed to create host B: %v", err) + } + defer func() { _ = hostB.Close() }() + + hostB.SetStreamHandler("/echo/1.0.0", func(s network.Stream) { + defer s.Close() + _, _ = io.Copy(s, s) + }) + + hostA, err := libp2p.New( + libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"), + ) + if err != nil { + t.Fatalf("failed to create host A: %v", err) + } + defer func() { _ = hostA.Close() }() + + circuitAddrStr := fmt.Sprintf("%s/p2p/%s/p2p-circuit/p2p/%s", relayAddr.String(), relayID.String(), pidB.String()) + circuitAddr, err := ma.NewMultiaddr(circuitAddrStr) + if err != nil { + t.Fatalf("failed to build circuit multiaddr: %v", err) + } + + hostA.Peerstore().AddAddr(pidB, circuitAddr, peerstore.TempAddrTTL) + + pi := peer.AddrInfo{ID: pidB, Addrs: []ma.Multiaddr{circuitAddr}} + if err := hostA.Connect(ctx, pi); err != nil { + t.Fatalf("hostA failed to connect to hostB via relay: %v", err) + } + + stream, err := hostA.NewStream(ctx, pidB, "/echo/1.0.0") + if err != nil { + t.Fatalf("failed to open stream to B via relay: %v", err) + } + defer stream.Close() + + want := []byte("hello over circuitv2") + if _, err := stream.Write(want); err != nil { + t.Fatalf("failed to write to stream: %v", err) + } + _ = stream.CloseWrite() + + got, err := io.ReadAll(stream) + if err != nil { + t.Fatalf("failed to read echo reply: %v", err) + } + + if !bytes.Equal(got, want) { + t.Fatalf("echo mismatch: want=%q got=%q", string(want), string(got)) + } +} From a9056ed248657d7a669175d480115b27d81475dc Mon Sep 17 00:00:00 2001 From: asmit27rai Date: Wed, 24 Sep 2025 01:48:47 +0530 Subject: [PATCH 2/3] test: add circuit-v2 transport to integration tests --- .../transport/circuitv2_integration_test.go | 116 ------------------ p2p/test/transport/transport_test.go | 90 ++++++++++++++ 2 files changed, 90 insertions(+), 116 deletions(-) delete mode 100644 p2p/test/transport/circuitv2_integration_test.go diff --git a/p2p/test/transport/circuitv2_integration_test.go b/p2p/test/transport/circuitv2_integration_test.go deleted file mode 100644 index 3f03cae219..0000000000 --- a/p2p/test/transport/circuitv2_integration_test.go +++ /dev/null @@ -1,116 +0,0 @@ -package transport_integration - -import ( - "bytes" - "context" - "fmt" - "io" - "testing" - "time" - - libp2p "github.com/libp2p/go-libp2p" - crypto "github.com/libp2p/go-libp2p/core/crypto" - peer "github.com/libp2p/go-libp2p/core/peer" - peerstore "github.com/libp2p/go-libp2p/core/peerstore" - network "github.com/libp2p/go-libp2p/core/network" - - ma "github.com/multiformats/go-multiaddr" -) - -func TestCircuitV2Integration(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - relay, err := libp2p.New( - libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"), - libp2p.EnableRelayService(), - ) - if err != nil { - t.Fatalf("failed to start relay host: %v", err) - } - defer func() { _ = relay.Close() }() - - relayAddrs := relay.Addrs() - if len(relayAddrs) == 0 { - t.Fatalf("relay has no addresses") - } - relayAddr := relayAddrs[0] - - privB, pubB, err := crypto.GenerateKeyPair(crypto.Ed25519, -1) - if err != nil { - t.Fatalf("failed to generate keypair for host B: %v", err) - } - pidB, err := peer.IDFromPublicKey(pubB) - if err != nil { - t.Fatalf("failed to compute peer id from pubkey: %v", err) - } - - relayID := relay.ID() - addrFactory := func(_ []ma.Multiaddr) []ma.Multiaddr { - out := make([]ma.Multiaddr, 0, 1) - relayAddrStr := relayAddr.String() - circuitStr := fmt.Sprintf("%s/p2p/%s/p2p-circuit/p2p/%s", relayAddrStr, relayID.String(), pidB.String()) - maddr, err := ma.NewMultiaddr(circuitStr) - if err != nil { - t.Fatalf("failed to create circuit multiaddr: %v", err) - } - out = append(out, maddr) - return out - } - - hostB, err := libp2p.New( - libp2p.Identity(privB), - libp2p.NoListenAddrs, - libp2p.AddrsFactory(addrFactory), - ) - if err != nil { - t.Fatalf("failed to create host B: %v", err) - } - defer func() { _ = hostB.Close() }() - - hostB.SetStreamHandler("/echo/1.0.0", func(s network.Stream) { - defer s.Close() - _, _ = io.Copy(s, s) - }) - - hostA, err := libp2p.New( - libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"), - ) - if err != nil { - t.Fatalf("failed to create host A: %v", err) - } - defer func() { _ = hostA.Close() }() - - circuitAddrStr := fmt.Sprintf("%s/p2p/%s/p2p-circuit/p2p/%s", relayAddr.String(), relayID.String(), pidB.String()) - circuitAddr, err := ma.NewMultiaddr(circuitAddrStr) - if err != nil { - t.Fatalf("failed to build circuit multiaddr: %v", err) - } - - hostA.Peerstore().AddAddr(pidB, circuitAddr, peerstore.TempAddrTTL) - - pi := peer.AddrInfo{ID: pidB, Addrs: []ma.Multiaddr{circuitAddr}} - if err := hostA.Connect(ctx, pi); err != nil { - t.Fatalf("hostA failed to connect to hostB via relay: %v", err) - } - - stream, err := hostA.NewStream(ctx, pidB, "/echo/1.0.0") - if err != nil { - t.Fatalf("failed to open stream to B via relay: %v", err) - } - defer stream.Close() - - want := []byte("hello over circuitv2") - if _, err := stream.Write(want); err != nil { - t.Fatalf("failed to write to stream: %v", err) - } - _ = stream.CloseWrite() - - got, err := io.ReadAll(stream) - if err != nil { - t.Fatalf("failed to read echo reply: %v", err) - } - - if !bytes.Equal(got, want) { - t.Fatalf("echo mismatch: want=%q got=%q", string(want), string(got)) - } -} diff --git a/p2p/test/transport/transport_test.go b/p2p/test/transport/transport_test.go index 9b92dc96c4..c67566356d 100644 --- a/p2p/test/transport/transport_test.go +++ b/p2p/test/transport/transport_test.go @@ -38,6 +38,7 @@ import ( "github.com/libp2p/go-libp2p/p2p/muxer/yamux" "github.com/libp2p/go-libp2p/p2p/net/swarm" "github.com/libp2p/go-libp2p/p2p/protocol/ping" + "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" "github.com/libp2p/go-libp2p/p2p/security/noise" "github.com/libp2p/go-libp2p/p2p/transport/quicreuse" "github.com/libp2p/go-libp2p/p2p/transport/tcp" @@ -353,6 +354,95 @@ var transportsToTest = []TransportTestCase{ return h }, }, + { + Name: "circuit-v2", + HostGenerator: func(t *testing.T, opts TransportTestCaseOpts) host.Host { + ctx := context.Background() + libp2pOpts := transformOpts(opts) + + if opts.NoListen { + libp2pOpts = append(libp2pOpts, + libp2p.NoListenAddrs, + libp2p.EnableRelay(), + ) + h, err := libp2p.New(libp2pOpts...) + require.NoError(t, err) + return h + } else { + relayHost, err := libp2p.New( + libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"), + libp2p.EnableRelay(), + libp2p.EnableRelayService(), + libp2p.ForceReachabilityPublic(), + ) + require.NoError(t, err) + + libp2pOpts = append(libp2pOpts, + libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"), + libp2p.EnableRelay(), + ) + listenerHost, err := libp2p.New(libp2pOpts...) + require.NoError(t, err) + + err = listenerHost.Connect(ctx, peer.AddrInfo{ + ID: relayHost.ID(), + Addrs: relayHost.Addrs(), + }) + require.NoError(t, err) + + _, err = client.Reserve(ctx, listenerHost, peer.AddrInfo{ + ID: relayHost.ID(), + Addrs: relayHost.Addrs(), + }) + require.NoError(t, err) + + relayAddrs := relayHost.Addrs() + require.NotEmpty(t, relayAddrs) + + addrFactory := func([]ma.Multiaddr) []ma.Multiaddr { + var circuitAddrs []ma.Multiaddr + for _, relayAddr := range relayAddrs { + circuitAddr, err := ma.NewMultiaddr(fmt.Sprintf("%s/p2p/%s/p2p-circuit/p2p/%s", + relayAddr.String(), relayHost.ID().String(), listenerHost.ID().String())) + if err == nil { + circuitAddrs = append(circuitAddrs, circuitAddr) + } + } + return circuitAddrs + } + + finalLibp2pOpts := transformOpts(opts) + finalLibp2pOpts = append(finalLibp2pOpts, + libp2p.Identity(listenerHost.Peerstore().PrivKey(listenerHost.ID())), + libp2p.EnableRelay(), + libp2p.AddrsFactory(addrFactory), + libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"), + ) + + finalHost, err := libp2p.New(finalLibp2pOpts...) + require.NoError(t, err) + + err = finalHost.Connect(ctx, peer.AddrInfo{ + ID: relayHost.ID(), + Addrs: relayHost.Addrs(), + }) + require.NoError(t, err) + + _, err = client.Reserve(ctx, finalHost, peer.AddrInfo{ + ID: relayHost.ID(), + Addrs: relayHost.Addrs(), + }) + require.NoError(t, err) + + t.Cleanup(func() { + relayHost.Close() + listenerHost.Close() + }) + + return finalHost + } + }, + }, } func TestPing(t *testing.T) { From 3629d61ef9764b381fa68013ca866ffd95249dbb Mon Sep 17 00:00:00 2001 From: asmit27rai Date: Wed, 24 Sep 2025 03:44:15 +0530 Subject: [PATCH 3/3] fix --- p2p/test/transport/transport_test.go | 74 ++++++---------------------- 1 file changed, 15 insertions(+), 59 deletions(-) diff --git a/p2p/test/transport/transport_test.go b/p2p/test/transport/transport_test.go index c67566356d..044feb7630 100644 --- a/p2p/test/transport/transport_test.go +++ b/p2p/test/transport/transport_test.go @@ -357,7 +357,6 @@ var transportsToTest = []TransportTestCase{ { Name: "circuit-v2", HostGenerator: func(t *testing.T, opts TransportTestCaseOpts) host.Host { - ctx := context.Background() libp2pOpts := transformOpts(opts) if opts.NoListen { @@ -365,82 +364,39 @@ var transportsToTest = []TransportTestCase{ libp2p.NoListenAddrs, libp2p.EnableRelay(), ) - h, err := libp2p.New(libp2pOpts...) - require.NoError(t, err) - return h } else { - relayHost, err := libp2p.New( - libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"), - libp2p.EnableRelay(), - libp2p.EnableRelayService(), - libp2p.ForceReachabilityPublic(), - ) - require.NoError(t, err) - libp2pOpts = append(libp2pOpts, libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"), libp2p.EnableRelay(), ) - listenerHost, err := libp2p.New(libp2pOpts...) - require.NoError(t, err) - - err = listenerHost.Connect(ctx, peer.AddrInfo{ - ID: relayHost.ID(), - Addrs: relayHost.Addrs(), - }) - require.NoError(t, err) - - _, err = client.Reserve(ctx, listenerHost, peer.AddrInfo{ - ID: relayHost.ID(), - Addrs: relayHost.Addrs(), - }) - require.NoError(t, err) - - relayAddrs := relayHost.Addrs() - require.NotEmpty(t, relayAddrs) - - addrFactory := func([]ma.Multiaddr) []ma.Multiaddr { - var circuitAddrs []ma.Multiaddr - for _, relayAddr := range relayAddrs { - circuitAddr, err := ma.NewMultiaddr(fmt.Sprintf("%s/p2p/%s/p2p-circuit/p2p/%s", - relayAddr.String(), relayHost.ID().String(), listenerHost.ID().String())) - if err == nil { - circuitAddrs = append(circuitAddrs, circuitAddr) - } - } - return circuitAddrs - } + } + + h, err := libp2p.New(libp2pOpts...) + require.NoError(t, err) + + if !opts.NoListen { + ctx := context.Background() - finalLibp2pOpts := transformOpts(opts) - finalLibp2pOpts = append(finalLibp2pOpts, - libp2p.Identity(listenerHost.Peerstore().PrivKey(listenerHost.ID())), - libp2p.EnableRelay(), - libp2p.AddrsFactory(addrFactory), + relayHost, err := libp2p.New( libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"), + libp2p.EnableRelay(), + libp2p.EnableRelayService(), + libp2p.ForceReachabilityPublic(), ) - - finalHost, err := libp2p.New(finalLibp2pOpts...) require.NoError(t, err) - err = finalHost.Connect(ctx, peer.AddrInfo{ - ID: relayHost.ID(), - Addrs: relayHost.Addrs(), - }) + err = h.Connect(ctx, peer.AddrInfo{ID: relayHost.ID(), Addrs: relayHost.Addrs()}) require.NoError(t, err) - _, err = client.Reserve(ctx, finalHost, peer.AddrInfo{ - ID: relayHost.ID(), - Addrs: relayHost.Addrs(), - }) + _, err = client.Reserve(ctx, h, peer.AddrInfo{ID: relayHost.ID(), Addrs: relayHost.Addrs()}) require.NoError(t, err) t.Cleanup(func() { relayHost.Close() - listenerHost.Close() }) - - return finalHost } + + return h }, }, }