diff --git a/tests/waku_rln_relay/test_rln_group_manager_onchain.nim b/tests/waku_rln_relay/test_rln_group_manager_onchain.nim index 0596a8e96b..3d95a4e40d 100644 --- a/tests/waku_rln_relay/test_rln_group_manager_onchain.nim +++ b/tests/waku_rln_relay/test_rln_group_manager_onchain.nim @@ -8,7 +8,6 @@ else: import std/[options, os, osproc, sequtils, deques, streams, strutils, tempfiles], stew/[results, byteutils], - stew/shims/net as stewNet, testutils/unittests, chronos, chronicles, @@ -218,7 +217,8 @@ suite "Onchain group manager": asyncTest "should initialize successfully": let manager = await setup() - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error check: manager.ethRpc.isSome() @@ -231,7 +231,8 @@ suite "Onchain group manager": asyncTest "should error on initialization when loaded metadata does not match": let manager = await setup() - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error let metadataSetRes = manager.setMetadata() assert metadataSetRes.isOk(), metadataSetRes.error @@ -253,50 +254,43 @@ suite "Onchain group manager": ethContractAddress: $differentContractAddress, rlnInstance: manager.rlnInstance, ) - expect(ValueError): - await manager2.init() + (await manager2.init()).isErrOr: + raiseAssert "Expected error when contract address doesn't match" asyncTest "should error when keystore path and password are provided but file doesn't exist": let manager = await setup() manager.keystorePath = some("/inexistent/file") manager.keystorePassword = some("password") - expect(CatchableError): - await manager.init() + (await manager.init()).isErrOr: + raiseAssert "Expected error when keystore file doesn't exist" asyncTest "startGroupSync: should start group sync": let manager = await setup() - await manager.init() - try: - await manager.startGroupSync() - except Exception, CatchableError: - assert false, - "exception raised when calling startGroupSync: " & getCurrentExceptionMsg() + (await manager.init()).isOkOr: + raiseAssert $error + (await manager.startGroupSync()).isOkOr: + raiseAssert $error + await manager.stop() asyncTest "startGroupSync: should guard against uninitialized state": let manager = await setup() - try: - await manager.startGroupSync() - except CatchableError: - assert true - except Exception: - assert false, - "exception raised when calling startGroupSync: " & getCurrentExceptionMsg() + (await manager.startGroupSync()).isErrOr: + raiseAssert "Expected error when not initialized" await manager.stop() asyncTest "startGroupSync: should sync to the state of the group": let manager = await setup() let credentials = generateCredentials(manager.rlnInstance) - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error - let merkleRootBeforeRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootBeforeRes.isOk() - let merkleRootBefore = merkleRootBeforeRes.get() + let merkleRootBefore = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error let fut = newFuture[void]("startGroupSync") @@ -324,16 +318,15 @@ suite "Onchain group manager": await manager.register(credentials, UserMessageLimit(1)) else: await manager.register(credentials) - await manager.startGroupSync() + (await manager.startGroupSync()).isOkOr: + raiseAssert $error except Exception, CatchableError: assert false, "exception raised: " & getCurrentExceptionMsg() await fut - let merkleRootAfterRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootAfterRes.isOk() - let merkleRootAfter = merkleRootAfterRes.get() + let merkleRootAfter = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error check: merkleRootBefore != merkleRootAfter @@ -343,12 +336,11 @@ suite "Onchain group manager": let manager = await setup() const credentialCount = 6 let credentials = generateCredentials(manager.rlnInstance, credentialCount) - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error - let merkleRootBeforeRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootBeforeRes.isOk() - let merkleRootBefore = merkleRootBeforeRes.get() + let merkleRootBefore = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error type TestGroupSyncFuts = array[0 .. credentialCount - 1, Future[void]] var futures: TestGroupSyncFuts @@ -377,7 +369,8 @@ suite "Onchain group manager": try: manager.onRegister(generateCallback(futures, credentials)) - await manager.startGroupSync() + (await manager.startGroupSync()).isOkOr: + raiseAssert $error for i in 0 ..< credentials.len(): when defined(rln_v2): @@ -389,10 +382,8 @@ suite "Onchain group manager": await allFutures(futures) - let merkleRootAfterRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootAfterRes.isOk() - let merkleRootAfter = merkleRootAfterRes.get() + let merkleRootAfter = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error check: merkleRootBefore != merkleRootAfter @@ -421,18 +412,14 @@ suite "Onchain group manager": asyncTest "register: should register successfully": let manager = await setup() - await manager.init() - try: - await manager.startGroupSync() - except Exception, CatchableError: - assert false, - "exception raised when calling startGroupSync: " & getCurrentExceptionMsg() + (await manager.init()).isOkOr: + raiseAssert $error + (await manager.startGroupSync()).isOkOr: + raiseAssert $error let idCommitment = generateCredentials(manager.rlnInstance).idCommitment - let merkleRootBeforeRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootBeforeRes.isOk() - let merkleRootBefore = merkleRootBeforeRes.get() + let merkleRootBefore = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error try: when defined(rln_v2): @@ -447,10 +434,8 @@ suite "Onchain group manager": assert false, "exception raised when calling register: " & getCurrentExceptionMsg() - let merkleRootAfterRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootAfterRes.isOk() - let merkleRootAfter = merkleRootAfterRes.get() + let merkleRootAfter = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error check: merkleRootAfter.inHex() != merkleRootBefore.inHex() manager.latestIndex == 1 @@ -480,9 +465,11 @@ suite "Onchain group manager": fut.complete() manager.onRegister(callback) - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error try: - await manager.startGroupSync() + (await manager.startGroupSync()).isOkOr: + raiseAssert $error when defined(rln_v2): await manager.register( RateCommitment( @@ -519,7 +506,8 @@ suite "Onchain group manager": asyncTest "validateRoot: should validate good root": let manager = await setup() let credentials = generateCredentials(manager.rlnInstance) - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error let fut = newFuture[void]() @@ -541,7 +529,8 @@ suite "Onchain group manager": manager.onRegister(callback) try: - await manager.startGroupSync() + (await manager.startGroupSync()).isOkOr: + raiseAssert $error when defined(rln_v2): await manager.register(credentials, UserMessageLimit(1)) else: @@ -578,12 +567,10 @@ suite "Onchain group manager": asyncTest "validateRoot: should reject bad root": let manager = await setup() - await manager.init() - try: - await manager.startGroupSync() - except Exception, CatchableError: - assert false, - "exception raised when calling startGroupSync: " & getCurrentExceptionMsg() + (await manager.init()).isOkOr: + raiseAssert $error + (await manager.startGroupSync()).isOkOr: + raiseAssert $error let credentials = generateCredentials(manager.rlnInstance) @@ -620,7 +607,8 @@ suite "Onchain group manager": asyncTest "verifyProof: should verify valid proof": let manager = await setup() let credentials = generateCredentials(manager.rlnInstance) - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error let fut = newFuture[void]() @@ -642,7 +630,8 @@ suite "Onchain group manager": manager.onRegister(callback) try: - await manager.startGroupSync() + (await manager.startGroupSync()).isOkOr: + raiseAssert $error when defined(rln_v2): await manager.register(credentials, UserMessageLimit(1)) else: @@ -679,12 +668,10 @@ suite "Onchain group manager": asyncTest "verifyProof: should reject invalid proof": let manager = await setup() - await manager.init() - try: - await manager.startGroupSync() - except Exception, CatchableError: - assert false, - "exception raised when calling startGroupSync: " & getCurrentExceptionMsg() + (await manager.init()).isOkOr: + raiseAssert $error + (await manager.startGroupSync()).isOkOr: + raiseAssert $error let idCredential = generateCredentials(manager.rlnInstance) @@ -724,19 +711,19 @@ suite "Onchain group manager": let invalidProof = invalidProofRes.get() # verify the proof (should be false) - let verifiedRes = manager.verifyProof(messageBytes, invalidProof) - require: - verifiedRes.isOk() + let verified = manager.verifyProof(messageBytes, invalidProof).valueOr: + raiseAssert $error check: - verifiedRes.get() == false + verified == false await manager.stop() asyncTest "backfillRootQueue: should backfill roots in event of chain reorg": let manager = await setup() const credentialCount = 6 let credentials = generateCredentials(manager.rlnInstance, credentialCount) - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error type TestBackfillFuts = array[0 .. credentialCount - 1, Future[void]] var futures: TestBackfillFuts @@ -766,7 +753,9 @@ suite "Onchain group manager": try: manager.onRegister(generateCallback(futures, credentials)) - await manager.startGroupSync() + (await manager.startGroupSync()).isOkOr: + raiseAssert $error + for i in 0 ..< credentials.len(): when defined(rln_v2): await manager.register(credentials[i], UserMessageLimit(1)) @@ -798,7 +787,8 @@ suite "Onchain group manager": asyncTest "isReady should return false if ethRpc is none": let manager = await setup() - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error manager.ethRpc = none(Web3) @@ -815,7 +805,8 @@ suite "Onchain group manager": asyncTest "isReady should return false if lastSeenBlockHead > lastProcessed": let manager = await setup() - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error var isReady = true try: @@ -830,13 +821,12 @@ suite "Onchain group manager": asyncTest "isReady should return true if ethRpc is ready": let manager = await setup() - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error # node can only be ready after group sync is done - try: - await manager.startGroupSync() - except Exception, CatchableError: - assert false, - "exception raised when calling startGroupSync: " & getCurrentExceptionMsg() + (await manager.startGroupSync()).isOkOr: + raiseAssert $error + var isReady = false try: isReady = await manager.isReady() diff --git a/tests/waku_rln_relay/test_rln_group_manager_static.nim b/tests/waku_rln_relay/test_rln_group_manager_static.nim index 29c987f246..b6ff5a511a 100644 --- a/tests/waku_rln_relay/test_rln_group_manager_static.nim +++ b/tests/waku_rln_relay/test_rln_group_manager_static.nim @@ -30,12 +30,11 @@ proc generateCredentials(rlnInstance: ptr RLN, n: int): seq[IdentityCredential] suite "Static group manager": setup: - let rlnInstanceRes = - createRlnInstance(tree_path = genTempPath("rln_tree", "group_manager_static")) - require: - rlnInstanceRes.isOk() + let rlnInstance = createRlnInstance( + tree_path = genTempPath("rln_tree", "group_manager_static") + ).valueOr: + raiseAssert $error - let rlnInstance = rlnInstanceRes.get() let credentials = generateCredentials(rlnInstance, 10) let manager {.used.} = StaticGroupManager( @@ -46,16 +45,14 @@ suite "Static group manager": ) asyncTest "should initialize successfully": - let merkleRootBeforeRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootBeforeRes.isOk() - let merkleRootBefore = merkleRootBeforeRes.get() + let merkleRootBefore = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error + + (await manager.init()).isOkOr: + raiseAssert $error + let merkleRootAfter = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error - await manager.init() - let merkleRootAfterRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootAfterRes.isOk() - let merkleRootAfter = merkleRootAfterRes.get() check: manager.idCredentials.isSome() manager.groupKeys.len == 10 @@ -66,16 +63,14 @@ suite "Static group manager": merkleRootAfter.inHex() != merkleRootBefore.inHex() asyncTest "startGroupSync: should start group sync": - await manager.init() + (await manager.init()).isOkOr: + raiseAssert $error require: manager.validRoots.len() == 1 manager.rlnInstance.getMerkleRoot().get() == manager.validRoots[0] - try: - await manager.startGroupSync() - except Exception, CatchableError: - assert false, - "exception raised when calling startGroupSync: " & getCurrentExceptionMsg() + (await manager.startGroupSync()).isOkOr: + raiseAssert $error asyncTest "startGroupSync: should guard against uninitialized state": let manager = StaticGroupManager( @@ -84,13 +79,9 @@ suite "Static group manager": groupKeys: @[], rlnInstance: rlnInstance, ) - try: - await manager.startGroupSync() - except ValueError: - assert true - except Exception, CatchableError: - assert false, - "exception raised when calling startGroupSync: " & getCurrentExceptionMsg() + + (await manager.startGroupSync()).isErrOr: + raiseAssert "StartGroupSync: expected error" asyncTest "register: should guard against uninitialized state": let manager = StaticGroupManager( @@ -117,17 +108,14 @@ suite "Static group manager": assert false, "exception raised: " & getCurrentExceptionMsg() asyncTest "register: should register successfully": - await manager.init() - try: - await manager.startGroupSync() - except Exception, CatchableError: - assert false, "exception raised: " & getCurrentExceptionMsg() + (await manager.init()).isOkOr: + raiseAssert $error + (await manager.startGroupSync()).isOkOr: + raiseAssert $error let idCommitment = generateCredentials(manager.rlnInstance).idCommitment - let merkleRootBeforeRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootBeforeRes.isOk() - let merkleRootBefore = merkleRootBeforeRes.get() + let merkleRootBefore = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error try: when defined(rln_v2): await manager.register( @@ -139,10 +127,8 @@ suite "Static group manager": await manager.register(idCommitment) except Exception, CatchableError: assert false, "exception raised: " & getCurrentExceptionMsg() - let merkleRootAfterRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootAfterRes.isOk() - let merkleRootAfter = merkleRootAfterRes.get() + let merkleRootAfter = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error check: merkleRootAfter.inHex() != merkleRootBefore.inHex() manager.latestIndex == 10 @@ -171,8 +157,10 @@ suite "Static group manager": try: manager.onRegister(callback) - await manager.init() - await manager.startGroupSync() + (await manager.init()).isOkOr: + raiseAssert $error + (await manager.startGroupSync()).isOkOr: + raiseAssert $error when defined(rln_v2): await manager.register( RateCommitment( @@ -199,25 +187,21 @@ suite "Static group manager": assert false, "exception raised: " & getCurrentExceptionMsg() asyncTest "withdraw: should withdraw successfully": - await manager.init() - try: - await manager.startGroupSync() - except Exception, CatchableError: - assert false, "exception raised: " & getCurrentExceptionMsg() + (await manager.init()).isOkOr: + raiseAssert $error + (await manager.startGroupSync()).isOkOr: + raiseAssert $error let idSecretHash = credentials[0].idSecretHash - let merkleRootBeforeRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootBeforeRes.isOk() - let merkleRootBefore = merkleRootBeforeRes.get() + let merkleRootBefore = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error + try: await manager.withdraw(idSecretHash) except Exception, CatchableError: assert false, "exception raised: " & getCurrentExceptionMsg() - let merkleRootAfterRes = manager.rlnInstance.getMerkleRoot() - require: - merkleRootAfterRes.isOk() - let merkleRootAfter = merkleRootAfterRes.get() + let merkleRootAfter = manager.rlnInstance.getMerkleRoot().valueOr: + raiseAssert $error check: merkleRootAfter.inHex() != merkleRootBefore.inHex() @@ -245,8 +229,10 @@ suite "Static group manager": try: manager.onWithdraw(callback) - await manager.init() - await manager.startGroupSync() + (await manager.init()).isOkOr: + raiseAssert $error + (await manager.startGroupSync()).isOkOr: + raiseAssert $error await manager.withdraw(idSecretHash) except Exception, CatchableError: diff --git a/tools/rln_keystore_generator/rln_keystore_generator.nim b/tools/rln_keystore_generator/rln_keystore_generator.nim index 6be2e1a270..c904519c0d 100644 --- a/tools/rln_keystore_generator/rln_keystore_generator.nim +++ b/tools/rln_keystore_generator/rln_keystore_generator.nim @@ -56,8 +56,11 @@ proc doRlnKeystoreGenerator*(conf: WakuNodeConf) = ethPrivateKey: some(conf.rlnRelayEthPrivateKey), ) try: - waitFor groupManager.init() - except CatchableError: + (waitFor groupManager.init()).isOkOr: + error "failure while initializing OnchainGroupManager", error = $error + quit(1) + # handling the exception is required since waitFor raises an exception + except Exception, CatchableError: error "failure while initializing OnchainGroupManager", error = getCurrentExceptionMsg() quit(1) diff --git a/waku/waku_rln_relay/conversion_utils.nim b/waku/waku_rln_relay/conversion_utils.nim index 59070c6a5a..5744507f8a 100644 --- a/waku/waku_rln_relay/conversion_utils.nim +++ b/waku/waku_rln_relay/conversion_utils.nim @@ -7,7 +7,7 @@ import std/[sequtils, strutils, algorithm], web3, chronicles, - stew/[arrayops, results, endians2], + stew/[arrayops, endians2], stint import ./constants, ./protocol_types import ../waku_keystore diff --git a/waku/waku_rln_relay/group_manager/group_manager_base.nim b/waku/waku_rln_relay/group_manager/group_manager_base.nim index 99dff9635c..6fce958300 100644 --- a/waku/waku_rln_relay/group_manager/group_manager_base.nim +++ b/waku/waku_rln_relay/group_manager/group_manager_base.nim @@ -40,18 +40,15 @@ type GroupManager* = ref object of RootObj # This proc is used to initialize the group manager # Any initialization logic should be implemented here -method init*(g: GroupManager): Future[void] {.base, async.} = - raise - newException(CatchableError, "init proc for " & $g.type & " is not implemented yet") +method init*(g: GroupManager): Future[GroupManagerResult[void]] {.base, async.} = + return err("init proc for " & $g.type & " is not implemented yet") # This proc is used to start the group sync process # It should be used to sync the group state with the rest of the group members method startGroupSync*( g: GroupManager -): Future[void] {.base, async: (raises: [Exception]).} = - raise newException( - CatchableError, "startGroupSync proc for " & $g.type & " is not implemented yet" - ) +): Future[GroupManagerResult[void]] {.base, async.} = + return err("startGroupSync proc for " & $g.type & " is not implemented yet") # This proc is used to register a new identity commitment into the merkle tree # The user may or may not have the identity secret to this commitment diff --git a/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim b/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim index f85145ad6a..dad3da9289 100644 --- a/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim +++ b/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim @@ -121,6 +121,13 @@ template initializedGuard(g: OnchainGroupManager): untyped = if not g.initialized: raise newException(CatchableError, "OnchainGroupManager is not initialized") +proc resultifiedInitGuard(g: OnchainGroupManager): GroupManagerResult[void] = + try: + initializedGuard(g) + return ok() + except CatchableError: + return err("OnchainGroupManager is not initialized") + template retryWrapper( g: OnchainGroupManager, res: auto, errStr: string, body: untyped ): auto = @@ -262,12 +269,12 @@ when defined(rln_v2): int(await ethRpc.provider.eth_gasPrice()) * 2 let idCommitment = identityCredential.idCommitment.toUInt256() - var txHash: TxHash let storageIndex = g.usingStorageIndex.get() debug "registering the member", idCommitment = idCommitment, storageIndex = storageIndex, userMessageLimit = userMessageLimit + var txHash: TxHash g.retryWrapper(txHash, "Failed to register the member"): await registryContract .register(storageIndex, idCommitment, u256(userMessageLimit)) @@ -319,10 +326,10 @@ else: int(await ethRpc.provider.eth_gasPrice()) * 2 let idCommitment = credentials.idCommitment.toUInt256() - var txHash: TxHash let storageIndex = g.usingStorageIndex.get() debug "registering the member", idCommitment = idCommitment, storageIndex = storageIndex + var txHash: TxHash g.retryWrapper(txHash, "Failed to register the member"): await registryContract.register(storageIndex, idCommitment).send( gasPrice = gasPrice @@ -584,7 +591,7 @@ proc getNewBlockCallback(g: OnchainGroupManager): proc = var handleBlockRes: bool g.retryWrapper(handleBlockRes, "Failed to handle new block"): await g.getAndHandleEvents(fromBlock, latestBlock) - return true + return handleBlockRes return wrappedCb @@ -675,17 +682,14 @@ proc startOnchainSync( method startGroupSync*( g: OnchainGroupManager -): Future[void] {.async: (raises: [Exception]).} = - initializedGuard(g) +): Future[GroupManagerResult[void]] {.async.} = + ?resultifiedInitGuard(g) # Get archive history try: await startOnchainSync(g) - except CatchableError: - raise newException( - CatchableError, - "failed to start onchain sync service: " & getCurrentExceptionMsg(), - ) - return + return ok() + except CatchableError, Exception: + return err("failed to start group sync: " & getCurrentExceptionMsg()) method onRegister*(g: OnchainGroupManager, cb: OnRegisterCallback) {.gcsafe.} = g.registerCb = some(cb) @@ -693,11 +697,12 @@ method onRegister*(g: OnchainGroupManager, cb: OnRegisterCallback) {.gcsafe.} = method onWithdraw*(g: OnchainGroupManager, cb: OnWithdrawCallback) {.gcsafe.} = g.withdrawCb = some(cb) -method init*(g: OnchainGroupManager): Future[void] {.async.} = - var ethRpc: Web3 +method init*(g: OnchainGroupManager): Future[GroupManagerResult[void]] {.async.} = # check if the Ethereum client is reachable + var ethRpc: Web3 g.retryWrapper(ethRpc, "Failed to connect to the Ethereum client"): await newWeb3(g.ethClientUrl) + # Set the chain id var chainId: Quantity g.retryWrapper(chainId, "Failed to get the chain id"): @@ -706,10 +711,9 @@ method init*(g: OnchainGroupManager): Future[void] {.async.} = if g.ethPrivateKey.isSome(): let pk = g.ethPrivateKey.get() - let pkParseRes = keys.PrivateKey.fromHex(pk) - if pkParseRes.isErr(): - raise newException(ValueError, "could not parse the private key") - ethRpc.privateKey = some(pkParseRes.get()) + let parsedPk = keys.PrivateKey.fromHex(pk).valueOr: + return err("failed to parse the private key" & ": " & $error) + ethRpc.privateKey = some(parsedPk) ethRpc.defaultAccount = ethRpc.privateKey.get().toPublicKey().toCanonicalAddress().Address @@ -732,9 +736,9 @@ method init*(g: OnchainGroupManager): Future[void] {.async.} = g.registryContract = some(registryContract) if g.keystorePath.isSome() and g.keystorePassword.isSome(): - if not existsFile(g.keystorePath.get()): + if not fileExists(g.keystorePath.get()): error "File provided as keystore path does not exist", path = g.keystorePath.get() - raise newException(CatchableError, "missing keystore") + return err("File provided as keystore path does not exist") var keystoreQuery = KeystoreMembership( membershipContract: @@ -743,17 +747,14 @@ method init*(g: OnchainGroupManager): Future[void] {.async.} = if g.membershipIndex.isSome(): keystoreQuery.treeIndex = MembershipIndex(g.membershipIndex.get()) waku_rln_membership_credentials_import_duration_seconds.nanosecondTime: - let keystoreCredRes = getMembershipCredentials( + let keystoreCred = getMembershipCredentials( path = g.keystorePath.get(), password = g.keystorePassword.get(), query = keystoreQuery, appInfo = RLNAppInfo, - ) - if keystoreCredRes.isErr(): - raise newException( - CatchableError, "could not parse the keystore: " & $keystoreCredRes.error - ) - let keystoreCred = keystoreCredRes.get() + ).valueOr: + return err("failed to get the keystore credentials: " & $error) + g.membershipIndex = some(keystoreCred.treeIndex) when defined(rln_v2): g.userMessageLimit = some(keystoreCred.userMessageLimit) @@ -763,15 +764,9 @@ method init*(g: OnchainGroupManager): Future[void] {.async.} = .memberExists(keystoreCred.identityCredential.idCommitment.toUInt256()) .call() if membershipExists == 0: - raise newException( - CatchableError, "the provided commitment does not have a membership" - ) + return err("the commitment does not have a membership") except CatchableError: - raise newException( - CatchableError, - "could not check if the commitment exists on the contract: " & - getCurrentExceptionMsg(), - ) + return err("failed to check if the commitment has a membership") g.idCredentials = some(keystoreCred.identityCredential) @@ -781,10 +776,10 @@ method init*(g: OnchainGroupManager): Future[void] {.async.} = elif metadataGetOptRes.get().isSome(): let metadata = metadataGetOptRes.get().get() if metadata.chainId != uint64(g.chainId.get()): - raise newException(ValueError, "persisted data: chain id mismatch") + return err("persisted data: chain id mismatch") if metadata.contractAddress != g.ethContractAddress.toLower(): - raise newException(ValueError, "persisted data: contract address mismatch") + return err("persisted data: contract address mismatch") g.latestProcessedBlock = metadata.lastProcessedBlock g.validRoots = metadata.validRoots.toDeque() @@ -825,6 +820,8 @@ method init*(g: OnchainGroupManager): Future[void] {.async.} = waku_rln_number_registered_memberships.set(int64(g.rlnInstance.leavesSet())) g.initialized = true + return ok() + method stop*(g: OnchainGroupManager): Future[void] {.async, gcsafe.} = g.blockFetchingActive = false diff --git a/waku/waku_rln_relay/group_manager/on_chain/retry_wrapper.nim b/waku/waku_rln_relay/group_manager/on_chain/retry_wrapper.nim index 1391599bcc..9ae000e3ce 100644 --- a/waku/waku_rln_relay/group_manager/on_chain/retry_wrapper.nim +++ b/waku/waku_rln_relay/group_manager/on_chain/retry_wrapper.nim @@ -1,5 +1,6 @@ import ../../../common/error_handling import chronos +import results type RetryStrategy* = object shouldRetry*: bool diff --git a/waku/waku_rln_relay/group_manager/static/group_manager.nim b/waku/waku_rln_relay/group_manager/static/group_manager.nim index 48d38dd725..c577512fac 100644 --- a/waku/waku_rln_relay/group_manager/static/group_manager.nim +++ b/waku/waku_rln_relay/group_manager/static/group_manager.nim @@ -10,7 +10,14 @@ template initializedGuard*(g: StaticGroupManager): untyped = if not g.initialized: raise newException(ValueError, "StaticGroupManager is not initialized") -method init*(g: StaticGroupManager): Future[void] {.async.} = +proc resultifiedInitGuard(g: StaticGroupManager): GroupManagerResult[void] = + try: + initializedGuard(g) + return ok() + except CatchableError: + return err("StaticGroupManager is not initialized") + +method init*(g: StaticGroupManager): Future[GroupManagerResult[void]] {.async.} = let groupSize = g.groupSize groupKeys = g.groupKeys @@ -18,14 +25,13 @@ method init*(g: StaticGroupManager): Future[void] {.async.} = if g.membershipIndex.isSome(): g.membershipIndex.get() else: - raise newException(ValueError, "Membership index is not set") + return err("membershipIndex is not set") if membershipIndex < MembershipIndex(0) or membershipIndex >= MembershipIndex(groupSize): - raise newException( - ValueError, + return err( "Invalid membership index. Must be within 0 and " & $(groupSize - 1) & "but was " & - $membershipIndex, + $membershipIndex ) when defined(rln_v2): g.userMessageLimit = some(DefaultUserMessageLimit) @@ -39,15 +45,13 @@ method init*(g: StaticGroupManager): Future[void] {.async.} = ) ) let leaves = rateCommitments.toLeaves().valueOr: - raise newException( - ValueError, "Failed to convert rate commitments to leaves: " & $error - ) + return err("Failed to convert rate commitments to leaves: " & $error) let membersInserted = g.rlnInstance.insertMembers(g.latestIndex, leaves) else: let idCommitments = groupKeys.mapIt(it.idCommitment) let membersInserted = g.rlnInstance.insertMembers(g.latestIndex, idCommitments) if not membersInserted: - raise newException(ValueError, "Failed to insert members into the merkle tree") + return err("Failed to insert members into the merkle tree") discard g.slideRootQueue() @@ -55,13 +59,14 @@ method init*(g: StaticGroupManager): Future[void] {.async.} = g.initialized = true - return + return ok() method startGroupSync*( g: StaticGroupManager -): Future[void] {.async: (raises: [Exception]).} = - initializedGuard(g) +): Future[GroupManagerResult[void]] {.async.} = + ?g.resultifiedInitGuard() # No-op + return ok() when defined(rln_v2): method register*( diff --git a/waku/waku_rln_relay/rln/wrappers.nim b/waku/waku_rln_relay/rln/wrappers.nim index 3f7c87ed4d..1f26e2eec4 100644 --- a/waku/waku_rln_relay/rln/wrappers.nim +++ b/waku/waku_rln_relay/rln/wrappers.nim @@ -4,8 +4,7 @@ import options, eth/keys, stew/[arrayops, byteutils, results, endians2], - std/[sequtils, strformat, strutils, tables], - nimcrypto/utils + std/[sequtils, strutils, tables] import ./rln_interface, ../conversion_utils, ../protocol_types, ../protocol_metrics import ../../waku_core, ../../waku_keystore diff --git a/waku/waku_rln_relay/rln_relay.nim b/waku/waku_rln_relay/rln_relay.nim index 0b1506620e..fc2491ca44 100644 --- a/waku/waku_rln_relay/rln_relay.nim +++ b/waku/waku_rln_relay/rln_relay.nim @@ -273,7 +273,7 @@ proc validateMessageAndUpdateLog*( ## validates the message and updates the log to prevent double messaging ## in future messages - let result = rlnPeer.validateMessage(msg, timeOption) + let isValidMessage = rlnPeer.validateMessage(msg, timeOption) let decodeRes = RateLimitProof.init(msg.proof) if decodeRes.isErr(): @@ -288,7 +288,7 @@ proc validateMessageAndUpdateLog*( # insert the message to the log (never errors) discard rlnPeer.updateLog(msgProof.epoch, proofMetadataRes.get()) - return result + return isValidMessage proc toRLNSignal*(wakumessage: WakuMessage): seq[byte] = ## it is a utility proc that prepares the `data` parameter of the proof generation procedure i.e., `proofGen` that resides in the current module @@ -397,23 +397,22 @@ proc generateRlnValidator*( proc mount( conf: WakuRlnConfig, registrationHandler = none(RegistrationHandler) -): Future[WakuRlnRelay] {.async: (raises: [Exception]).} = +): Future[RlnRelayResult[WakuRlnRelay]] {.async.} = var groupManager: GroupManager wakuRlnRelay: WakuRLNRelay # create an RLN instance - let rlnInstanceRes = createRLNInstance(tree_path = conf.rlnRelayTreePath) - if rlnInstanceRes.isErr(): - raise newException(CatchableError, "RLN instance creation failed") - let rlnInstance = rlnInstanceRes.get() + let rlnInstance = createRLNInstance(tree_path = conf.rlnRelayTreePath).valueOr: + return err("could not create RLN instance: " & $error) + if not conf.rlnRelayDynamic: # static setup - let parsedGroupKeysRes = StaticGroupKeys.toIdentityCredentials() - if parsedGroupKeysRes.isErr(): - raise newException(ValueError, "Static group keys are not valid") + let parsedGroupKeys = StaticGroupKeys.toIdentityCredentials().valueOr: + return err("could not parse static group keys: " & $error) + groupManager = StaticGroupManager( groupSize: StaticGroupSize, - groupKeys: parsedGroupKeysRes.get(), + groupKeys: parsedGroupKeys, membershipIndex: conf.rlnRelayCredIndex, rlnInstance: rlnInstance, onFatalErrorAction: conf.onFatalErrorAction, @@ -442,25 +441,33 @@ proc mount( ) # Initialize the groupManager - await groupManager.init() + (await groupManager.init()).isOkOr: + return err("could not initialize the group manager: " & $error) # Start the group sync - await groupManager.startGroupSync() + (await groupManager.startGroupSync()).isOkOr: + return err("could not start the group sync: " & $error) when defined(rln_v2): - return WakuRLNRelay( - groupManager: groupManager, - nonceManager: - NonceManager.init(conf.rlnRelayUserMessageLimit, conf.rlnEpochSizeSec.float), - rlnEpochSizeSec: conf.rlnEpochSizeSec, - rlnMaxEpochGap: max(uint64(MaxClockGapSeconds / float64(conf.rlnEpochSizeSec)), 1), - onFatalErrorAction: conf.onFatalErrorAction, + return ok( + WakuRLNRelay( + groupManager: groupManager, + nonceManager: + NonceManager.init(conf.rlnRelayUserMessageLimit, conf.rlnEpochSizeSec.float), + rlnEpochSizeSec: conf.rlnEpochSizeSec, + rlnMaxEpochGap: + max(uint64(MaxClockGapSeconds / float64(conf.rlnEpochSizeSec)), 1), + onFatalErrorAction: conf.onFatalErrorAction, + ) ) else: - return WakuRLNRelay( - groupManager: groupManager, - rlnEpochSizeSec: conf.rlnEpochSizeSec, - rlnMaxEpochGap: max(uint64(MaxClockGapSeconds / float64(conf.rlnEpochSizeSec)), 1), - onFatalErrorAction: conf.onFatalErrorAction, + return ok( + WakuRLNRelay( + groupManager: groupManager, + rlnEpochSizeSec: conf.rlnEpochSizeSec, + rlnMaxEpochGap: + max(uint64(MaxClockGapSeconds / float64(conf.rlnEpochSizeSec)), 1), + onFatalErrorAction: conf.onFatalErrorAction, + ) ) proc isReady*(rlnPeer: WakuRLNRelay): Future[bool] {.async: (raises: [Exception]).} = @@ -486,7 +493,6 @@ proc new*( ## 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. try: - let rlnRelay = await mount(conf, registrationHandler) - return ok(rlnRelay) - except: - return err("exception in new WakuRlnRelay: " & getCurrentExceptionMsg()) + return await mount(conf, registrationHandler) + except CatchableError: + return err("could not mount the rln-relay protocol: " & getCurrentExceptionMsg())