diff --git a/apps/chat2/chat2.nim b/apps/chat2/chat2.nim index 0da62ecb9..35aad5e9d 100644 --- a/apps/chat2/chat2.nim +++ b/apps/chat2/chat2.nim @@ -565,13 +565,13 @@ proc processInput(rfd: AsyncFD) {.async.} = rlnRelayCredentialsPassword: conf.rlnRelayCredentialsPassword ) - let res = await node.mountRlnRelay(conf=rlnConf, spamHandler = some(spamHandler), registrationHandler = some(registrationHandler)) - if res.isErr(): - echo "failed to mount rln-relay: " & res.error() - else: - echo "your membership index is: ", node.wakuRlnRelay.membershipIndex - echo "your rln identity key is: ", node.wakuRlnRelay.membershipKeyPair.idKey.inHex() - echo "your rln identity commitment key is: ", node.wakuRlnRelay.membershipKeyPair.idCommitment.inHex() + await node.mountRlnRelay(rlnConf, + spamHandler=some(spamHandler), + registrationHandler=some(registrationHandler)) + + echo "your membership index is: ", node.wakuRlnRelay.membershipIndex + echo "your rln identity key is: ", node.wakuRlnRelay.membershipKeyPair.idKey.inHex() + echo "your rln identity commitment key is: ", node.wakuRlnRelay.membershipKeyPair.idCommitment.inHex() if conf.metricsLogging: startMetricsLog() diff --git a/apps/wakunode2/wakunode2.nim b/apps/wakunode2/wakunode2.nim index 59929ce0c..21edc6633 100644 --- a/apps/wakunode2/wakunode2.nim +++ b/apps/wakunode2/wakunode2.nim @@ -371,9 +371,7 @@ proc setupProtocols(node: WakuNode, conf: WakuNodeConf, ) try: - let res = await node.mountRlnRelay(rlnConf) - if res.isErr(): - return err("failed to mount waku RLN relay protocol: " & res.error) + await node.mountRlnRelay(rlnConf) except: return err("failed to mount waku RLN relay protocol: " & getCurrentExceptionMsg()) diff --git a/tests/v2/test_waku_rln_relay.nim b/tests/v2/test_waku_rln_relay.nim index aefa99f41..71a3e1d67 100644 --- a/tests/v2/test_waku_rln_relay.nim +++ b/tests/v2/test_waku_rln_relay.nim @@ -56,7 +56,7 @@ procSuite "Waku rln relay": # -------- mount rln-relay in the off-chain mode await node.mountRelay(@[RlnRelayPubsubTopic]) - let mountRes = node.mountRlnRelayStatic(group = groupIDCommitments, + let mountRes = node.wakuRelay.mountRlnRelayStatic(group = groupIDCommitments, memKeyPair = groupKeyPairs[index], memIndex = index, pubsubTopic = RlnRelayPubsubTopic, @@ -64,8 +64,13 @@ procSuite "Waku rln relay": require: mountRes.isOk() + let wakuRlnRelay = mountRes.get() + # get the root of Merkle tree which is constructed inside the mountRlnRelay proc - let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex + let calculatedRootRes = wakuRlnRelay.rlnInstance.getMerkleRoot() + require: + calculatedRootRes.isOk() + let calculatedRoot = calculatedRootRes.get().inHex() debug "calculated root by mountRlnRelay", calculatedRoot # this part checks whether the Merkle tree is constructed correctly inside the mountRlnRelay proc diff --git a/tests/v2/test_waku_rln_relay_onchain.nim b/tests/v2/test_waku_rln_relay_onchain.nim index 68d860404..ca2127ed3 100644 --- a/tests/v2/test_waku_rln_relay_onchain.nim +++ b/tests/v2/test_waku_rln_relay_onchain.nim @@ -8,10 +8,7 @@ import stew/byteutils, stew/shims/net as stewNet, libp2p/crypto/crypto, eth/keys, - ../../waku/v2/protocol/waku_rln_relay/[utils, - constants, - protocol_types, - rln_relay_contract], + ../../waku/v2/protocol/waku_rln_relay, ../../waku/v2/node/waku_node, ../test_helpers, ./test_utils @@ -209,11 +206,11 @@ procSuite "Waku-rln-relay": let fut = newFuture[void]() let s = await contractObj.subscribe(MemberRegistered, %*{"fromBlock": "0x0", "address": contractAddress}) do( - pubkey: Uint256, index: Uint256){.raises: [Defect], gcsafe.}: + idCommitment: Uint256, index: Uint256){.raises: [Defect], gcsafe.}: try: - debug "onRegister", pubkey = pubkey, index = index + debug "onRegister", idCommitment = idCommitment, index = index require: - pubkey == pk + idCommitment == pk fut.complete() except Exception as err: # chronos still raises exceptions which inherit directly from Exception @@ -287,9 +284,9 @@ procSuite "Waku-rln-relay": events[futIndex].complete() futIndex += 1 let index = members[0].index - let isSuccessful = rlnPeer.rlnInstance.insertMembers(index, members.mapIt(it.idComm)) + let insertRes = rlnPeer.insertMembers(index, members.mapIt(it.idComm)) check: - isSuccessful + insertRes.isOk() return ok() # mount the handler for listening to the contract events @@ -308,7 +305,7 @@ procSuite "Waku-rln-relay": debug "a member is registered", tx2 = tx2 # wait for the events to be processed - await all(events) + await allFutures(events) # release resources ----------------------- await web3.close() @@ -432,7 +429,8 @@ procSuite "Waku-rln-relay": # test ------------------------------ # start rln-relay await node.mountRelay(@[RlnRelayPubsubTopic]) - let mountRes = node.mountRlnRelayStatic(group = group, + let mountRes = mountRlnRelayStatic(wakuRelay = node.wakuRelay, + group = group, memKeyPair = keyPair, memIndex = index, pubsubTopic = RlnRelayPubsubTopic, @@ -441,7 +439,9 @@ procSuite "Waku-rln-relay": require: mountRes.isOk() - let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex + let wakuRlnRelay = mountRes.get() + + let calculatedRoot = wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex() debug "calculated root ", calculatedRoot check: @@ -522,7 +522,8 @@ procSuite "Waku-rln-relay": # test ------------------------------ # start rln-relay await node.mountRelay(@[RlnRelayPubsubTopic]) - discard await node.mountRlnRelayDynamic(ethClientAddr = EthClient, + let mountRes = await mountRlnRelayDynamic(wakuRelay = node.wakuRelay, + ethClientAddr = EthClient, ethAccountAddress = some(ethacc), ethAccountPrivKeyOpt = some(ethPrivKey), memContractAddr = contractAddress, @@ -530,12 +531,17 @@ procSuite "Waku-rln-relay": memIndex = some(MembershipIndex(0)), pubsubTopic = RlnRelayPubsubTopic, contentTopic = RlnRelayContentTopic) + + require: + mountRes.isOk() + + let wakuRlnRelay = mountRes.get() - await sleepAsync(2000) # wait for the event to reach the group handler + await sleepAsync(2000.milliseconds()) # wait for the event to reach the group handler # rln pks are inserted into the rln peer's Merkle tree and the resulting root # is expected to be the same as the calculatedRoot i.e., the one calculated outside of the mountRlnRelayDynamic proc - let calculatedRoot = node.wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex + let calculatedRoot = wakuRlnRelay.rlnInstance.getMerkleRoot().value().inHex debug "calculated root ", calculatedRoot=calculatedRoot debug "expected root ", expectedRoot=expectedRoot @@ -575,7 +581,8 @@ procSuite "Waku-rln-relay": # start rln-relay on the first node, leave rln-relay credentials empty await node.mountRelay(@[RlnRelayPubsubTopic]) - discard await node.mountRlnRelayDynamic(ethClientAddr = EthClient, + let mountRes = await mountRlnRelayDynamic(wakuRelay=node.wakuRelay, + ethClientAddr = EthClient, ethAccountAddress = some(ethacc), ethAccountPrivKeyOpt = some(ethPrivKey), memContractAddr = contractAddress, @@ -583,12 +590,16 @@ procSuite "Waku-rln-relay": memIndex = none(MembershipIndex), pubsubTopic = RlnRelayPubsubTopic, contentTopic = RlnRelayContentTopic) - + require: + mountRes.isOk() + + let wakuRlnRelay = mountRes.get() # start rln-relay on the second node, leave rln-relay credentials empty await node2.mountRelay(@[RlnRelayPubsubTopic]) - discard await node2.mountRlnRelayDynamic(ethClientAddr = EthClient, + let mountRes2 = await mountRlnRelayDynamic(wakuRelay=node2.wakuRelay, + ethClientAddr = EthClient, ethAccountAddress = some(ethacc), ethAccountPrivKeyOpt = some(ethPrivKey), memContractAddr = contractAddress, @@ -597,12 +608,17 @@ procSuite "Waku-rln-relay": pubsubTopic = RlnRelayPubsubTopic, contentTopic = RlnRelayContentTopic) + require: + mountRes2.isOk() + + let wakuRlnRelay2 = mountRes2.get() + # the two nodes should be registered into the contract # since nodes are spun up sequentially # the first node has index 0 whereas the second node gets index 1 check: - node.wakuRlnRelay.membershipIndex == MembershipIndex(0) - node2.wakuRlnRelay.membershipIndex == MembershipIndex(1) + wakuRlnRelay.membershipIndex == MembershipIndex(0) + wakuRlnRelay2.membershipIndex == MembershipIndex(1) await node.stop() await node2.stop() diff --git a/tests/v2/test_wakunode_rln_relay.nim b/tests/v2/test_wakunode_rln_relay.nim index 3b1a68f0f..f9b65ade6 100644 --- a/tests/v2/test_wakunode_rln_relay.nim +++ b/tests/v2/test_wakunode_rln_relay.nim @@ -11,7 +11,6 @@ import libp2p/peerid, libp2p/multiaddress, libp2p/switch, - libp2p/protocols/pubsub/rpc/messages, libp2p/protocols/pubsub/pubsub, eth/keys import @@ -48,54 +47,35 @@ procSuite "WakuNode - RLN relay": # set up three nodes # node1 await node1.mountRelay(@[rlnRelayPubSubTopic]) - let staticSetupRes1 = rlnRelayStaticSetUp(1) # set up rln relay inputs - require: - staticSetupRes1.isOk() - let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = staticSetupRes1.get() # mount rlnrelay in off-chain mode - let mountRes1 = node1.mountRlnRelayStatic(group = groupOpt1.get(), - memKeyPair = memKeyPairOpt1.get(), - memIndex = memIndexOpt1.get(), - pubsubTopic = rlnRelayPubSubTopic, - contentTopic = contentTopic) - require: - mountRes1.isOk() + await node1.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayPubsubTopic: rlnRelayPubSubTopic, + rlnRelayContentTopic: contentTopic, + rlnRelayMembershipIndex: MembershipIndex(1), + )) await node1.start() # node 2 await node2.mountRelay(@[rlnRelayPubSubTopic]) - let staticSetupRes2 = rlnRelayStaticSetUp(2) # set up rln relay inputs - require: - staticSetupRes2.isOk() - let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = staticSetupRes2.get() # mount rlnrelay in off-chain mode - let mountRes2 = node2.mountRlnRelayStatic(group = groupOpt2.get(), - memKeyPair = memKeyPairOpt2.get(), - memIndex = memIndexOpt2.get(), - pubsubTopic = rlnRelayPubSubTopic, - contentTopic = contentTopic) - require: - mountRes2.isOk() + await node2.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayPubsubTopic: rlnRelayPubSubTopic, + rlnRelayContentTopic: contentTopic, + rlnRelayMembershipIndex: MembershipIndex(2), + )) await node2.start() # node 3 await node3.mountRelay(@[rlnRelayPubSubTopic]) - let staticSetupRes3 = rlnRelayStaticSetUp(3) # set up rln relay inputs - require: - staticSetupRes3.isOk() - let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = staticSetupRes3.get() - # mount rlnrelay in off-chain mode - let mountRes3 = node3.mountRlnRelayStatic(group = groupOpt3.get(), - memKeyPair = memKeyPairOpt3.get(), - memIndex = memIndexOpt3.get(), - pubsubTopic = rlnRelayPubSubTopic, - contentTopic = contentTopic) - require: - mountRes3.isOk() + await node3.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayPubsubTopic: rlnRelayPubSubTopic, + rlnRelayContentTopic: contentTopic, + rlnRelayMembershipIndex: MembershipIndex(3), + )) await node3.start() @@ -151,56 +131,41 @@ procSuite "WakuNode - RLN relay": rlnRelayPubSubTopic = RlnRelayPubsubTopic contentTopic = ContentTopic("/waku/2/default-content/proto") + # set up three nodes + # node1 # set up three nodes # node1 await node1.mountRelay(@[rlnRelayPubSubTopic]) - let staticSetupRes1 = rlnRelayStaticSetUp(1) # set up rln relay inputs - require: - staticSetupRes1.isOk() - let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = staticSetupRes1.get() # mount rlnrelay in off-chain mode - let mountRes1 = node1.mountRlnRelayStatic(group = groupOpt1.get(), - memKeyPair = memKeyPairOpt1.get(), - memIndex = memIndexOpt1.get(), - pubsubTopic = rlnRelayPubSubTopic, - contentTopic = contentTopic) - require: - mountRes1.isOk() + await node1.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayPubsubTopic: rlnRelayPubSubTopic, + rlnRelayContentTopic: contentTopic, + rlnRelayMembershipIndex: MembershipIndex(1), + )) + await node1.start() # node 2 await node2.mountRelay(@[rlnRelayPubSubTopic]) - let staticSetupRes2 = rlnRelayStaticSetUp(2) # set up rln relay inputs - require: - staticSetupRes2.isOk() - - let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = staticSetupRes2.get() # mount rlnrelay in off-chain mode - let mountRes2 = node2.mountRlnRelayStatic(group = groupOpt2.get(), - memKeyPair = memKeyPairOpt2.get(), - memIndex = memIndexOpt2.get(), - pubsubTopic = rlnRelayPubSubTopic, - contentTopic = contentTopic) - require: - mountRes2.isOk() + await node2.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayPubsubTopic: rlnRelayPubSubTopic, + rlnRelayContentTopic: contentTopic, + rlnRelayMembershipIndex: MembershipIndex(2), + )) + await node2.start() # node 3 await node3.mountRelay(@[rlnRelayPubSubTopic]) - let staticSetupRes3 = rlnRelayStaticSetUp(3) # set up rln relay inputs - require: - staticSetupRes3.isOk() - let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = staticSetupRes3.get() - # mount rlnrelay in off-chain mode - let mountRes3 = node3.mountRlnRelayStatic(group = groupOpt3.get(), - memKeyPair = memKeyPairOpt3.get(), - memIndex= memIndexOpt3.get(), - pubsubTopic = rlnRelayPubSubTopic, - contentTopic = contentTopic) - require: - mountRes3.isOk() + await node3.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayPubsubTopic: rlnRelayPubSubTopic, + rlnRelayContentTopic: contentTopic, + rlnRelayMembershipIndex: MembershipIndex(3), + )) + await node3.start() # connect them together @@ -278,55 +243,37 @@ procSuite "WakuNode - RLN relay": # set up three nodes # node1 await node1.mountRelay(@[rlnRelayPubSubTopic]) - let staticSetupRes1 = rlnRelayStaticSetUp(1) # set up rln relay inputs - require: - staticSetupRes1.isOk() - - let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = staticSetupRes1.get() + # mount rlnrelay in off-chain mode - let mountRes1 = node1.mountRlnRelayStatic(group = groupOpt1.get(), - memKeyPair = memKeyPairOpt1.get(), - memIndex = memIndexOpt1.get(), - pubsubTopic = rlnRelayPubSubTopic, - contentTopic = contentTopic) - require: - mountRes1.isOk() + await node1.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayPubsubTopic: rlnRelayPubSubTopic, + rlnRelayContentTopic: contentTopic, + rlnRelayMembershipIndex: MembershipIndex(1), + )) await node1.start() # node 2 await node2.mountRelay(@[rlnRelayPubSubTopic]) - let staticSetupRes2 = rlnRelayStaticSetUp(2) # set up rln relay inputs - require: - staticSetupRes2.isOk() - - let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = staticSetupRes2.get() + # mount rlnrelay in off-chain mode - let mountRes2 = node2.mountRlnRelayStatic(group = groupOpt2.get(), - memKeyPair = memKeyPairOpt2.get(), - memIndex = memIndexOpt2.get(), - pubsubTopic = rlnRelayPubSubTopic, - contentTopic = contentTopic) - require: - mountRes2.isOk() + await node2.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayPubsubTopic: rlnRelayPubSubTopic, + rlnRelayContentTopic: contentTopic, + rlnRelayMembershipIndex: MembershipIndex(2), + )) await node2.start() # node 3 await node3.mountRelay(@[rlnRelayPubSubTopic]) - let staticSetupRes3 = rlnRelayStaticSetUp(3) # set up rln relay inputs - require: - staticSetupRes3.isOk() - - let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = staticSetupRes3.get() + # mount rlnrelay in off-chain mode - let mountRes3 = node3.mountRlnRelayStatic(group = groupOpt3.get(), - memKeyPair = memKeyPairOpt3.get(), - memIndex = memIndexOpt3.get(), - pubsubTopic = rlnRelayPubSubTopic, - contentTopic = contentTopic) - require: - mountRes3.isOk() + await node3.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false, + rlnRelayPubsubTopic: rlnRelayPubSubTopic, + rlnRelayContentTopic: contentTopic, + rlnRelayMembershipIndex: MembershipIndex(3), + )) await node3.start() diff --git a/waku/v2/node/waku_node.nim b/waku/v2/node/waku_node.nim index 426e85771..a82e74771 100644 --- a/waku/v2/node/waku_node.nim +++ b/waku/v2/node/waku_node.nim @@ -43,7 +43,7 @@ import when defined(rln): import - ../protocol/waku_rln_relay/protocol_types + ../protocol/waku_rln_relay declarePublicGauge waku_version, "Waku version info (in git describe format)", ["version"] declarePublicCounter waku_node_messages, "number of messages received", ["type"] @@ -777,6 +777,22 @@ proc lightpushPublish*(node: WakuNode, pubsubTopic: PubsubTopic, message: WakuMe error "failed to publish message", error=publishRes.error +## Waku RLN Relay +when defined(rln): + proc mountRlnRelay*(node: WakuNode, + rlnConf: WakuRlnConfig, + spamHandler: Option[SpamHandler] = none(SpamHandler), + registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)) {.async.} = + info "mounting rln relay" + + let rlnRelayRes = await WakuRlnRelay.new(node.wakuRelay, + rlnConf, + spamHandler, + registrationHandler) + if rlnRelayRes.isErr(): + error "failed to mount rln relay", error=rlnRelayRes.error + return + node.wakuRlnRelay = rlnRelayRes.get() ## Waku peer-exchange diff --git a/waku/v2/protocol/waku_rln_relay.nim b/waku/v2/protocol/waku_rln_relay.nim index 55565ad14..53c632f5b 100644 --- a/waku/v2/protocol/waku_rln_relay.nim +++ b/waku/v2/protocol/waku_rln_relay.nim @@ -3,11 +3,13 @@ import ./waku_rln_relay/constants, ./waku_rln_relay/protocol_types, ./waku_rln_relay/protocol_metrics, - ./waku_rln_relay/utils + ./waku_rln_relay/utils, + ./waku_rln_relay/contract export rln, constants, protocol_types, protocol_metrics, - utils + utils, + contract diff --git a/waku/v2/protocol/waku_rln_relay/rln_relay_contract.nim b/waku/v2/protocol/waku_rln_relay/contract.nim similarity index 100% rename from waku/v2/protocol/waku_rln_relay/rln_relay_contract.nim rename to waku/v2/protocol/waku_rln_relay/contract.nim diff --git a/waku/v2/protocol/waku_rln_relay/membershipContract.txt b/waku/v2/protocol/waku_rln_relay/membershipContract.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/waku/v2/protocol/waku_rln_relay/utils.nim b/waku/v2/protocol/waku_rln_relay/utils.nim index 66eaac6e9..538410261 100644 --- a/waku/v2/protocol/waku_rln_relay/utils.nim +++ b/waku/v2/protocol/waku_rln_relay/utils.nim @@ -23,8 +23,8 @@ import import ../../utils/time, ../../utils/keyfile, - ../../node/waku_node, - ../waku_message + ../waku_message, + ../waku_relay logScope: topics = "waku rln_relay" @@ -971,7 +971,11 @@ proc handleGroupUpdates*(rlnPeer: WakuRLNRelay) {.async, gcsafe.} = contractAddress = rlnPeer.membershipContractAddress, handler = handler) -proc addRLNRelayValidator*(node: WakuNode, pubsubTopic: PubsubTopic, contentTopic: ContentTopic, spamHandler: Option[SpamHandler] = none(SpamHandler)) = +proc addRLNRelayValidator*(wakuRlnRelay: WakuRLNRelay, + wakuRelay: WakuRelay, + pubsubTopic: PubsubTopic, + contentTopic: ContentTopic, + spamHandler: Option[SpamHandler] = none(SpamHandler)) = ## this procedure is a thin wrapper for the pubsub addValidator method ## it sets a validator for the waku messages published on the supplied pubsubTopic and contentTopic ## if contentTopic is empty, then validation takes place for All the messages published on the given pubsubTopic @@ -998,7 +1002,7 @@ proc addRLNRelayValidator*(node: WakuNode, pubsubTopic: PubsubTopic, contentTopi # validate the message let - validationRes = node.wakuRlnRelay.validateMessage(wakumessage) + validationRes = wakuRlnRelay.validateMessage(wakumessage) proof = toHex(msgProof.proof) epoch = fromEpoch(msgProof.epoch) root = inHex(msgProof.merkleRoot) @@ -1022,29 +1026,19 @@ proc addRLNRelayValidator*(node: WakuNode, pubsubTopic: PubsubTopic, contentTopi handler(wakumessage) return pubsub.ValidationResult.Reject # set a validator for the supplied pubsubTopic - let pb = PubSub(node.wakuRelay) + let pb = PubSub(wakuRelay) pb.addValidator(pubsubTopic, validator) -proc mountRlnRelayStatic*(node: WakuNode, - group: seq[IDCommitment], - memKeyPair: MembershipKeyPair, - memIndex: MembershipIndex, - pubsubTopic: PubsubTopic, - contentTopic: ContentTopic, - spamHandler: Option[SpamHandler] = none(SpamHandler)): RlnRelayResult[void] = +proc mountRlnRelayStatic*(wakuRelay: WakuRelay, + group: seq[IDCommitment], + memKeyPair: MembershipKeyPair, + memIndex: MembershipIndex, + pubsubTopic: PubsubTopic, + contentTopic: ContentTopic, + spamHandler: Option[SpamHandler] = none(SpamHandler)): RlnRelayResult[WakuRlnRelay] = # Returns RlnRelayResult[void] to indicate the success of the call debug "mounting rln-relay in off-chain/static mode" - # check whether inputs are provided - # relay protocol is the prerequisite of rln-relay - if node.wakuRelay.isNil(): - return err("WakuRelay protocol is not mounted") - # check whether the pubsub topic is supported at the relay level - if pubsubTopic notin node.wakuRelay.defaultPubsubTopics: - return err("The relay protocol does not support the configured pubsub topic") - - debug "rln-relay input validation passed" - # check the peer's index and the inclusion of user's identity commitment in the group if not memKeyPair.idCommitment == group[int(memIndex)]: return err("The peer's index is not consistent with the group") @@ -1070,33 +1064,23 @@ proc mountRlnRelayStatic*(node: WakuNode, # adds a topic validator for the supplied pubsub topic at the relay protocol # messages published on this pubsub topic will be relayed upon a successful validation, otherwise they will be dropped # the topic validator checks for the correct non-spamming proof of the message - node.addRLNRelayValidator(pubsubTopic, contentTopic, spamHandler) + rlnPeer.addRLNRelayValidator(wakuRelay, pubsubTopic, contentTopic, spamHandler) debug "rln relay topic validator is mounted successfully", pubsubTopic=pubsubTopic, contentTopic=contentTopic - node.wakuRlnRelay = rlnPeer - return ok() + return ok(rlnPeer) -proc mountRlnRelayDynamic*(node: WakuNode, - ethClientAddr: string = "", - ethAccountAddress: Option[web3.Address] = none(web3.Address), - ethAccountPrivKeyOpt: Option[keys.PrivateKey], - memContractAddr: web3.Address, - memKeyPair: Option[MembershipKeyPair] = none(MembershipKeyPair), - memIndex: Option[MembershipIndex] = none(MembershipIndex), - pubsubTopic: PubsubTopic, - contentTopic: ContentTopic, - spamHandler: Option[SpamHandler] = none(SpamHandler), - registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)) : Future[RlnRelayResult[void]] {.async.} = +proc mountRlnRelayDynamic*(wakuRelay: WakuRelay, + ethClientAddr: string = "", + ethAccountAddress: Option[web3.Address] = none(web3.Address), + ethAccountPrivKeyOpt: Option[keys.PrivateKey], + memContractAddr: web3.Address, + memKeyPair: Option[MembershipKeyPair] = none(MembershipKeyPair), + memIndex: Option[MembershipIndex] = none(MembershipIndex), + pubsubTopic: PubsubTopic, + contentTopic: ContentTopic, + spamHandler: Option[SpamHandler] = none(SpamHandler), + registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)) : Future[RlnRelayResult[WakuRlnRelay]] {.async.} = debug "mounting rln-relay in on-chain/dynamic mode" - # TODO return a bool value to indicate the success of the call - # relay protocol is the prerequisite of rln-relay - if node.wakuRelay.isNil: - return err("WakuRelay protocol is not mounted.") - # check whether the pubsub topic is supported at the relay level - if pubsubTopic notin node.wakuRelay.defaultPubsubTopics: - return err("WakuRelay protocol does not support the configured pubsub topic.") - debug "rln-relay input validation passed" - # create an RLN instance let rlnInstance = createRLNInstance() @@ -1153,11 +1137,10 @@ proc mountRlnRelayDynamic*(node: WakuNode, # adds a topic validator for the supplied pubsub topic at the relay protocol # messages published on this pubsub topic will be relayed upon a successful validation, otherwise they will be dropped # the topic validator checks for the correct non-spamming proof of the message - addRLNRelayValidator(node, pubsubTopic, contentTopic, spamHandler) + rlnPeer.addRLNRelayValidator(wakuRelay, pubsubTopic, contentTopic, spamHandler) debug "rln relay topic validator is mounted successfully", pubsubTopic=pubsubTopic, contentTopic=contentTopic - node.wakuRlnRelay = rlnPeer - return ok() + return ok(rlnPeer) proc writeRlnCredentials*(path: string, credentials: RlnMembershipCredentials, @@ -1204,34 +1187,37 @@ proc readRlnCredentials*(path: string, except: return err("Error while loading keyfile for RLN credentials at " & path) -proc mount(node: WakuNode, +proc mount(wakuRelay: WakuRelay, conf: WakuRlnConfig, spamHandler: Option[SpamHandler] = none(SpamHandler), registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler) - ): Future[RlnRelayResult[void]] {.async.} = - # Returns RlnRelayResult[void], which indicates the success of the call - if not conf.rlnRelayDynamic: + ): Future[RlnRelayResult[WakuRlnRelay]] {.async.} = + + if not conf.rlnRelayDynamic: info " setting up waku-rln-relay in off-chain mode... " # set up rln relay inputs let staticSetupRes = rlnRelayStaticSetUp(MembershipIndex(conf.rlnRelayMembershipIndex)) if staticSetupRes.isErr(): return err("rln relay static setup failed: " & staticSetupRes.error()) let (groupOpt, memKeyPairOpt, memIndexOpt) = staticSetupRes.get() - if memIndexOpt.isNone: + if memIndexOpt.isNone(): error "failed to mount WakuRLNRelay" return err("failed to mount WakuRLNRelay") else: # mount rlnrelay in off-chain mode with a static group of users - let mountRes = node.mountRlnRelayStatic(group = groupOpt.get(), - memKeyPair = memKeyPairOpt.get(), - memIndex= memIndexOpt.get(), - pubsubTopic = conf.rlnRelayPubsubTopic, - contentTopic = conf.rlnRelayContentTopic, - spamHandler = spamHandler) + let mountRes = mountRlnRelayStatic(wakuRelay, + group = groupOpt.get(), + memKeyPair = memKeyPairOpt.get(), + memIndex = memIndexOpt.get(), + pubsubTopic = conf.rlnRelayPubsubTopic, + contentTopic = conf.rlnRelayContentTopic, + spamHandler = spamHandler) if mountRes.isErr(): return err("Failed to mount WakuRLNRelay: " & mountRes.error()) + let rlnRelay = mountRes.get() + info "membership id key", idkey=memKeyPairOpt.get().idKey.inHex() info "membership id commitment key", idCommitmentkey=memKeyPairOpt.get().idCommitment.inHex() @@ -1239,7 +1225,7 @@ proc mount(node: WakuNode, # no error should happen as it is already captured in the unit tests # TODO have added this check to account for unseen corner cases, will remove it later let - rootRes = node.wakuRlnRelay.rlnInstance.getMerkleRoot() + rootRes = rlnRelay.rlnInstance.getMerkleRoot() expectedRoot = StaticGroupMerkleRoot if rootRes.isErr(): @@ -1251,7 +1237,7 @@ proc mount(node: WakuNode, error "root mismatch: something went wrong not in Merkle tree construction" debug "the calculated root", root info "WakuRLNRelay is mounted successfully", pubsubtopic=conf.rlnRelayPubsubTopic, contentTopic=conf.rlnRelayContentTopic - return ok() + return ok(rlnRelay) else: # mount the rln relay protocol in the on-chain/dynamic mode debug "setting up waku-rln-relay in on-chain mode... " @@ -1268,7 +1254,9 @@ proc mount(node: WakuNode, var ethAccountPrivKeyOpt = none(keys.PrivateKey) var ethAccountAddressOpt = none(Address) var credentials = none(RlnMembershipCredentials) - var res: RlnRelayResult[void] + var rlnRelayRes: RlnRelayResult[WakuRlnRelay] + var rlnRelayCredPath: string + var persistCredentials: bool = false if conf.rlnRelayEthAccountPrivateKey != "": ethAccountPrivKeyOpt = some(keys.PrivateKey(SkSecretKey.fromHex(conf.rlnRelayEthAccountPrivateKey).value)) @@ -1286,7 +1274,7 @@ proc mount(node: WakuNode, # if there is a credential file, then no new credentials are generated, instead the content of the file is read and used to mount rln-relay if conf.rlnRelayCredPath != "": - let rlnRelayCredPath = joinPath(conf.rlnRelayCredPath, RlnCredentialsFilename) + rlnRelayCredPath = joinPath(conf.rlnRelayCredPath, RlnCredentialsFilename) debug "rln-relay credential path", rlnRelayCredPath # check if there is an rln-relay credential file in the supplied path @@ -1298,7 +1286,7 @@ proc mount(node: WakuNode, let readCredentialsRes = readRlnCredentials(rlnRelayCredPath, conf.rlnRelayCredentialsPassword) if readCredentialsRes.isErr(): - return err("RLN credentials cannot be read: " & readCredentialsRes.error()) + return err("RLN credentials cannot be read: " & readCredentialsRes.error()) credentials = readCredentialsRes.get() @@ -1309,59 +1297,80 @@ proc mount(node: WakuNode, if credentials.isSome(): # mount rln-relay in on-chain mode, with credentials that were read or generated - res = await node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, - ethClientAddr = ethClientAddr, - ethAccountAddress = ethAccountAddressOpt, - ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, - pubsubTopic = conf.rlnRelayPubsubTopic, - contentTopic = conf.rlnRelayContentTopic, - spamHandler = spamHandler, - registrationHandler = registrationHandler, - memKeyPair = some(credentials.get().membershipKeyPair), - memIndex = some(credentials.get().rlnIndex)) + rlnRelayRes = await mountRlnRelayDynamic(wakuRelay, + memContractAddr = ethMemContractAddress, + ethClientAddr = ethClientAddr, + ethAccountAddress = ethAccountAddressOpt, + ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, + pubsubTopic = conf.rlnRelayPubsubTopic, + contentTopic = conf.rlnRelayContentTopic, + spamHandler = spamHandler, + registrationHandler = registrationHandler, + memKeyPair = some(credentials.get().membershipKeyPair), + memIndex = some(credentials.get().rlnIndex)) else: # mount rln-relay in on-chain mode, with the provided private key - res = await node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, - ethClientAddr = ethClientAddr, - ethAccountAddress = ethAccountAddressOpt, - ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, - pubsubTopic = conf.rlnRelayPubsubTopic, - contentTopic = conf.rlnRelayContentTopic, - spamHandler = spamHandler, - registrationHandler = registrationHandler) + rlnRelayRes = await mountRlnRelayDynamic(wakuRelay, + memContractAddr = ethMemContractAddress, + ethClientAddr = ethClientAddr, + ethAccountAddress = ethAccountAddressOpt, + ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, + pubsubTopic = conf.rlnRelayPubsubTopic, + contentTopic = conf.rlnRelayContentTopic, + spamHandler = spamHandler, + registrationHandler = registrationHandler) - # TODO should be replaced with key-store with proper encryption - # persist rln credential - credentials = some(RlnMembershipCredentials(rlnIndex: node.wakuRlnRelay.membershipIndex, - membershipKeyPair: node.wakuRlnRelay.membershipKeyPair)) - if writeRlnCredentials(rlnRelayCredPath, credentials.get(), conf.rlnRelayCredentialsPassword).isErr(): - return err("error in storing rln credentials") + persistCredentials = true else: # do not persist or use a persisted rln-relay credential # a new credential will be generated during the mount process but will not be persisted info "no need to persist or use a persisted rln-relay credential" - res = await node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr, - ethAccountAddress = ethAccountAddressOpt, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic, - contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler, registrationHandler = registrationHandler) + rlnRelayRes = await mountRlnRelayDynamic(wakuRelay, + memContractAddr = ethMemContractAddress, + ethClientAddr = ethClientAddr, + ethAccountAddress = ethAccountAddressOpt, + ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, + pubsubTopic = conf.rlnRelayPubsubTopic, + contentTopic = conf.rlnRelayContentTopic, + spamHandler = spamHandler, + registrationHandler = registrationHandler) - if res.isErr(): - return err("dynamic rln-relay could not be mounted: " & res.error()) - return ok() + if rlnRelayRes.isErr(): + return err("dynamic rln-relay could not be mounted: " & rlnRelayRes.error()) + let wakuRlnRelay = rlnRelayRes.get() + if persistCredentials: + # persist rln credential + credentials = some(RlnMembershipCredentials(rlnIndex: wakuRlnRelay.membershipIndex, + membershipKeyPair: wakuRlnRelay.membershipKeyPair)) + if writeRlnCredentials(rlnRelayCredPath, credentials.get(), conf.rlnRelayCredentialsPassword).isErr(): + return err("error in storing rln credentials") + return ok(wakuRlnRelay) -proc mountRlnRelay*(node: WakuNode, - conf: WakuRlnConfig, - spamHandler: Option[SpamHandler] = none(SpamHandler), - registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler) - ): Future[RlnRelayResult[void]] {.async.} = +proc new*(T: type WakuRlnRelay, + wakuRelay: WakuRelay, + conf: WakuRlnConfig, + spamHandler: Option[SpamHandler] = none(SpamHandler), + registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler) + ): Future[RlnRelayResult[WakuRlnRelay]] {.async.} = ## Mounts the rln-relay protocol on the node. ## The rln-relay protocol can be mounted in two modes: on-chain and off-chain. ## Returns an error if the rln-relay protocol could not be mounted. - waku_rln_relay_mounting_duration_seconds.nanosecondTime: - let res = await mount( - node, + + # check whether inputs are provided + # relay protocol is the prerequisite of rln-relay + if wakuRelay.isNil(): + return err("WakuRelay protocol is not mounted") + # check whether the pubsub topic is supported at the relay level + if conf.rlnRelayPubsubTopic notin wakuRelay.defaultPubsubTopics: + return err("The relay protocol does not support the configured pubsub topic") + + debug "rln-relay input validation passed" + waku_rln_relay_mounting_duration_seconds.nanosecondTime: + let rlnRelayRes = await mount( + wakuRelay, conf, spamHandler, registrationHandler ) - return res + return rlnRelayRes \ No newline at end of file