From 7d1c6abaacba3e05edb57fa177381602b71b9b98 Mon Sep 17 00:00:00 2001 From: Sergei Tikhomirov Date: Thu, 11 Dec 2025 10:51:47 +0100 Subject: [PATCH] chore: do not mount lightpush without relay (fixes #2808) (#3540) * chore: do not mount lightpush without relay (fixes #2808) - Change mountLightPush signature to return Result[void, string] - Return error when relay is not mounted - Update all call sites to handle Result return type - Add test verifying mounting fails without relay - Only advertise lightpush capability when relay is enabled * chore: don't mount legacy lightpush without relay --- apps/chat2/chat2.nim | 4 +- tests/node/test_wakunode_legacy_lightpush.nim | 23 ++++++- tests/node/test_wakunode_lightpush.nim | 23 ++++++- tests/node/test_wakunode_sharding.nim | 8 +-- tests/wakunode_rest/test_rest_lightpush.nim | 2 +- .../test_rest_lightpush_legacy.nim | 2 +- .../conf_builder/waku_conf_builder.nim | 2 +- waku/factory/node_factory.nim | 7 ++- waku/node/kernel_api/lightpush.nim | 61 ++++++++++--------- 9 files changed, 88 insertions(+), 44 deletions(-) diff --git a/apps/chat2/chat2.nim b/apps/chat2/chat2.nim index e2a46ca1b..71d8a4e6a 100644 --- a/apps/chat2/chat2.nim +++ b/apps/chat2/chat2.nim @@ -480,7 +480,9 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} = if conf.lightpushnode != "": let peerInfo = parsePeerInfo(conf.lightpushnode) if peerInfo.isOk(): - await mountLegacyLightPush(node) + (await node.mountLegacyLightPush()).isOkOr: + error "failed to mount legacy lightpush", error = error + quit(QuitFailure) node.mountLegacyLightPushClient() node.peerManager.addServicePeer(peerInfo.value, WakuLightpushCodec) else: diff --git a/tests/node/test_wakunode_legacy_lightpush.nim b/tests/node/test_wakunode_legacy_lightpush.nim index 80e623ce4..4aedd7d4b 100644 --- a/tests/node/test_wakunode_legacy_lightpush.nim +++ b/tests/node/test_wakunode_legacy_lightpush.nim @@ -13,6 +13,7 @@ import node/peer_manager, node/waku_node, node/kernel_api, + node/kernel_api/lightpush, waku_lightpush_legacy, waku_lightpush_legacy/common, waku_lightpush_legacy/protocol_metrics, @@ -56,7 +57,7 @@ suite "Waku Legacy Lightpush - End To End": (await server.mountRelay()).isOkOr: assert false, "Failed to mount relay" - await server.mountLegacyLightpush() # without rln-relay + check (await server.mountLegacyLightpush()).isOk() # without rln-relay client.mountLegacyLightpushClient() serverRemotePeerInfo = server.peerInfo.toRemotePeerInfo() @@ -147,7 +148,7 @@ suite "RLN Proofs as a Lightpush Service": (await server.mountRelay()).isOkOr: assert false, "Failed to mount relay" await server.mountRlnRelay(wakuRlnConfig) - await server.mountLegacyLightPush() + check (await server.mountLegacyLightPush()).isOk() client.mountLegacyLightPushClient() let manager1 = cast[OnchainGroupManager](server.wakuRlnRelay.groupManager) @@ -213,7 +214,7 @@ suite "Waku Legacy Lightpush message delivery": assert false, "Failed to mount relay" (await bridgeNode.mountRelay()).isOkOr: assert false, "Failed to mount relay" - await bridgeNode.mountLegacyLightPush() + check (await bridgeNode.mountLegacyLightPush()).isOk() lightNode.mountLegacyLightPushClient() discard await lightNode.peerManager.dialPeer( @@ -249,3 +250,19 @@ suite "Waku Legacy Lightpush message delivery": ## Cleanup await allFutures(lightNode.stop(), bridgeNode.stop(), destNode.stop()) + +suite "Waku Legacy Lightpush mounting behavior": + asyncTest "fails to mount when relay is not mounted": + ## Given a node without Relay mounted + let + key = generateSecp256k1Key() + node = newTestWakuNode(key, parseIpAddress("0.0.0.0"), Port(0)) + + # Do not mount Relay on purpose + check node.wakuRelay.isNil() + + ## Then mounting Legacy Lightpush must fail + let res = await node.mountLegacyLightPush() + check: + res.isErr() + res.error == MountWithoutRelayError diff --git a/tests/node/test_wakunode_lightpush.nim b/tests/node/test_wakunode_lightpush.nim index 29f72b2cc..7b4da6d4c 100644 --- a/tests/node/test_wakunode_lightpush.nim +++ b/tests/node/test_wakunode_lightpush.nim @@ -13,6 +13,7 @@ import node/peer_manager, node/waku_node, node/kernel_api, + node/kernel_api/lightpush, waku_lightpush, waku_rln_relay, ], @@ -55,7 +56,7 @@ suite "Waku Lightpush - End To End": (await server.mountRelay()).isOkOr: assert false, "Failed to mount relay" - await server.mountLightpush() # without rln-relay + check (await server.mountLightpush()).isOk() # without rln-relay client.mountLightpushClient() serverRemotePeerInfo = server.peerInfo.toRemotePeerInfo() @@ -147,7 +148,7 @@ suite "RLN Proofs as a Lightpush Service": (await server.mountRelay()).isOkOr: assert false, "Failed to mount relay" await server.mountRlnRelay(wakuRlnConfig) - await server.mountLightPush() + check (await server.mountLightPush()).isOk() client.mountLightPushClient() let manager1 = cast[OnchainGroupManager](server.wakuRlnRelay.groupManager) @@ -213,7 +214,7 @@ suite "Waku Lightpush message delivery": assert false, "Failed to mount relay" (await bridgeNode.mountRelay()).isOkOr: assert false, "Failed to mount relay" - await bridgeNode.mountLightPush() + check (await bridgeNode.mountLightPush()).isOk() lightNode.mountLightPushClient() discard await lightNode.peerManager.dialPeer( @@ -251,3 +252,19 @@ suite "Waku Lightpush message delivery": ## Cleanup await allFutures(lightNode.stop(), bridgeNode.stop(), destNode.stop()) + +suite "Waku Lightpush mounting behavior": + asyncTest "fails to mount when relay is not mounted": + ## Given a node without Relay mounted + let + key = generateSecp256k1Key() + node = newTestWakuNode(key, parseIpAddress("0.0.0.0"), Port(0)) + + # Do not mount Relay on purpose + check node.wakuRelay.isNil() + + ## Then mounting Lightpush must fail + let res = await node.mountLightPush() + check: + res.isErr() + res.error == MountWithoutRelayError diff --git a/tests/node/test_wakunode_sharding.nim b/tests/node/test_wakunode_sharding.nim index eefd8f06e..261077e36 100644 --- a/tests/node/test_wakunode_sharding.nim +++ b/tests/node/test_wakunode_sharding.nim @@ -282,7 +282,7 @@ suite "Sharding": asyncTest "lightpush": # Given a connected server and client subscribed to the same pubsub topic client.mountLegacyLightPushClient() - await server.mountLightpush() + check (await server.mountLightpush()).isOk() let topic = "/waku/2/rs/0/1" @@ -405,7 +405,7 @@ suite "Sharding": asyncTest "lightpush (automatic sharding filtering)": # Given a connected server and client using the same content topic (with two different formats) client.mountLegacyLightPushClient() - await server.mountLightpush() + check (await server.mountLightpush()).isOk() let contentTopicShort = "/toychat/2/huilong/proto" @@ -563,7 +563,7 @@ suite "Sharding": asyncTest "lightpush - exclusion (automatic sharding filtering)": # Given a connected server and client using different content topics client.mountLegacyLightPushClient() - await server.mountLightpush() + check (await server.mountLightpush()).isOk() let contentTopic1 = "/toychat/2/huilong/proto" @@ -874,7 +874,7 @@ suite "Sharding": asyncTest "Waku LightPush Sharding (Static Sharding)": # Given a connected server and client using two different pubsub topics client.mountLegacyLightPushClient() - await server.mountLightpush() + check (await server.mountLightpush()).isOk() # Given a connected server and client subscribed to multiple pubsub topics let diff --git a/tests/wakunode_rest/test_rest_lightpush.nim b/tests/wakunode_rest/test_rest_lightpush.nim index cc5c715b8..deba7de22 100644 --- a/tests/wakunode_rest/test_rest_lightpush.nim +++ b/tests/wakunode_rest/test_rest_lightpush.nim @@ -61,7 +61,7 @@ proc init( assert false, "Failed to mount relay: " & $error (await testSetup.serviceNode.mountRelay()).isOkOr: assert false, "Failed to mount relay: " & $error - await testSetup.serviceNode.mountLightPush(rateLimit) + check (await testSetup.serviceNode.mountLightPush(rateLimit)).isOk() testSetup.pushNode.mountLightPushClient() testSetup.serviceNode.peerManager.addServicePeer( diff --git a/tests/wakunode_rest/test_rest_lightpush_legacy.nim b/tests/wakunode_rest/test_rest_lightpush_legacy.nim index 526a6c24e..4043eeed9 100644 --- a/tests/wakunode_rest/test_rest_lightpush_legacy.nim +++ b/tests/wakunode_rest/test_rest_lightpush_legacy.nim @@ -61,7 +61,7 @@ proc init( assert false, "Failed to mount relay" (await testSetup.serviceNode.mountRelay()).isOkOr: assert false, "Failed to mount relay" - await testSetup.serviceNode.mountLegacyLightPush(rateLimit) + check (await testSetup.serviceNode.mountLegacyLightPush(rateLimit)).isOk() testSetup.pushNode.mountLegacyLightPushClient() testSetup.serviceNode.peerManager.addServicePeer( diff --git a/waku/factory/conf_builder/waku_conf_builder.nim b/waku/factory/conf_builder/waku_conf_builder.nim index 645869247..f3f942ecc 100644 --- a/waku/factory/conf_builder/waku_conf_builder.nim +++ b/waku/factory/conf_builder/waku_conf_builder.nim @@ -606,7 +606,7 @@ proc build*( let relayShardedPeerManagement = builder.relayShardedPeerManagement.get(false) let wakuFlags = CapabilitiesBitfield.init( - lightpush = lightPush, + lightpush = lightPush and relay, filter = filterServiceConf.isSome, store = storeServiceConf.isSome, relay = relay, diff --git a/waku/factory/node_factory.nim b/waku/factory/node_factory.nim index 34fc958fe..2cdfdb0d2 100644 --- a/waku/factory/node_factory.nim +++ b/waku/factory/node_factory.nim @@ -368,8 +368,11 @@ proc setupProtocols( # NOTE Must be mounted after relay if conf.lightPush: try: - await mountLightPush(node, node.rateLimitSettings.getSetting(LIGHTPUSH)) - await mountLegacyLightPush(node, node.rateLimitSettings.getSetting(LIGHTPUSH)) + (await mountLightPush(node, node.rateLimitSettings.getSetting(LIGHTPUSH))).isOkOr: + return err("failed to mount waku lightpush protocol: " & $error) + + (await mountLegacyLightPush(node, node.rateLimitSettings.getSetting(LIGHTPUSH))).isOkOr: + return err("failed to mount waku legacy lightpush protocol: " & $error) except CatchableError: return err("failed to mount waku lightpush protocol: " & getCurrentExceptionMsg()) diff --git a/waku/node/kernel_api/lightpush.nim b/waku/node/kernel_api/lightpush.nim index 9451767ac..2a5f6acbb 100644 --- a/waku/node/kernel_api/lightpush.nim +++ b/waku/node/kernel_api/lightpush.nim @@ -34,26 +34,27 @@ import logScope: topics = "waku node lightpush api" +const MountWithoutRelayError* = "cannot mount lightpush because relay is not mounted" + ## Waku lightpush proc mountLegacyLightPush*( node: WakuNode, rateLimit: RateLimitSetting = DefaultGlobalNonRelayRateLimit -) {.async.} = +): Future[Result[void, string]] {.async.} = info "mounting legacy light push" - let pushHandler = - if node.wakuRelay.isNil: - info "mounting legacy lightpush without relay (nil)" - legacy_lightpush_protocol.getNilPushHandler() + if node.wakuRelay.isNil(): + return err(MountWithoutRelayError) + + info "mounting legacy lightpush with relay" + let rlnPeer = + if node.wakuRlnRelay.isNil(): + info "mounting legacy lightpush without rln-relay" + none(WakuRLNRelay) else: - info "mounting legacy lightpush with relay" - let rlnPeer = - if isNil(node.wakuRlnRelay): - info "mounting legacy lightpush without rln-relay" - none(WakuRLNRelay) - else: - info "mounting legacy lightpush with rln-relay" - some(node.wakuRlnRelay) - legacy_lightpush_protocol.getRelayPushHandler(node.wakuRelay, rlnPeer) + info "mounting legacy lightpush with rln-relay" + some(node.wakuRlnRelay) + let pushHandler = + legacy_lightpush_protocol.getRelayPushHandler(node.wakuRelay, rlnPeer) node.wakuLegacyLightPush = WakuLegacyLightPush.new(node.peerManager, node.rng, pushHandler, some(rateLimit)) @@ -64,6 +65,9 @@ proc mountLegacyLightPush*( node.switch.mount(node.wakuLegacyLightPush, protocolMatcher(WakuLegacyLightPushCodec)) + info "legacy lightpush mounted successfully" + return ok() + proc mountLegacyLightPushClient*(node: WakuNode) = info "mounting legacy light push client" @@ -146,23 +150,21 @@ proc legacyLightpushPublish*( proc mountLightPush*( node: WakuNode, rateLimit: RateLimitSetting = DefaultGlobalNonRelayRateLimit -) {.async.} = +): Future[Result[void, string]] {.async.} = info "mounting light push" - let pushHandler = - if node.wakuRelay.isNil(): - info "mounting lightpush v2 without relay (nil)" - lightpush_protocol.getNilPushHandler() + if node.wakuRelay.isNil(): + return err(MountWithoutRelayError) + + info "mounting lightpush with relay" + let rlnPeer = + if node.wakuRlnRelay.isNil(): + info "mounting lightpush without rln-relay" + none(WakuRLNRelay) else: - info "mounting lightpush with relay" - let rlnPeer = - if isNil(node.wakuRlnRelay): - info "mounting lightpush without rln-relay" - none(WakuRLNRelay) - else: - info "mounting lightpush with rln-relay" - some(node.wakuRlnRelay) - lightpush_protocol.getRelayPushHandler(node.wakuRelay, rlnPeer) + info "mounting lightpush with rln-relay" + some(node.wakuRlnRelay) + let pushHandler = lightpush_protocol.getRelayPushHandler(node.wakuRelay, rlnPeer) node.wakuLightPush = WakuLightPush.new( node.peerManager, node.rng, pushHandler, node.wakuAutoSharding, some(rateLimit) @@ -174,6 +176,9 @@ proc mountLightPush*( node.switch.mount(node.wakuLightPush, protocolMatcher(WakuLightPushCodec)) + info "lightpush mounted successfully" + return ok() + proc mountLightPushClient*(node: WakuNode) = info "mounting light push client"