diff --git a/apps/wakunode2/app.nim b/apps/wakunode2/app.nim index 08dfffa7db..e8cbdbf154 100644 --- a/apps/wakunode2/app.nim +++ b/apps/wakunode2/app.nim @@ -526,6 +526,12 @@ proc setupProtocols(node: WakuNode, conf: WakuNodeConf, notice "routing only signed traffic", protectedTopic=topicKey.topic, publicKey=topicKey.key node.wakuRelay.addSignedTopicValidator(Pubsubtopic(topicKey.topic), topicKey.key) + # Enable Rendezvous Discovery protocol when Relay is enabled + try: + await mountRendezvous(node) + except CatchableError: + return err("failed to mount waku rendezvous protocol: " & getCurrentExceptionMsg()) + # Keepalive mounted on all nodes try: await mountLibp2pPing(node) diff --git a/tests/all_tests_v2.nim b/tests/all_tests_v2.nim index f60095a976..f071674476 100644 --- a/tests/all_tests_v2.nim +++ b/tests/all_tests_v2.nim @@ -62,6 +62,7 @@ import ./v2/test_waku_noise, ./v2/test_waku_noise_sessions, ./v2/test_waku_switch, + ./v2/test_waku_rendezvous, # Utils ./v2/test_utils_compat diff --git a/tests/v2/test_waku_rendezvous.nim b/tests/v2/test_waku_rendezvous.nim new file mode 100644 index 0000000000..7b3950e621 --- /dev/null +++ b/tests/v2/test_waku_rendezvous.nim @@ -0,0 +1,59 @@ +{.used.} + +import + chronos, + testutils/unittests, + libp2p, + libp2p/protocols/rendezvous + +import + ../../waku/v2/node/waku_switch, + ./testlib/common, + ./testlib/wakucore + +proc newRendezvousClientSwitch(rdv: RendezVous): Switch = + SwitchBuilder.new() + .withRng(rng()) + .withAddresses(@[MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet()]) + .withTcpTransport() + .withMplex() + .withNoise() + .withRendezVous(rdv) + .build() + +procSuite "Waku Rendezvous": + asyncTest "Waku Switch uses Rendezvous": + ## Setup + + let + wakuClient = RendezVous.new() + sourceClient = RendezVous.new() + destClient = RendezVous.new() + wakuSwitch = newRendezvousClientSwitch(wakuClient) #rendezvous point + sourceSwitch = newRendezvousClientSwitch(sourceClient) #client + destSwitch = newRendezvousClientSwitch(destClient) #client + + # Setup client rendezvous + wakuClient.setup(wakuSwitch) + sourceClient.setup(sourceSwitch) + destClient.setup(destSwitch) + + await allFutures(wakuSwitch.start(), sourceSwitch.start(), destSwitch.start()) + + # Connect clients to the rendezvous point + await sourceSwitch.connect(wakuSwitch.peerInfo.peerId, wakuSwitch.peerInfo.addrs) + await destSwitch.connect(wakuSwitch.peerInfo.peerId, wakuSwitch.peerInfo.addrs) + + let res0 = await sourceClient.request("empty") + check res0.len == 0 + + # Check that source client gets peer info of dest client from rendezvous point + await sourceClient.advertise("foo") + let res1 = await destClient.request("foo") + check: + res1.len == 1 + res1[0] == sourceSwitch.peerInfo.signedPeerRecord.data + + await allFutures(wakuSwitch.stop(), sourceSwitch.stop(), destSwitch.stop()) + + diff --git a/tests/v2/testlib/wakunode.nim b/tests/v2/testlib/wakunode.nim index 96fdd8dd0e..28e96adab1 100644 --- a/tests/v2/testlib/wakunode.nim +++ b/tests/v2/testlib/wakunode.nim @@ -67,6 +67,7 @@ proc newTestWakuNode*(nodeKey: crypto.PrivateKey, secureKey = if secureKey != "": some(secureKey) else: none(string), secureCert = if secureCert != "": some(secureCert) else: none(string), agentString = agentString, + ) builder.withWakuDiscv5(wakuDiscv5.get(nil)) diff --git a/tests/wakunode2/test_app.nim b/tests/wakunode2/test_app.nim index cdfe52da16..7ea97f28d0 100644 --- a/tests/wakunode2/test_app.nim +++ b/tests/wakunode2/test_app.nim @@ -24,6 +24,8 @@ proc defaultTestWakuNodeConf(): WakuNodeConf = metricsServerAddress: ValidIpAddress.init("127.0.0.1"), nat: "any", maxConnections: 50, + topics: @["/waku/2/default-waku/proto"], + relay: true ) @@ -77,6 +79,7 @@ suite "Wakunode2 - App initialization": node.wakuArchive.isNil() node.wakuStore.isNil() not node.wakuStoreClient.isNil() + not node.rendezvous.isNil() ## Cleanup waitFor wakunode2.stop() diff --git a/waku/v2/node/waku_node.nim b/waku/v2/node/waku_node.nim index 7f8a60c5b9..8d7b86a912 100644 --- a/waku/v2/node/waku_node.nim +++ b/waku/v2/node/waku_node.nim @@ -19,6 +19,7 @@ import libp2p/protocols/pubsub/rpc/messages, libp2p/protocols/connectivity/autonat/client, libp2p/protocols/connectivity/autonat/service, + libp2p/protocols/rendezvous, libp2p/nameresolving/nameresolver, libp2p/builders, libp2p/transports/tcptransport, @@ -101,6 +102,7 @@ type libp2pPing*: Ping rng*: ref rand.HmacDrbgContext wakuDiscv5*: WakuDiscoveryV5 + rendezvous*: RendezVous announcedAddresses* : seq[MultiAddress] started*: bool # Indicates that node has started listening @@ -921,6 +923,16 @@ proc stopDiscv5*(node: WakuNode): Future[bool] {.async.} = debug "Successfully stopped discovery v5 service" +proc mountRendezvous*(node: WakuNode) {.async, raises: [Defect, LPError].} = + info "mounting rendezvous discovery protocol" + + node.rendezvous = RendezVous.new(node.switch) + + if node.started: + await node.rendezvous.start() + + node.switch.mount(node.rendezvous) + proc start*(node: WakuNode) {.async.} = ## Starts a created Waku Node and diff --git a/waku/v2/node/waku_switch.nim b/waku/v2/node/waku_switch.nim index 678f74af96..6fee27cc35 100644 --- a/waku/v2/node/waku_switch.nim +++ b/waku/v2/node/waku_switch.nim @@ -10,6 +10,7 @@ import eth/keys, libp2p/crypto/crypto, libp2p/protocols/pubsub/gossipsub, + libp2p/protocols/rendezvous, libp2p/nameresolving/nameresolver, libp2p/builders, libp2p/switch, @@ -78,6 +79,7 @@ proc newWakuSwitch*( agentString = none(string), # defaults to nim-libp2p version peerStoreCapacity = none(int), # defaults to 1.25 maxConnections services: seq[switch.Service] = @[], + rendezvous: RendezVous = nil, ): Switch {.raises: [Defect, IOError, LPError].} = @@ -119,4 +121,7 @@ proc newWakuSwitch*( if services.len > 0: b = b.withServices(services) + if not rendezvous.isNil(): + b = b.withRendezVous(rendezvous) + b.build()