From bacdfe41b68109b9e41103a61a6671604c3761eb Mon Sep 17 00:00:00 2001 From: shash256 <111925100+shash256@users.noreply.github.com> Date: Thu, 30 May 2024 02:34:34 +0400 Subject: [PATCH 1/7] add rlnPeer to LP --- tests/waku_lightpush/test_all.nim | 44 +++++++++++++++++++++++++++++++ waku/node/waku_node.nim | 9 ++++++- waku/waku_lightpush/protocol.nim | 27 ++++++++++++++----- 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/tests/waku_lightpush/test_all.nim b/tests/waku_lightpush/test_all.nim index 4e49809296..3b9b55e7b9 100644 --- a/tests/waku_lightpush/test_all.nim +++ b/tests/waku_lightpush/test_all.nim @@ -1 +1,45 @@ import ./test_client, ./test_ratelimit + +# import std/[unittest, options, times] +# import ../../../waku/[ +# waku_lightpush/protocol, +# waku_rln_relay/rln_relay, +# waku_core, +# node/peer_manager/peer_manager +# ] + +# suite "LightPush with RLN": +# test "handleRequest with valid RLN proof": +# let peerManager = PeerManager() +# let rng = initHmacDrbgContext() +# let rlnPeer = WakuRLNRelay() +# let pushHandler: PushMessageHandler = proc (peerId, topic, msg): Future[Result[void, string]] {.async.} = +# return ok() + +# let wl = WakuLightPush( +# peerManager: peerManager, +# rng: rng, +# pushHandler: pushHandler, +# rlnPeer: rlnPeer, +# ) + +# # Prepare a valid WakuMessage +# let payload = "Hello, Waku!".toBytes() +# let contentTopic = "/waku/2/default-content/proto" +# var message = WakuMessage(payload: payload, contentTopic: contentTopic) + +# # Append RLN proof to the message +# let senderEpochTime = rlnPeer.calcEpoch(epochTime()) +# let appendProofRes = rlnPeer.appendRLNProof(message, senderEpochTime) +# doAssert appendProofRes.isOk(), "Failed to append RLN proof: " & appendProofRes.error + +# # Prepare a valid PushRPC request +# let pushRequest = PushRequest(pubSubTopic: contentTopic, message: message) +# let pushRpc = PushRPC(requestId: "1", request: some(pushRequest)) +# let buffer = pushRpc.encode().buffer + +# # Call handleRequest and check the result +# let result = waitFor wl.handleRequest("peer1", buffer) +# check result.response.isSome +# check result.response.get().isSuccess + diff --git a/waku/node/waku_node.nim b/waku/node/waku_node.nim index 7221e7d8bd..9f8712cb7b 100644 --- a/waku/node/waku_node.nim +++ b/waku/node/waku_node.nim @@ -938,6 +938,13 @@ proc mountLightPush*( peer: PeerId, pubsubTopic: string, message: WakuMessage ): Future[WakuLightPushResult[void]] {.async.} = return err("no waku relay found") + # Ensure the relay is ready before mounting lightpush + elif node.wakuRlnRelay.isNil(): #not await node.wakuRlnRelay.isReady(): + debug "mounting lightpush without rln-relay (nil)" + pushHandler = proc( + peer: PeerId, pubsubTopic: string, message: WakuMessage + ): Future[WakuLightPushResult[void]] {.async.} = + return err("WakuRlnRelay is not ready") else: pushHandler = proc( peer: PeerId, pubsubTopic: string, message: WakuMessage @@ -959,7 +966,7 @@ proc mountLightPush*( debug "mounting lightpush with relay" node.wakuLightPush = - WakuLightPush.new(node.peerManager, node.rng, pushHandler, some(rateLimit)) + WakuLightPush.new(node.peerManager, node.rng, pushHandler, node.wakuRlnRelay, some(rateLimit)) if node.started: # Node has started already. Let's start lightpush too. diff --git a/waku/waku_lightpush/protocol.nim b/waku/waku_lightpush/protocol.nim index 02bca0582b..bd10af6390 100644 --- a/waku/waku_lightpush/protocol.nim +++ b/waku/waku_lightpush/protocol.nim @@ -4,7 +4,7 @@ else: {.push raises: [].} import - std/options, stew/results, stew/byteutils, chronicles, chronos, metrics, bearssl/rand + std/options, std/times, stew/results, stew/byteutils, chronicles, chronos, metrics, bearssl/rand import ../node/peer_manager/peer_manager, ../waku_core, @@ -13,8 +13,8 @@ import ./rpc_codec, ./protocol_metrics, ../common/ratelimit, - ../common/waku_service_metrics - + ../common/waku_service_metrics, + ../waku_rln_relay/rln_relay, ../waku_rln_relay/protocol_types export ratelimit logScope: @@ -25,6 +25,7 @@ type WakuLightPush* = ref object of LPProtocol peerManager*: PeerManager pushHandler*: PushMessageHandler requestRateLimiter*: Option[TokenBucket] + rlnPeer*: WakuRLNRelay proc handleRequest*( wl: WakuLightPush, peerId: PeerId, buffer: seq[byte] @@ -48,7 +49,7 @@ proc handleRequest*( request = pushRpcRequest.request pubSubTopic = request.get().pubSubTopic - message = request.get().message + var message = request.get().message waku_lightpush_messages.inc(labelValues = ["PushRequest"]) debug "push request", peerId = peerId, @@ -56,9 +57,19 @@ proc handleRequest*( pubsubTopic = pubsubTopic, hash = pubsubTopic.computeMessageHash(message).to0xHex() - let handleRes = await wl.pushHandler(peerId, pubsubTopic, message) - isSuccess = handleRes.isOk() - pushResponseInfo = (if isSuccess: "OK" else: handleRes.error) + # Generate and validate RLN proof + let + rlnPeer = wl.rlnPeer + time = getTime().toUnix() + senderEpochTime = float64(time) #rlnPeer.getCurrentEpoch() + appendProofRes = rlnPeer.appendRLNProof(message, senderEpochTime) + + if appendProofRes.isErr(): + pushResponseInfo = "RLN proof generation failed: " & appendProofRes.error + else: + let handleRes = await wl.pushHandler(peerId, pubSubTopic, message) + isSuccess = handleRes.isOk() + pushResponseInfo = (if isSuccess: "OK" else: handleRes.error) if not isSuccess: waku_lightpush_errors.inc(labelValues = [pushResponseInfo]) @@ -106,6 +117,7 @@ proc new*( peerManager: PeerManager, rng: ref rand.HmacDrbgContext, pushHandler: PushMessageHandler, + rlnPeer: WakuRLNRelay, rateLimitSetting: Option[RateLimitSetting] = none[RateLimitSetting](), ): T = let wl = WakuLightPush( @@ -113,6 +125,7 @@ proc new*( peerManager: peerManager, pushHandler: pushHandler, requestRateLimiter: newTokenBucket(rateLimitSetting), + rlnPeer: rlnPeer, ) wl.initProtocolHandler() return wl From 619dee02cac18d816c0405e58b3a357b2d8a0ee8 Mon Sep 17 00:00:00 2001 From: shash256 <111925100+shash256@users.noreply.github.com> Date: Tue, 4 Jun 2024 05:54:31 +0400 Subject: [PATCH 2/7] new proc, mnt rln in e2e test --- tests/node/test_wakunode_lightpush.nim | 21 ++++++++++++- waku/node/waku_node.nim | 17 ++++++----- waku/waku_lightpush/protocol.nim | 41 +++++++++++++++++--------- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/tests/node/test_wakunode_lightpush.nim b/tests/node/test_wakunode_lightpush.nim index 92ef250ebf..af2b1aa926 100644 --- a/tests/node/test_wakunode_lightpush.nim +++ b/tests/node/test_wakunode_lightpush.nim @@ -1,7 +1,7 @@ {.used.} import - std/[options, tables, sequtils], + std/[options, tables, sequtils, tempfiles], stew/shims/net as stewNet, testutils/unittests, chronos, @@ -23,6 +23,7 @@ import waku_lightpush/client, waku_lightpush/protocol_metrics, waku_lightpush/rpc, + waku_rln_relay ], ../testlib/[assertions, common, wakucore, wakunode, testasync, futures, testutils], ../resources/payloads @@ -55,10 +56,28 @@ suite "Waku Lightpush - End To End": server = newTestWakuNode(serverKey, ValidIpAddress.init("0.0.0.0"), Port(0)) client = newTestWakuNode(clientKey, ValidIpAddress.init("0.0.0.0"), Port(0)) + # mount rln-relay + when defined(rln_v2): + let wakuRlnConfig = WakuRlnConfig( + rlnRelayDynamic: false, + rlnRelayCredIndex: some(1.uint), + rlnRelayUserMessageLimit: 1, + rlnEpochSizeSec: 1, + rlnRelayTreePath: genTempPath("rln_tree", "wakunode"), + ) + else: + let wakuRlnConfig = WakuRlnConfig( + rlnRelayDynamic: false, + rlnRelayCredIndex: some(1.uint), + rlnEpochSizeSec: 1, + rlnRelayTreePath: genTempPath("rln_tree", "wakunode"), + ) + await allFutures(server.start(), client.start()) await server.start() await server.mountRelay() + await server.mountRlnRelay(wakuRlnConfig) await server.mountLightpush() client.mountLightpushClient() diff --git a/waku/node/waku_node.nim b/waku/node/waku_node.nim index 9f8712cb7b..767d86cce8 100644 --- a/waku/node/waku_node.nim +++ b/waku/node/waku_node.nim @@ -938,13 +938,6 @@ proc mountLightPush*( peer: PeerId, pubsubTopic: string, message: WakuMessage ): Future[WakuLightPushResult[void]] {.async.} = return err("no waku relay found") - # Ensure the relay is ready before mounting lightpush - elif node.wakuRlnRelay.isNil(): #not await node.wakuRlnRelay.isReady(): - debug "mounting lightpush without rln-relay (nil)" - pushHandler = proc( - peer: PeerId, pubsubTopic: string, message: WakuMessage - ): Future[WakuLightPushResult[void]] {.async.} = - return err("WakuRlnRelay is not ready") else: pushHandler = proc( peer: PeerId, pubsubTopic: string, message: WakuMessage @@ -965,8 +958,16 @@ proc mountLightPush*( return ok() debug "mounting lightpush with relay" + let rlnPeer = + if node.wakuRlnRelay.isNil: + debug "mounting lightpush without rln-relay" + none(WakuRLNRelay) + else: + debug "mounting lightpush with rln-relay" + some(node.wakuRlnRelay) + node.wakuLightPush = - WakuLightPush.new(node.peerManager, node.rng, pushHandler, node.wakuRlnRelay, some(rateLimit)) + WakuLightPush.new(node.peerManager, node.rng, pushHandler, rlnPeer, some(rateLimit)) if node.started: # Node has started already. Let's start lightpush too. diff --git a/waku/waku_lightpush/protocol.nim b/waku/waku_lightpush/protocol.nim index bd10af6390..1c13c3dc3c 100644 --- a/waku/waku_lightpush/protocol.nim +++ b/waku/waku_lightpush/protocol.nim @@ -25,7 +25,28 @@ type WakuLightPush* = ref object of LPProtocol peerManager*: PeerManager pushHandler*: PushMessageHandler requestRateLimiter*: Option[TokenBucket] - rlnPeer*: WakuRLNRelay + rlnPeer*: Option[WakuRLNRelay] + +proc generateAndValidateRLNProof*(wl: WakuLightPush, message: var WakuMessage): (string, WakuMessage) = + var pushResponseInfo = "" + # TODO: check and validate if the message already has RLN proof? + if wl.rlnPeer.isNone(): + return (pushResponseInfo, message) # publishing message without RLN proof + + # generate and append RLN proof + let + rlnPeer = wl.rlnPeer.get() + time = getTime().toUnix() + senderEpochTime = float64(time) + let appendProofRes = rlnPeer.appendRLNProof(message, senderEpochTime) + if appendProofRes.isErr(): + pushResponseInfo = "RLN proof generation failed: " & appendProofRes.error + + # validate RLN proof + let validateProofRes = rlnPeer.validateMessage(message, some(senderEpochTime)) + if validateProofRes != MessageValidationResult.Valid: + pushResponseInfo = "RLN proof validation failed" + return (pushResponseInfo, message) proc handleRequest*( wl: WakuLightPush, peerId: PeerId, buffer: seq[byte] @@ -47,7 +68,6 @@ proc handleRequest*( let request = pushRpcRequest.request - pubSubTopic = request.get().pubSubTopic var message = request.get().message waku_lightpush_messages.inc(labelValues = ["PushRequest"]) @@ -57,17 +77,10 @@ proc handleRequest*( pubsubTopic = pubsubTopic, hash = pubsubTopic.computeMessageHash(message).to0xHex() - # Generate and validate RLN proof - let - rlnPeer = wl.rlnPeer - time = getTime().toUnix() - senderEpochTime = float64(time) #rlnPeer.getCurrentEpoch() - appendProofRes = rlnPeer.appendRLNProof(message, senderEpochTime) - - if appendProofRes.isErr(): - pushResponseInfo = "RLN proof generation failed: " & appendProofRes.error - else: - let handleRes = await wl.pushHandler(peerId, pubSubTopic, message) + let (rlnResultInfo, msgWithProof) = generateAndValidateRLNProof(wl, message) + pushResponseInfo = rlnResultInfo + if pushResponseInfo == "": + let handleRes = await wl.pushHandler(peerId, pubSubTopic, msgWithProof) isSuccess = handleRes.isOk() pushResponseInfo = (if isSuccess: "OK" else: handleRes.error) @@ -117,7 +130,7 @@ proc new*( peerManager: PeerManager, rng: ref rand.HmacDrbgContext, pushHandler: PushMessageHandler, - rlnPeer: WakuRLNRelay, + rlnPeer: Option[WakuRLNRelay] = none[WakuRLNRelay](), rateLimitSetting: Option[RateLimitSetting] = none[RateLimitSetting](), ): T = let wl = WakuLightPush( From 00feb8424f1268d50780cb4f63acfa1bfa3aa585 Mon Sep 17 00:00:00 2001 From: shash256 <111925100+shash256@users.noreply.github.com> Date: Tue, 4 Jun 2024 06:07:19 +0400 Subject: [PATCH 3/7] remove a test --- tests/waku_lightpush/test_all.nim | 43 ------------------------------- 1 file changed, 43 deletions(-) diff --git a/tests/waku_lightpush/test_all.nim b/tests/waku_lightpush/test_all.nim index 3b9b55e7b9..e4188ad6d5 100644 --- a/tests/waku_lightpush/test_all.nim +++ b/tests/waku_lightpush/test_all.nim @@ -1,45 +1,2 @@ import ./test_client, ./test_ratelimit -# import std/[unittest, options, times] -# import ../../../waku/[ -# waku_lightpush/protocol, -# waku_rln_relay/rln_relay, -# waku_core, -# node/peer_manager/peer_manager -# ] - -# suite "LightPush with RLN": -# test "handleRequest with valid RLN proof": -# let peerManager = PeerManager() -# let rng = initHmacDrbgContext() -# let rlnPeer = WakuRLNRelay() -# let pushHandler: PushMessageHandler = proc (peerId, topic, msg): Future[Result[void, string]] {.async.} = -# return ok() - -# let wl = WakuLightPush( -# peerManager: peerManager, -# rng: rng, -# pushHandler: pushHandler, -# rlnPeer: rlnPeer, -# ) - -# # Prepare a valid WakuMessage -# let payload = "Hello, Waku!".toBytes() -# let contentTopic = "/waku/2/default-content/proto" -# var message = WakuMessage(payload: payload, contentTopic: contentTopic) - -# # Append RLN proof to the message -# let senderEpochTime = rlnPeer.calcEpoch(epochTime()) -# let appendProofRes = rlnPeer.appendRLNProof(message, senderEpochTime) -# doAssert appendProofRes.isOk(), "Failed to append RLN proof: " & appendProofRes.error - -# # Prepare a valid PushRPC request -# let pushRequest = PushRequest(pubSubTopic: contentTopic, message: message) -# let pushRpc = PushRPC(requestId: "1", request: some(pushRequest)) -# let buffer = pushRpc.encode().buffer - -# # Call handleRequest and check the result -# let result = waitFor wl.handleRequest("peer1", buffer) -# check result.response.isSome -# check result.response.get().isSuccess - From 0b747c79a64f3ef5e949b732d82ba09e53d7111e Mon Sep 17 00:00:00 2001 From: shash256 <111925100+shash256@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:03:24 +0400 Subject: [PATCH 4/7] move push handler and RLNaaS to callbacks --- tests/node/test_wakunode_lightpush.nim | 101 ++++++++++++++++++++----- tests/waku_lightpush/test_all.nim | 1 - waku/node/waku_node.nim | 32 +------- waku/waku_lightpush/callbacks.nim | 66 ++++++++++++++++ waku/waku_lightpush/protocol.nim | 44 +++-------- 5 files changed, 160 insertions(+), 84 deletions(-) create mode 100644 waku/waku_lightpush/callbacks.nim diff --git a/tests/node/test_wakunode_lightpush.nim b/tests/node/test_wakunode_lightpush.nim index af2b1aa926..b5d7a2ea90 100644 --- a/tests/node/test_wakunode_lightpush.nim +++ b/tests/node/test_wakunode_lightpush.nim @@ -56,29 +56,11 @@ suite "Waku Lightpush - End To End": server = newTestWakuNode(serverKey, ValidIpAddress.init("0.0.0.0"), Port(0)) client = newTestWakuNode(clientKey, ValidIpAddress.init("0.0.0.0"), Port(0)) - # mount rln-relay - when defined(rln_v2): - let wakuRlnConfig = WakuRlnConfig( - rlnRelayDynamic: false, - rlnRelayCredIndex: some(1.uint), - rlnRelayUserMessageLimit: 1, - rlnEpochSizeSec: 1, - rlnRelayTreePath: genTempPath("rln_tree", "wakunode"), - ) - else: - let wakuRlnConfig = WakuRlnConfig( - rlnRelayDynamic: false, - rlnRelayCredIndex: some(1.uint), - rlnEpochSizeSec: 1, - rlnRelayTreePath: genTempPath("rln_tree", "wakunode"), - ) - await allFutures(server.start(), client.start()) await server.start() await server.mountRelay() - await server.mountRlnRelay(wakuRlnConfig) - await server.mountLightpush() + await server.mountLightpush() # without rln-relay client.mountLightpushClient() serverRemotePeerInfo = server.peerInfo.toRemotePeerInfo() @@ -122,4 +104,83 @@ suite "Waku Lightpush - End To End": check: publishResponse.isErr() - publishResponse.error == fmt"Message size exceeded maximum of {DefaultMaxWakuMessageSize} bytes" \ No newline at end of file + publishResponse.error == fmt"Message size exceeded maximum of {DefaultMaxWakuMessageSize} bytes" + +suite "RLN Proofs as a Lightpush Service": + var + handlerFuture {.threadvar.}: Future[(PubsubTopic, WakuMessage)] + handler {.threadvar.}: PushMessageHandler + + server {.threadvar.}: WakuNode + client {.threadvar.}: WakuNode + + serverRemotePeerInfo {.threadvar.}: RemotePeerInfo + pubsubTopic {.threadvar.}: PubsubTopic + contentTopic {.threadvar.}: ContentTopic + message {.threadvar.}: WakuMessage + + asyncSetup: + handlerFuture = newPushHandlerFuture() + handler = proc( + peer: PeerId, pubsubTopic: PubsubTopic, message: WakuMessage + ): Future[WakuLightPushResult[void]] {.async.} = + handlerFuture.complete((pubsubTopic, message)) + return ok() + + let + serverKey = generateSecp256k1Key() + clientKey = generateSecp256k1Key() + + server = newTestWakuNode(serverKey, ValidIpAddress.init("0.0.0.0"), Port(0)) + client = newTestWakuNode(clientKey, ValidIpAddress.init("0.0.0.0"), Port(0)) + + # mount rln-relay + when defined(rln_v2): + let wakuRlnConfig = WakuRlnConfig( + rlnRelayDynamic: false, + rlnRelayCredIndex: some(1.uint), + rlnRelayUserMessageLimit: 1, + rlnEpochSizeSec: 1, + rlnRelayTreePath: genTempPath("rln_tree", "wakunode"), + ) + else: + let wakuRlnConfig = WakuRlnConfig( + rlnRelayDynamic: false, + rlnRelayCredIndex: some(1.uint), + rlnEpochSizeSec: 1, + rlnRelayTreePath: genTempPath("rln_tree", "wakunode"), + ) + + await allFutures(server.start(), client.start()) + await server.start() + + await server.mountRelay() + await server.mountRlnRelay(wakuRlnConfig) + await server.mountLightpush() + client.mountLightpushClient() + + serverRemotePeerInfo = server.peerInfo.toRemotePeerInfo() + pubsubTopic = DefaultPubsubTopic + contentTopic = DefaultContentTopic + message = fakeWakuMessage() + + asyncTeardown: + await server.stop() + + suite "Lightpush attaching RLN proofs": + asyncTest "Message is published when RLN enabled": + # Given a light lightpush client + let lightpushClient = + newTestWakuNode(generateSecp256k1Key(), ValidIpAddress.init("0.0.0.0"), Port(0)) + lightpushClient.mountLightpushClient() + + # When the client publishes a message + let publishResponse = await lightpushClient.lightpushPublish( + some(pubsubTopic), message, serverRemotePeerInfo + ) + + if not publishResponse.isOk(): + echo "Publish failed: ", publishResponse.error() + + # Then the message is relayed to the server + assertResultOk publishResponse \ No newline at end of file diff --git a/tests/waku_lightpush/test_all.nim b/tests/waku_lightpush/test_all.nim index e4188ad6d5..4e49809296 100644 --- a/tests/waku_lightpush/test_all.nim +++ b/tests/waku_lightpush/test_all.nim @@ -1,2 +1 @@ import ./test_client, ./test_ratelimit - diff --git a/waku/node/waku_node.nim b/waku/node/waku_node.nim index 767d86cce8..06185c105b 100644 --- a/waku/node/waku_node.nim +++ b/waku/node/waku_node.nim @@ -44,6 +44,7 @@ import ../waku_lightpush/common, ../waku_lightpush/protocol, ../waku_lightpush/self_req_handler, + ../waku_lightpush/callbacks, ../waku_enr, ../waku_peer_exchange, ../waku_rln_relay, @@ -931,33 +932,6 @@ proc mountLightPush*( ) {.async.} = info "mounting light push" - var pushHandler: PushMessageHandler - if node.wakuRelay.isNil(): - debug "mounting lightpush without relay (nil)" - pushHandler = proc( - peer: PeerId, pubsubTopic: string, message: WakuMessage - ): Future[WakuLightPushResult[void]] {.async.} = - return err("no waku relay found") - else: - pushHandler = proc( - peer: PeerId, pubsubTopic: string, message: WakuMessage - ): Future[WakuLightPushResult[void]] {.async.} = - let validationRes = await node.wakuRelay.validateMessage(pubSubTopic, message) - if validationRes.isErr(): - return err(validationRes.error) - - let publishedCount = - await node.wakuRelay.publish(pubsubTopic, message.encode().buffer) - - if publishedCount == 0: - ## Agreed change expected to the lightpush protocol to better handle such case. https://github.com/waku-org/pm/issues/93 - let msgHash = computeMessageHash(pubsubTopic, message).to0xHex() - debug "Lightpush request has not been published to any peers", - msg_hash = msgHash - - return ok() - - debug "mounting lightpush with relay" let rlnPeer = if node.wakuRlnRelay.isNil: debug "mounting lightpush without rln-relay" @@ -965,9 +939,11 @@ proc mountLightPush*( else: debug "mounting lightpush with rln-relay" some(node.wakuRlnRelay) + + var pushHandler = getPushHandler(node.wakuRelay, rlnPeer) node.wakuLightPush = - WakuLightPush.new(node.peerManager, node.rng, pushHandler, rlnPeer, some(rateLimit)) + WakuLightPush.new(node.peerManager, node.rng, pushHandler, some(rateLimit)) if node.started: # Node has started already. Let's start lightpush too. diff --git a/waku/waku_lightpush/callbacks.nim b/waku/waku_lightpush/callbacks.nim new file mode 100644 index 0000000000..9ac89eaef3 --- /dev/null +++ b/waku/waku_lightpush/callbacks.nim @@ -0,0 +1,66 @@ +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +import + ../waku_core, + ../waku_relay, + ./common, + ./protocol, + ../waku_rln_relay, + ../waku_rln_relay/protocol_types, + ../common/ratelimit +import + std/times, + libp2p/peerid, + stew/byteutils + +proc generateAndValidateRLNProof*(rlnPeer: Option[WakuRLNRelay], message: WakuMessage): (string, WakuMessage) = + var rlnResultInfo = "" + # TODO: check and validate if the message already has RLN proof? + if rlnPeer.isNone(): + return (rlnResultInfo, message) # publishing message without RLN proof + + # generate and append RLN proof + let + time = getTime().toUnix() + senderEpochTime = float64(time) + var msgWithProof = message + let appendProofRes = rlnPeer.get().appendRLNProof(msgWithProof, senderEpochTime) + if appendProofRes.isErr(): + rlnResultInfo = "RLN proof generation failed: " & appendProofRes.error + + return (rlnResultInfo, msgWithProof) + +proc getPushHandler*( + wakuRelay: WakuRelay, + rlnPeer: Option[WakuRLNRelay] = none[WakuRLNRelay]() +): PushMessageHandler = + if wakuRelay.isNil(): + debug "mounting lightpush without relay (nil)" + return proc( + peer: PeerId, pubsubTopic: string, message: WakuMessage + ): Future[WakuLightPushResult[void]] {.async.} = + return err("no waku relay found") + else: + debug "mounting lightpush with relay" + return proc( + peer: PeerId, pubsubTopic: string, message: WakuMessage + ): Future[WakuLightPushResult[void]] {.async.} = + # append RLN proof + let (rlnResultInfo, msgWithProof) = generateAndValidateRLNProof(rlnPeer, message) + if rlnResultInfo == "": + let validationRes = await wakuRelay.validateMessage(pubSubTopic, msgWithProof) + if validationRes.isErr(): + return err(validationRes.error) + + let publishedCount = await wakuRelay.publish(pubsubTopic, msgWithProof) + if publishedCount == 0: + ## Agreed change expected to the lightpush protocol to better handle such case. https://github.com/waku-org/pm/issues/93 + let msgHash = computeMessageHash(pubsubTopic, message).to0xHex() + debug "Lightpush request has not been published to any peers", msg_hash = msgHash + + return ok() + else: + return err(rlnResultInfo) \ No newline at end of file diff --git a/waku/waku_lightpush/protocol.nim b/waku/waku_lightpush/protocol.nim index 1c13c3dc3c..eb02d7556c 100644 --- a/waku/waku_lightpush/protocol.nim +++ b/waku/waku_lightpush/protocol.nim @@ -4,7 +4,7 @@ else: {.push raises: [].} import - std/options, std/times, stew/results, stew/byteutils, chronicles, chronos, metrics, bearssl/rand + std/options, stew/results, stew/byteutils, chronicles, chronos, metrics, bearssl/rand import ../node/peer_manager/peer_manager, ../waku_core, @@ -13,8 +13,8 @@ import ./rpc_codec, ./protocol_metrics, ../common/ratelimit, - ../common/waku_service_metrics, - ../waku_rln_relay/rln_relay, ../waku_rln_relay/protocol_types + ../common/waku_service_metrics + export ratelimit logScope: @@ -25,28 +25,6 @@ type WakuLightPush* = ref object of LPProtocol peerManager*: PeerManager pushHandler*: PushMessageHandler requestRateLimiter*: Option[TokenBucket] - rlnPeer*: Option[WakuRLNRelay] - -proc generateAndValidateRLNProof*(wl: WakuLightPush, message: var WakuMessage): (string, WakuMessage) = - var pushResponseInfo = "" - # TODO: check and validate if the message already has RLN proof? - if wl.rlnPeer.isNone(): - return (pushResponseInfo, message) # publishing message without RLN proof - - # generate and append RLN proof - let - rlnPeer = wl.rlnPeer.get() - time = getTime().toUnix() - senderEpochTime = float64(time) - let appendProofRes = rlnPeer.appendRLNProof(message, senderEpochTime) - if appendProofRes.isErr(): - pushResponseInfo = "RLN proof generation failed: " & appendProofRes.error - - # validate RLN proof - let validateProofRes = rlnPeer.validateMessage(message, some(senderEpochTime)) - if validateProofRes != MessageValidationResult.Valid: - pushResponseInfo = "RLN proof validation failed" - return (pushResponseInfo, message) proc handleRequest*( wl: WakuLightPush, peerId: PeerId, buffer: seq[byte] @@ -68,8 +46,9 @@ proc handleRequest*( let request = pushRpcRequest.request + pubSubTopic = request.get().pubSubTopic - var message = request.get().message + message = request.get().message waku_lightpush_messages.inc(labelValues = ["PushRequest"]) debug "push request", peerId = peerId, @@ -77,12 +56,9 @@ proc handleRequest*( pubsubTopic = pubsubTopic, hash = pubsubTopic.computeMessageHash(message).to0xHex() - let (rlnResultInfo, msgWithProof) = generateAndValidateRLNProof(wl, message) - pushResponseInfo = rlnResultInfo - if pushResponseInfo == "": - let handleRes = await wl.pushHandler(peerId, pubSubTopic, msgWithProof) - isSuccess = handleRes.isOk() - pushResponseInfo = (if isSuccess: "OK" else: handleRes.error) + let handleRes = await wl.pushHandler(peerId, pubsubTopic, message) + isSuccess = handleRes.isOk() + pushResponseInfo = (if isSuccess: "OK" else: handleRes.error) if not isSuccess: waku_lightpush_errors.inc(labelValues = [pushResponseInfo]) @@ -130,7 +106,6 @@ proc new*( peerManager: PeerManager, rng: ref rand.HmacDrbgContext, pushHandler: PushMessageHandler, - rlnPeer: Option[WakuRLNRelay] = none[WakuRLNRelay](), rateLimitSetting: Option[RateLimitSetting] = none[RateLimitSetting](), ): T = let wl = WakuLightPush( @@ -138,7 +113,6 @@ proc new*( peerManager: peerManager, pushHandler: pushHandler, requestRateLimiter: newTokenBucket(rateLimitSetting), - rlnPeer: rlnPeer, ) wl.initProtocolHandler() - return wl + return wl \ No newline at end of file From 078a5e564c8bd26c8bcba91d78520d9a6f281cb4 Mon Sep 17 00:00:00 2001 From: shash256 <111925100+shash256@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:56:15 +0400 Subject: [PATCH 5/7] address review comments --- waku/node/waku_node.nim | 23 ++++++----- waku/waku_lightpush/callbacks.nim | 65 +++++++++++++++---------------- 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/waku/node/waku_node.nim b/waku/node/waku_node.nim index 94ef81f253..9f4914bb6f 100644 --- a/waku/node/waku_node.nim +++ b/waku/node/waku_node.nim @@ -931,16 +931,21 @@ proc mountLightPush*( node: WakuNode, rateLimit: RateLimitSetting = DefaultGlobalNonRelayRateLimit ) {.async.} = info "mounting light push" - - let rlnPeer = - if node.wakuRlnRelay.isNil: - debug "mounting lightpush without rln-relay" - none(WakuRLNRelay) - else: - debug "mounting lightpush with rln-relay" - some(node.wakuRlnRelay) - var pushHandler = getPushHandler(node.wakuRelay, rlnPeer) + var pushHandler = + if node.wakuRelay.isNil: + debug "mounting lightpush without relay (nil)" + getNilPushHandler() + else: + debug "mounting lightpush with relay" + let rlnPeer = + if node.wakuRlnRelay.isNil: + debug "mounting lightpush without rln-relay" + none(WakuRLNRelay) + else: + debug "mounting lightpush with rln-relay" + some(node.wakuRlnRelay) + getRelayPushHandler(node.wakuRelay, rlnPeer) node.wakuLightPush = WakuLightPush.new(node.peerManager, node.rng, pushHandler, some(rateLimit)) diff --git a/waku/waku_lightpush/callbacks.nim b/waku/waku_lightpush/callbacks.nim index 9ac89eaef3..323bc0d1fe 100644 --- a/waku/waku_lightpush/callbacks.nim +++ b/waku/waku_lightpush/callbacks.nim @@ -16,11 +16,10 @@ import libp2p/peerid, stew/byteutils -proc generateAndValidateRLNProof*(rlnPeer: Option[WakuRLNRelay], message: WakuMessage): (string, WakuMessage) = - var rlnResultInfo = "" +proc generateAndValidateRLNProof*(rlnPeer: Option[WakuRLNRelay], message: WakuMessage): Result[WakuMessage, string] = # TODO: check and validate if the message already has RLN proof? if rlnPeer.isNone(): - return (rlnResultInfo, message) # publishing message without RLN proof + return ok(message) # publishing message without RLN proof # generate and append RLN proof let @@ -28,39 +27,37 @@ proc generateAndValidateRLNProof*(rlnPeer: Option[WakuRLNRelay], message: WakuMe senderEpochTime = float64(time) var msgWithProof = message let appendProofRes = rlnPeer.get().appendRLNProof(msgWithProof, senderEpochTime) - if appendProofRes.isErr(): - rlnResultInfo = "RLN proof generation failed: " & appendProofRes.error + if appendProofRes.isOk(): + return ok(msgWithProof) + + return err("RLN proof generation failed: " & appendProofRes.error) - return (rlnResultInfo, msgWithProof) +proc getNilPushHandler*(): PushMessageHandler = + return proc( + peer: PeerId, pubsubTopic: string, message: WakuMessage + ): Future[WakuLightPushResult[void]] {.async.} = + return err("no waku relay found") -proc getPushHandler*( - wakuRelay: WakuRelay, - rlnPeer: Option[WakuRLNRelay] = none[WakuRLNRelay]() +proc getRelayPushHandler*( + wakuRelay: WakuRelay, + rlnPeer: Option[WakuRLNRelay] = none[WakuRLNRelay]() ): PushMessageHandler = - if wakuRelay.isNil(): - debug "mounting lightpush without relay (nil)" - return proc( - peer: PeerId, pubsubTopic: string, message: WakuMessage - ): Future[WakuLightPushResult[void]] {.async.} = - return err("no waku relay found") - else: - debug "mounting lightpush with relay" - return proc( - peer: PeerId, pubsubTopic: string, message: WakuMessage - ): Future[WakuLightPushResult[void]] {.async.} = - # append RLN proof - let (rlnResultInfo, msgWithProof) = generateAndValidateRLNProof(rlnPeer, message) - if rlnResultInfo == "": - let validationRes = await wakuRelay.validateMessage(pubSubTopic, msgWithProof) - if validationRes.isErr(): - return err(validationRes.error) + return proc( + peer: PeerId, pubsubTopic: string, message: WakuMessage + ): Future[WakuLightPushResult[void]] {.async.} = + # append RLN proof + let msgWithProof = generateAndValidateRLNProof(rlnPeer, message) + if msgWithProof.isErr(): + return err(msgWithProof.error) - let publishedCount = await wakuRelay.publish(pubsubTopic, msgWithProof) - if publishedCount == 0: - ## Agreed change expected to the lightpush protocol to better handle such case. https://github.com/waku-org/pm/issues/93 - let msgHash = computeMessageHash(pubsubTopic, message).to0xHex() - debug "Lightpush request has not been published to any peers", msg_hash = msgHash + let validationRes = await wakuRelay.validateMessage(pubSubTopic, msgWithProof.value) + if validationRes.isErr(): + return err(validationRes.error) - return ok() - else: - return err(rlnResultInfo) \ No newline at end of file + let publishedCount = await wakuRelay.publish(pubsubTopic, msgWithProof.value) + if publishedCount == 0: + ## Agreed change expected to the lightpush protocol to better handle such case. https://github.com/waku-org/pm/issues/93 + let msgHash = computeMessageHash(pubsubTopic, message).to0xHex() + debug "Lightpush request has not been published to any peers", msg_hash = msgHash + + return ok() \ No newline at end of file From 8f5c425aeec2eaa39184c946fa2a9bbbd6067ae2 Mon Sep 17 00:00:00 2001 From: shash256 <111925100+shash256@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:15:02 +0400 Subject: [PATCH 6/7] changes from #2737 --- waku/waku_lightpush/callbacks.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waku/waku_lightpush/callbacks.nim b/waku/waku_lightpush/callbacks.nim index 323bc0d1fe..7b43a60292 100644 --- a/waku/waku_lightpush/callbacks.nim +++ b/waku/waku_lightpush/callbacks.nim @@ -58,6 +58,6 @@ proc getRelayPushHandler*( if publishedCount == 0: ## Agreed change expected to the lightpush protocol to better handle such case. https://github.com/waku-org/pm/issues/93 let msgHash = computeMessageHash(pubsubTopic, message).to0xHex() - debug "Lightpush request has not been published to any peers", msg_hash = msgHash + notice "Lightpush request has not been published to any peers", msg_hash = msgHash return ok() \ No newline at end of file From eceb52d6a5584b02f9855bd955b679ff106066cd Mon Sep 17 00:00:00 2001 From: shash256 <111925100+shash256@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:58:38 +0400 Subject: [PATCH 7/7] added check if msg has proof already --- waku/node/waku_node.nim | 2 +- waku/waku_lightpush/callbacks.nim | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/waku/node/waku_node.nim b/waku/node/waku_node.nim index 450ea18c40..898fc8ce30 100644 --- a/waku/node/waku_node.nim +++ b/waku/node/waku_node.nim @@ -939,7 +939,7 @@ proc mountLightPush*( else: debug "mounting lightpush with relay" let rlnPeer = - if node.wakuRlnRelay.isNil: + if isNil(node.wakuRlnRelay): debug "mounting lightpush without rln-relay" none(WakuRLNRelay) else: diff --git a/waku/waku_lightpush/callbacks.nim b/waku/waku_lightpush/callbacks.nim index 7b43a60292..6d4bff3d29 100644 --- a/waku/waku_lightpush/callbacks.nim +++ b/waku/waku_lightpush/callbacks.nim @@ -16,21 +16,22 @@ import libp2p/peerid, stew/byteutils -proc generateAndValidateRLNProof*(rlnPeer: Option[WakuRLNRelay], message: WakuMessage): Result[WakuMessage, string] = - # TODO: check and validate if the message already has RLN proof? +proc checkAndGenerateRLNProof*(rlnPeer: Option[WakuRLNRelay], message: WakuMessage): Result[WakuMessage, string] = + # check if the message already has RLN proof + if message.proof.len > 0: + return ok(message) + if rlnPeer.isNone(): - return ok(message) # publishing message without RLN proof - + notice "Publishing message without RLN proof" + return ok(message) # generate and append RLN proof let time = getTime().toUnix() senderEpochTime = float64(time) var msgWithProof = message - let appendProofRes = rlnPeer.get().appendRLNProof(msgWithProof, senderEpochTime) - if appendProofRes.isOk(): - return ok(msgWithProof) - - return err("RLN proof generation failed: " & appendProofRes.error) + rlnPeer.get().appendRLNProof(msgWithProof, senderEpochTime).isOkOr: + return err(error) + return ok(msgWithProof) proc getNilPushHandler*(): PushMessageHandler = return proc( @@ -46,13 +47,12 @@ proc getRelayPushHandler*( peer: PeerId, pubsubTopic: string, message: WakuMessage ): Future[WakuLightPushResult[void]] {.async.} = # append RLN proof - let msgWithProof = generateAndValidateRLNProof(rlnPeer, message) + let msgWithProof = checkAndGenerateRLNProof(rlnPeer, message) if msgWithProof.isErr(): return err(msgWithProof.error) - let validationRes = await wakuRelay.validateMessage(pubSubTopic, msgWithProof.value) - if validationRes.isErr(): - return err(validationRes.error) + (await wakuRelay.validateMessage(pubSubTopic, msgWithProof.value)).isOkOr: + return err(error) let publishedCount = await wakuRelay.publish(pubsubTopic, msgWithProof.value) if publishedCount == 0: