From deebee45d768c70c3f83128f301da8c879081bae Mon Sep 17 00:00:00 2001 From: Darshan K <35736874+darshankabariya@users.noreply.github.com> Date: Wed, 15 Oct 2025 19:08:46 +0530 Subject: [PATCH] feat: stateless RLN ( bump v0.9.0 ) (#3621) --- Makefile | 2 +- apps/benchmarks/benchmarks.nim | 2 +- scripts/build_rln.sh | 2 +- tests/node/test_wakunode_legacy_lightpush.nim | 2 +- tests/node/test_wakunode_lightpush.nim | 2 +- tests/waku_rln_relay/rln/test_wrappers.nim | 11 +- .../test_rln_group_manager_onchain.nim | 68 ++------- tests/waku_rln_relay/test_waku_rln_relay.nim | 95 ++----------- .../test_wakunode_rln_relay.nim | 10 +- tests/waku_rln_relay/utils_onchain.nim | 8 +- tests/wakunode_rest/test_rest_relay.nim | 10 +- .../rln_keystore_generator.nim | 19 +-- vendor/zerokit | 2 +- .../group_manager/on_chain/group_manager.nim | 34 ----- waku/waku_rln_relay/rln/rln_interface.nim | 52 ++----- waku/waku_rln_relay/rln/wrappers.nim | 130 ++---------------- 16 files changed, 68 insertions(+), 381 deletions(-) diff --git a/Makefile b/Makefile index 5b45960f1..37341792c 100644 --- a/Makefile +++ b/Makefile @@ -177,7 +177,7 @@ nimbus-build-system-nimble-dir: .PHONY: librln LIBRLN_BUILDDIR := $(CURDIR)/vendor/zerokit -LIBRLN_VERSION := v0.8.0 +LIBRLN_VERSION := v0.9.0 ifeq ($(detected_OS),Windows) LIBRLN_FILE := rln.lib diff --git a/apps/benchmarks/benchmarks.nim b/apps/benchmarks/benchmarks.nim index caa61cb77..3896cd765 100644 --- a/apps/benchmarks/benchmarks.nim +++ b/apps/benchmarks/benchmarks.nim @@ -15,7 +15,7 @@ proc benchmark( manager: OnChainGroupManager, registerCount: int, messageLimit: int ): Future[string] {.async, gcsafe.} = # Register a new member so that we can later generate proofs - let idCredentials = generateCredentials(manager.rlnInstance, registerCount) + let idCredentials = generateCredentials(registerCount) var start_time = getTime() for i in 0 .. registerCount - 1: diff --git a/scripts/build_rln.sh b/scripts/build_rln.sh index 2bc522f94..5e1b0caa5 100755 --- a/scripts/build_rln.sh +++ b/scripts/build_rln.sh @@ -49,6 +49,6 @@ else exit 1 fi # if submodule version = version in Makefile, build rln - cargo build --release -p rln --manifest-path "${build_dir}/rln/Cargo.toml" --features arkzkey + cargo build --release -p rln --manifest-path "${build_dir}/rln/Cargo.toml" cp "${build_dir}/target/release/librln.a" "${output_filename}" fi diff --git a/tests/node/test_wakunode_legacy_lightpush.nim b/tests/node/test_wakunode_legacy_lightpush.nim index b318171dd..9525892a1 100644 --- a/tests/node/test_wakunode_legacy_lightpush.nim +++ b/tests/node/test_wakunode_legacy_lightpush.nim @@ -151,7 +151,7 @@ suite "RLN Proofs as a Lightpush Service": client.mountLegacyLightPushClient() let manager1 = cast[OnchainGroupManager](server.wakuRlnRelay.groupManager) - let idCredentials1 = generateCredentials(manager1.rlnInstance) + let idCredentials1 = generateCredentials() try: waitFor manager1.register(idCredentials1, UserMessageLimit(20)) diff --git a/tests/node/test_wakunode_lightpush.nim b/tests/node/test_wakunode_lightpush.nim index d52eb242d..27c3a4d3e 100644 --- a/tests/node/test_wakunode_lightpush.nim +++ b/tests/node/test_wakunode_lightpush.nim @@ -151,7 +151,7 @@ suite "RLN Proofs as a Lightpush Service": client.mountLightPushClient() let manager1 = cast[OnchainGroupManager](server.wakuRlnRelay.groupManager) - let idCredentials1 = generateCredentials(manager1.rlnInstance) + let idCredentials1 = generateCredentials() try: waitFor manager1.register(idCredentials1, UserMessageLimit(20)) diff --git a/tests/waku_rln_relay/rln/test_wrappers.nim b/tests/waku_rln_relay/rln/test_wrappers.nim index 36526570b..29e24aae5 100644 --- a/tests/waku_rln_relay/rln/test_wrappers.nim +++ b/tests/waku_rln_relay/rln/test_wrappers.nim @@ -34,14 +34,9 @@ proc valid(x: seq[byte]): bool = return true suite "membershipKeyGen": - var rlnRes {.threadvar.}: RLNResult - - setup: - rlnRes = createRLNInstanceWrapper() - test "ok": # Given we generate valid membership keys - let identityCredentialsRes = membershipKeyGen(rlnRes.get()) + let identityCredentialsRes = membershipKeyGen() # Then it contains valid identity credentials let identityCredentials = identityCredentialsRes.get() @@ -62,7 +57,7 @@ suite "membershipKeyGen": keyGenMock # When we generate the membership keys - let identityCredentialsRes = membershipKeyGen(rlnRes.get()) + let identityCredentialsRes = membershipKeyGen() # Then it fails check: @@ -85,7 +80,7 @@ suite "membershipKeyGen": keyGenMock # When we generate the membership keys - let identityCredentialsRes = membershipKeyGen(rlnRes.get()) + let identityCredentialsRes = membershipKeyGen() # Then it fails check: 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 92826159e..cf697961a 100644 --- a/tests/waku_rln_relay/test_rln_group_manager_onchain.nim +++ b/tests/waku_rln_relay/test_rln_group_manager_onchain.nim @@ -60,44 +60,6 @@ suite "Onchain group manager": (waitFor manager.init()).isOkOr: raiseAssert $error - test "should error on initialization when loaded metadata does not match": - (waitFor manager.init()).isOkOr: - assert false, $error - let metadataSetRes = manager.setMetadata() - assert metadataSetRes.isOk(), metadataSetRes.error - let metadataOpt = manager.rlnInstance.getMetadata().valueOr: - assert false, $error - return - assert metadataOpt.isSome(), "metadata is not set" - let metadata = metadataOpt.get() - assert metadata.chainId == 1234, "chainId is not equal to 1234" - assert metadata.contractAddress == manager.ethContractAddress, - "contractAddress is not equal to " & manager.ethContractAddress - let web3 = manager.ethRpc.get() - let accounts = waitFor web3.provider.eth_accounts() - web3.defaultAccount = accounts[2] - let (privateKey, acc) = createEthAccount(web3) - let tokenAddress = (waitFor deployTestToken(privateKey, acc, web3)).valueOr: - assert false, "Failed to deploy test token contract: " & $error - return - let differentContractAddress = ( - waitFor executeForgeContractDeployScripts(privateKey, acc, web3) - ).valueOr: - assert false, "Failed to deploy RLN contract: " & $error - return - # simulating a change in the contractAddress - let manager2 = OnchainGroupManager( - ethClientUrls: @[EthClient], - ethContractAddress: $differentContractAddress, - rlnInstance: manager.rlnInstance, - onFatalErrorAction: proc(errStr: string) = - assert false, errStr - , - ) - let e = waitFor manager2.init() - (e).isErrOr: - assert false, "Expected error when contract address doesn't match" - test "should error if contract does not exist": manager.ethContractAddress = "0x0000000000000000000000000000000000000000" @@ -118,7 +80,7 @@ suite "Onchain group manager": check getCurrentExceptionMsg().len == 38 test "trackRootChanges: should sync to the state of the group": - let credentials = generateCredentials(manager.rlnInstance) + let credentials = generateCredentials() (waitFor manager.init()).isOkOr: raiseAssert $error @@ -133,17 +95,7 @@ suite "Onchain group manager": let merkleRootAfter = waitFor manager.fetchMerkleRoot() - let metadataSetRes = manager.setMetadata() - assert metadataSetRes.isOk(), metadataSetRes.error - - let metadataOpt = getMetadata(manager.rlnInstance).valueOr: - raiseAssert $error - - assert metadataOpt.isSome(), "metadata is not set" - let metadata = metadataOpt.get() - check: - metadata.validRoots == manager.validRoots.toSeq() merkleRootBefore != merkleRootAfter test "trackRootChanges: should fetch history correctly": @@ -152,7 +104,7 @@ suite "Onchain group manager": # so we can't use it in this test. const credentialCount = 6 - let credentials = generateCredentials(manager.rlnInstance, credentialCount) + let credentials = generateCredentials(credentialCount) (waitFor manager.init()).isOkOr: raiseAssert $error @@ -191,7 +143,7 @@ suite "Onchain group manager": (waitFor manager.init()).isOkOr: raiseAssert $error - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() let merkleRootBefore = waitFor manager.fetchMerkleRoot() try: @@ -207,7 +159,7 @@ suite "Onchain group manager": manager.latestIndex == 1 test "register: callback is called": - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() let idCommitment = idCredentials.idCommitment let fut = newFuture[void]() @@ -237,7 +189,7 @@ suite "Onchain group manager": waitFor fut test "withdraw: should guard against uninitialized state": - let idSecretHash = generateCredentials(manager.rlnInstance).idSecretHash + let idSecretHash = generateCredentials().idSecretHash try: waitFor manager.withdraw(idSecretHash) @@ -247,7 +199,7 @@ suite "Onchain group manager": assert false, "exception raised: " & getCurrentExceptionMsg() test "validateRoot: should validate good root": - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() let idCommitment = idCredentials.idCommitment let fut = newFuture[void]() @@ -298,7 +250,7 @@ suite "Onchain group manager": validated test "validateRoot: should reject bad root": - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() let idCommitment = idCredentials.idCommitment (waitFor manager.init()).isOkOr: @@ -331,7 +283,7 @@ suite "Onchain group manager": validated == false test "verifyProof: should verify valid proof": - let credentials = generateCredentials(manager.rlnInstance) + let credentials = generateCredentials() (waitFor manager.init()).isOkOr: raiseAssert $error @@ -383,7 +335,7 @@ suite "Onchain group manager": (waitFor manager.init()).isOkOr: raiseAssert $error - let idCredential = generateCredentials(manager.rlnInstance) + let idCredential = generateCredentials() try: waitFor manager.register(idCredential, UserMessageLimit(20)) @@ -420,7 +372,7 @@ suite "Onchain group manager": test "root queue should be updated correctly": const credentialCount = 12 - let credentials = generateCredentials(manager.rlnInstance, credentialCount) + let credentials = generateCredentials(credentialCount) (waitFor manager.init()).isOkOr: raiseAssert $error diff --git a/tests/waku_rln_relay/test_waku_rln_relay.nim b/tests/waku_rln_relay/test_waku_rln_relay.nim index 04fe1fdc2..0bbb448e1 100644 --- a/tests/waku_rln_relay/test_waku_rln_relay.nim +++ b/tests/waku_rln_relay/test_waku_rln_relay.nim @@ -36,15 +36,11 @@ suite "Waku rln relay": test "key_gen Nim Wrappers": let merkleDepth: csize_t = 20 - let rlnInstance = createRLNInstanceWrapper() - require: - rlnInstance.isOk() - # keysBufferPtr will hold the generated identity credential i.e., id trapdoor, nullifier, secret hash and commitment var keysBuffer: Buffer let keysBufferPtr = addr(keysBuffer) - done = key_gen(rlnInstance.get(), keysBufferPtr) + done = key_gen(keysBufferPtr, true) require: # check whether the keys are generated successfully done @@ -56,12 +52,7 @@ suite "Waku rln relay": info "generated keys: ", generatedKeys test "membership Key Generation": - # create an RLN instance - let rlnInstance = createRLNInstanceWrapper() - require: - rlnInstance.isOk() - - let idCredentialsRes = membershipKeyGen(rlnInstance.get()) + let idCredentialsRes = membershipKeyGen() require: idCredentialsRes.isOk() @@ -79,61 +70,6 @@ suite "Waku rln relay": info "the generated identity credential: ", idCredential - test "setMetadata rln utils": - # create an RLN instance which also includes an empty Merkle tree - let rlnInstance = createRLNInstanceWrapper() - require: - rlnInstance.isOk() - let rln = rlnInstance.get() - check: - rln - .setMetadata( - RlnMetadata( - lastProcessedBlock: 128, - chainId: 1155511'u256, - contractAddress: "0x9c09146844c1326c2dbc41c451766c7138f88155", - ) - ) - .isOk() - - test "getMetadata rln utils": - # create an RLN instance which also includes an empty Merkle tree - let rlnInstance = createRLNInstanceWrapper() - require: - rlnInstance.isOk() - let rln = rlnInstance.get() - - require: - rln - .setMetadata( - RlnMetadata( - lastProcessedBlock: 128, - chainId: 1155511'u256, - contractAddress: "0x9c09146844c1326c2dbc41c451766c7138f88155", - ) - ) - .isOk() - - let metadataOpt = rln.getMetadata().valueOr: - raiseAssert $error - - assert metadataOpt.isSome(), "metadata is not set" - let metadata = metadataOpt.get() - check: - metadata.lastProcessedBlock == 128 - metadata.chainId == 1155511'u256 - metadata.contractAddress == "0x9c09146844c1326c2dbc41c451766c7138f88155" - - test "getMetadata: empty rln metadata": - # create an RLN instance which also includes an empty Merkle tree - let rln = createRLNInstanceWrapper().valueOr: - raiseAssert $error - let metadata = rln.getMetadata().valueOr: - raiseAssert $error - - check: - metadata.isNone() - test "hash Nim Wrappers": # create an RLN instance let rlnInstance = createRLNInstanceWrapper() @@ -149,7 +85,7 @@ suite "Waku rln relay": # prepare other inputs to the hash function let outputBuffer = default(Buffer) - let hashSuccess = sha256(unsafeAddr hashInputBuffer, unsafeAddr outputBuffer) + let hashSuccess = sha256(unsafeAddr hashInputBuffer, unsafeAddr outputBuffer, true) require: hashSuccess let outputArr = cast[ptr array[32, byte]](outputBuffer.`ptr`)[] @@ -348,7 +284,7 @@ suite "Waku rln relay": raiseAssert $error let manager = cast[OnchainGroupManager](wakuRlnRelay.groupManager) - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() try: waitFor manager.register(idCredentials, UserMessageLimit(20)) @@ -405,7 +341,7 @@ suite "Waku rln relay": raiseAssert $error let manager = cast[OnchainGroupManager](wakuRlnRelay.groupManager) - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() try: waitFor manager.register(idCredentials, UserMessageLimit(20)) @@ -455,7 +391,7 @@ suite "Waku rln relay": raiseAssert "failed to create waku rln relay: " & $error let manager1 = cast[OnchainGroupManager](wakuRlnRelay1.groupManager) - let idCredentials1 = generateCredentials(manager1.rlnInstance) + let idCredentials1 = generateCredentials() try: waitFor manager1.register(idCredentials1, UserMessageLimit(20)) @@ -469,7 +405,7 @@ suite "Waku rln relay": raiseAssert "failed to create waku rln relay: " & $error let manager2 = cast[OnchainGroupManager](wakuRlnRelay2.groupManager) - let idCredentials2 = generateCredentials(manager2.rlnInstance) + let idCredentials2 = generateCredentials() try: waitFor manager2.register(idCredentials2, UserMessageLimit(20)) @@ -502,15 +438,7 @@ suite "Waku rln relay": msgValidate2 == MessageValidationResult.Valid test "toIDCommitment and toUInt256": - # create an instance of rln - let rlnInstance = createRLNInstanceWrapper() - require: - rlnInstance.isOk() - - let rln = rlnInstance.get() - - # create an idendity credential - let idCredentialRes = rln.membershipKeyGen() + let idCredentialRes = membershipKeyGen() require: idCredentialRes.isOk() @@ -526,12 +454,7 @@ suite "Waku rln relay": idCredential.idCommitment == idCommitment test "Read/Write RLN credentials": - # create an RLN instance - let rlnInstance = createRLNInstanceWrapper() - require: - rlnInstance.isOk() - - let idCredentialRes = membershipKeyGen(rlnInstance.get()) + let idCredentialRes = membershipKeyGen() require: idCredentialRes.isOk() diff --git a/tests/waku_rln_relay/test_wakunode_rln_relay.nim b/tests/waku_rln_relay/test_wakunode_rln_relay.nim index 4349859fc..7308ae257 100644 --- a/tests/waku_rln_relay/test_wakunode_rln_relay.nim +++ b/tests/waku_rln_relay/test_wakunode_rln_relay.nim @@ -63,7 +63,7 @@ procSuite "WakuNode - RLN relay": # Registration is mandatory before sending messages with rln-relay let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager) - let idCredentials1 = generateCredentials(manager1.rlnInstance) + let idCredentials1 = generateCredentials() try: waitFor manager1.register(idCredentials1, UserMessageLimit(20)) @@ -180,7 +180,7 @@ procSuite "WakuNode - RLN relay": await node.mountRlnRelay(wakuRlnConfig) await node.start() let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager) - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() try: waitFor manager.register(idCredentials, UserMessageLimit(20)) @@ -299,7 +299,7 @@ procSuite "WakuNode - RLN relay": await node1.start() let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager) - let idCredentials1 = generateCredentials(manager1.rlnInstance) + let idCredentials1 = generateCredentials() try: waitFor manager1.register(idCredentials1, UserMessageLimit(20)) @@ -416,7 +416,7 @@ procSuite "WakuNode - RLN relay": # Registration is mandatory before sending messages with rln-relay let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager) - let idCredentials1 = generateCredentials(manager1.rlnInstance) + let idCredentials1 = generateCredentials() try: waitFor manager1.register(idCredentials1, UserMessageLimit(20)) @@ -583,7 +583,7 @@ procSuite "WakuNode - RLN relay": # Registration is mandatory before sending messages with rln-relay let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager) - let idCredentials1 = generateCredentials(manager1.rlnInstance) + let idCredentials1 = generateCredentials() try: waitFor manager1.register(idCredentials1, UserMessageLimit(20)) diff --git a/tests/waku_rln_relay/utils_onchain.nim b/tests/waku_rln_relay/utils_onchain.nim index 69807a544..85f627aa0 100644 --- a/tests/waku_rln_relay/utils_onchain.nim +++ b/tests/waku_rln_relay/utils_onchain.nim @@ -44,8 +44,8 @@ func strip0xPrefix(s: string): string = else: s -proc generateCredentials*(rlnInstance: ptr RLN): IdentityCredential = - let credRes = membershipKeyGen(rlnInstance) +proc generateCredentials*(): IdentityCredential = + let credRes = membershipKeyGen() return credRes.get() proc getRateCommitment*( @@ -55,10 +55,10 @@ proc getRateCommitment*( idCommitment: idCredential.idCommitment, userMessageLimit: userMessageLimit ).toLeaf() -proc generateCredentials*(rlnInstance: ptr RLN, n: int): seq[IdentityCredential] = +proc generateCredentials*(n: int): seq[IdentityCredential] = var credentials: seq[IdentityCredential] for i in 0 ..< n: - credentials.add(generateCredentials(rlnInstance)) + credentials.add(generateCredentials()) return credentials proc getContractAddressFromDeployScriptOutput(output: string): Result[string, string] = diff --git a/tests/wakunode_rest/test_rest_relay.nim b/tests/wakunode_rest/test_rest_relay.nim index 16705658a..99470dbc8 100644 --- a/tests/wakunode_rest/test_rest_relay.nim +++ b/tests/wakunode_rest/test_rest_relay.nim @@ -265,7 +265,7 @@ suite "Waku v2 Rest API - Relay": await node.start() # Registration is mandatory before sending messages with rln-relay let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager) - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() try: waitFor manager.register(idCredentials, UserMessageLimit(20)) @@ -516,7 +516,7 @@ suite "Waku v2 Rest API - Relay": await node.start() # Registration is mandatory before sending messages with rln-relay let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager) - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() try: waitFor manager.register(idCredentials, UserMessageLimit(20)) @@ -588,7 +588,7 @@ suite "Waku v2 Rest API - Relay": # Registration is mandatory before sending messages with rln-relay let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager) - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() try: waitFor manager.register(idCredentials, UserMessageLimit(20)) @@ -650,7 +650,7 @@ suite "Waku v2 Rest API - Relay": # Registration is mandatory before sending messages with rln-relay let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager) - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() try: waitFor manager.register(idCredentials, UserMessageLimit(20)) @@ -725,7 +725,7 @@ suite "Waku v2 Rest API - Relay": # Registration is mandatory before sending messages with rln-relay let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager) - let idCredentials = generateCredentials(manager.rlnInstance) + let idCredentials = generateCredentials() try: waitFor manager.register(idCredentials, UserMessageLimit(20)) diff --git a/tools/rln_keystore_generator/rln_keystore_generator.nim b/tools/rln_keystore_generator/rln_keystore_generator.nim index c4634f860..36a3759c9 100644 --- a/tools/rln_keystore_generator/rln_keystore_generator.nim +++ b/tools/rln_keystore_generator/rln_keystore_generator.nim @@ -30,16 +30,8 @@ proc doRlnKeystoreGenerator*(conf: RlnKeystoreGeneratorConf) = # 1. load configuration trace "configuration", conf = $conf - # 2. initialize rlnInstance - let rlnInstanceRes = createRLNInstance(d = 20) - if rlnInstanceRes.isErr(): - error "failure while creating RLN instance", error = rlnInstanceRes.error - quit(1) - - let rlnInstance = rlnInstanceRes.get() - - # 3. generate credentials - let credentialRes = rlnInstance.membershipKeyGen() + # 2. generate credentials + let credentialRes = membershipKeyGen() if credentialRes.isErr(): error "failure while generating credentials", error = credentialRes.error quit(1) @@ -61,12 +53,11 @@ proc doRlnKeystoreGenerator*(conf: RlnKeystoreGeneratorConf) = error "Unrecoverable error occurred", error = msg quit(QuitFailure) - # 4. initialize OnchainGroupManager + # 3. initialize OnchainGroupManager let groupManager = OnchainGroupManager( ethClientUrls: conf.ethClientUrls, chainId: conf.chainId, ethContractAddress: conf.ethContractAddress, - rlnInstance: rlnInstance, keystorePath: none(string), keystorePassword: none(string), ethPrivateKey: some(conf.ethPrivateKey), @@ -82,7 +73,7 @@ proc doRlnKeystoreGenerator*(conf: RlnKeystoreGeneratorConf) = error = getCurrentExceptionMsg() quit(1) - # 5. register on-chain + # 4. register on-chain try: waitFor groupManager.register(credential, conf.userMessageLimit) except Exception, CatchableError: @@ -98,7 +89,7 @@ proc doRlnKeystoreGenerator*(conf: RlnKeystoreGeneratorConf) = membershipIndex = groupManager.membershipIndex.get() info "Your user message limit is", userMessageLimit = conf.userMessageLimit - # 6. write to keystore + # 5. write to keystore let keystoreCred = KeystoreMembership( membershipContract: MembershipContract( chainId: $groupManager.chainId, address: conf.ethContractAddress diff --git a/vendor/zerokit b/vendor/zerokit index dc0b31752..a4bb3feb5 160000 --- a/vendor/zerokit +++ b/vendor/zerokit @@ -1 +1 @@ -Subproject commit dc0b31752c91e7b4fefc441cfa6a8210ad7dba7b +Subproject commit a4bb3feb5054e6fd24827adf204493e6e173437b 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 860745674..76c00408e 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 @@ -144,25 +144,6 @@ proc fetchMaxMembershipRateLimit*( error "Failed to fetch max membership rate limit", error = getCurrentExceptionMsg() return err("Failed to fetch max membership rate limit: " & getCurrentExceptionMsg()) -proc setMetadata*( - g: OnchainGroupManager, lastProcessedBlock = none(BlockNumber) -): GroupManagerResult[void] = - let normalizedBlock = lastProcessedBlock.get(g.latestProcessedBlock) - try: - let metadataSetRes = g.rlnInstance.setMetadata( - RlnMetadata( - lastProcessedBlock: normalizedBlock.uint64, - chainId: g.chainId, - contractAddress: g.ethContractAddress, - validRoots: g.validRoots.toSeq(), - ) - ) - if metadataSetRes.isErr(): - return err("failed to persist rln metadata: " & metadataSetRes.error) - except CatchableError: - return err("failed to persist rln metadata: " & getCurrentExceptionMsg()) - return ok() - template initializedGuard(g: OnchainGroupManager): untyped = if not g.initialized: raise newException(CatchableError, "OnchainGroupManager is not initialized") @@ -593,18 +574,6 @@ method init*(g: OnchainGroupManager): Future[GroupManagerResult[void]] {.async.} g.idCredentials = some(keystoreCred.identityCredential) - let metadataGetOptRes = g.rlnInstance.getMetadata() - if metadataGetOptRes.isErr(): - warn "could not initialize with persisted rln metadata" - elif metadataGetOptRes.get().isSome(): - let metadata = metadataGetOptRes.get().get() - if metadata.chainId != g.chainId: - return err( - fmt"chain id mismatch. persisted={metadata.chainId}, smart_contract_chainId={g.chainId}" - ) - if metadata.contractAddress != g.ethContractAddress.toLower(): - return err("persisted data: contract address mismatch") - let maxMembershipRateLimitRes = await g.fetchMaxMembershipRateLimit() let maxMembershipRateLimit = maxMembershipRateLimitRes.valueOr: return err("failed to fetch max membership rate limit: " & error) @@ -631,9 +600,6 @@ method stop*(g: OnchainGroupManager): Future[void] {.async, gcsafe.} = if g.ethRpc.isSome(): g.ethRpc.get().ondisconnect = nil await g.ethRpc.get().close() - let flushed = g.rlnInstance.flush() - if not flushed: - error "failed to flush to the tree db" g.initialized = false diff --git a/waku/waku_rln_relay/rln/rln_interface.nim b/waku/waku_rln_relay/rln/rln_interface.nim index 98d415657..0bb0ef6b0 100644 --- a/waku/waku_rln_relay/rln/rln_interface.nim +++ b/waku/waku_rln_relay/rln/rln_interface.nim @@ -23,7 +23,7 @@ proc toBuffer*(x: openArray[byte]): Buffer = #-------------------------------- zkSNARKs operations ----------------------------------------- proc key_gen*( - ctx: ptr RLN, output_buffer: ptr Buffer + output_buffer: ptr Buffer, is_little_endian: bool ): bool {.importc: "extended_key_gen".} ## generates identity trapdoor, identity nullifier, identity secret hash and id commitment tuple serialized inside output_buffer as | identity_trapdoor<32> | identity_nullifier<32> | identity_secret_hash<32> | id_commitment<32> | @@ -32,7 +32,7 @@ proc key_gen*( ## the return bool value indicates the success or failure of the operation proc seeded_key_gen*( - ctx: ptr RLN, input_buffer: ptr Buffer, output_buffer: ptr Buffer + input_buffer: ptr Buffer, output_buffer: ptr Buffer, is_little_endian: bool ): bool {.importc: "seeded_extended_key_gen".} ## generates identity trapdoor, identity nullifier, identity secret hash and id commitment tuple serialized inside output_buffer as | identity_trapdoor<32> | identity_nullifier<32> | identity_secret_hash<32> | id_commitment<32> | using ChaCha20 @@ -40,6 +40,7 @@ proc seeded_key_gen*( ## The input seed provided by the user is hashed using Keccak256 before being passed to ChaCha20 as seed. ## identity secret hash is the poseidon hash of [identity_trapdoor, identity_nullifier] ## id commitment is the poseidon hash of the identity secret hash +# use_little_endian: if true, uses big or little endian for serialization (default: true) ## the return bool value indicates the success or failure of the operation proc generate_proof*( @@ -120,39 +121,34 @@ proc zk_verify*( ## the verification of the zk proof is available in proof_is_valid_ptr, where a value of true indicates success and false a failure ## the return bool value indicates the success or failure of the operation -#---------------------------------------------------------------------------------------------- - #-------------------------------- Common procedures ------------------------------------------- +# stateful version proc new_circuit*( - tree_height: uint, input_buffer: ptr Buffer, ctx: ptr (ptr RLN) + tree_depth: uint, input_buffer: ptr Buffer, ctx: ptr (ptr RLN) ): bool {.importc: "new".} ## creates an instance of rln object as defined by the zerokit RLN lib -## tree_height represent the depth of the Merkle tree ## input_buffer contains a serialization of the path where the circuit resources can be found (.r1cs, .wasm, .zkey and optionally the verification_key.json) ## ctx holds the final created rln object ## the return bool value indicates the success or failure of the operation +# stateless version +proc new_circuit*(ctx: ptr (ptr RLN)): bool {.importc: "new".} + proc new_circuit_from_data*( - tree_height: uint, - circom_buffer: ptr Buffer, - zkey_buffer: ptr Buffer, - vk_buffer: ptr Buffer, - ctx: ptr (ptr RLN), + zkey_buffer: ptr Buffer, graph_buffer: ptr Buffer, ctx: ptr (ptr RLN) ): bool {.importc: "new_with_params".} ## creates an instance of rln object as defined by the zerokit RLN lib by passing the required inputs as byte arrays -## tree_height represent the depth of the Merkle tree -## circom_buffer contains the bytes read from the Circom .wasm circuit ## zkey_buffer contains the bytes read from the .zkey proving key -## vk_buffer contains the bytes read from the verification_key.json +## graph_buffer contains the bytes read from the graph data file ## ctx holds the final created rln object ## the return bool value indicates the success or failure of the operation #-------------------------------- Hashing utils ------------------------------------------- proc sha256*( - input_buffer: ptr Buffer, output_buffer: ptr Buffer + input_buffer: ptr Buffer, output_buffer: ptr Buffer, is_little_endian: bool ): bool {.importc: "hash".} ## it hashes (sha256) the plain text supplied in inputs_buffer and then maps it to a field element @@ -162,7 +158,7 @@ proc sha256*( ## the output_buffer contains 32 bytes hash output proc poseidon*( - input_buffer: ptr Buffer, output_buffer: ptr Buffer + input_buffer: ptr Buffer, output_buffer: ptr Buffer, is_little_endian: bool ): bool {.importc: "poseidon_hash".} ## it hashes (poseidon) the plain text supplied in inputs_buffer @@ -170,27 +166,3 @@ proc poseidon*( ## inputs_buffer holds the hash input as a byte seq ## the hash output is generated and populated inside output_buffer ## the output_buffer contains 32 bytes hash output - -#-------------------------------- Persistent Metadata utils ------------------------------------------- - -proc set_metadata*( - ctx: ptr RLN, input_buffer: ptr Buffer -): bool {.importc: "set_metadata".} - -## sets the metadata stored by ctx to the value passed by input_buffer -## the input_buffer holds a serialized representation of the metadata (format to be defined) -## input_buffer holds the metadata as a byte seq -## the return bool value indicates the success or failure of the operation - -proc get_metadata*( - ctx: ptr RLN, output_buffer: ptr Buffer -): bool {.importc: "get_metadata".} - -## gets the metadata stored by ctx and populates the passed pointer output_buffer with it -## the output_buffer holds the metadata as a byte seq -## the return bool value indicates the success or failure of the operation - -proc flush*(ctx: ptr RLN): bool {.importc: "flush".} -## flushes the write buffer to the database -## the return bool value indicates the success or failure of the operation -## This allows more robust and graceful handling of the database connection diff --git a/waku/waku_rln_relay/rln/wrappers.nim b/waku/waku_rln_relay/rln/wrappers.nim index 99433444d..d1dec2b38 100644 --- a/waku/waku_rln_relay/rln/wrappers.nim +++ b/waku/waku_rln_relay/rln/wrappers.nim @@ -14,7 +14,7 @@ import ../../waku_core, ../../waku_keystore logScope: topics = "waku rln_relay ffi" -proc membershipKeyGen*(ctxPtr: ptr RLN): RlnRelayResult[IdentityCredential] = +proc membershipKeyGen*(): RlnRelayResult[IdentityCredential] = ## generates a IdentityCredential that can be used for the registration into the rln membership contract ## Returns an error if the key generation fails @@ -22,7 +22,7 @@ proc membershipKeyGen*(ctxPtr: ptr RLN): RlnRelayResult[IdentityCredential] = var keysBuffer: Buffer keysBufferPtr = addr(keysBuffer) - done = key_gen(ctxPtr, keysBufferPtr) + done = key_gen(keysBufferPtr, true) # check whether the keys are generated successfully if (done == false): @@ -80,14 +80,13 @@ proc `%`(c: RlnConfig): JsonNode = } return %[("resources_folder", %c.resources_folder), ("tree_config", %tree_config)] -proc createRLNInstanceLocal(d = MerkleTreeDepth): RLNResult = +proc createRLNInstanceLocal(): RLNResult = ## generates an instance of RLN ## An RLN instance supports both zkSNARKs logics and Merkle tree data structure and operations - ## d indicates the depth of Merkle tree ## Returns an error if the instance creation fails let rln_config = RlnConfig( - resources_folder: "tree_height_" & $d & "/", + resources_folder: "tree_height_/", tree_config: RlnTreeConfig( cache_capacity: 15_000, mode: "high_throughput", @@ -100,7 +99,7 @@ proc createRLNInstanceLocal(d = MerkleTreeDepth): RLNResult = var rlnInstance: ptr RLN - merkleDepth: csize_t = uint(d) + merkleDepth: csize_t = uint(20) configBuffer = serialized_rln_config.toOpenArrayByte(0, serialized_rln_config.high).toBuffer() @@ -112,12 +111,12 @@ proc createRLNInstanceLocal(d = MerkleTreeDepth): RLNResult = return err("error in parameters generation") return ok(rlnInstance) -proc createRLNInstance*(d = MerkleTreeDepth): RLNResult = +proc createRLNInstance*(): RLNResult = ## Wraps the rln instance creation for metrics ## Returns an error if the instance creation fails var res: RLNResult waku_rln_instance_creation_duration_seconds.nanosecondTime: - res = createRLNInstanceLocal(d) + res = createRLNInstanceLocal() return res proc sha256*(data: openArray[byte]): RlnRelayResult[MerkleNode] = @@ -128,7 +127,7 @@ proc sha256*(data: openArray[byte]): RlnRelayResult[MerkleNode] = outputBuffer: Buffer # will holds the hash output trace "sha256 hash input buffer length", bufflen = hashInputBuffer.len - let hashSuccess = sha256(addr hashInputBuffer, addr outputBuffer) + let hashSuccess = sha256(addr hashInputBuffer, addr outputBuffer, true) # check whether the hash call is done successfully if not hashSuccess: @@ -145,7 +144,7 @@ proc poseidon*(data: seq[seq[byte]]): RlnRelayResult[array[32, byte]] = hashInputBuffer = inputBytes.toBuffer() outputBuffer: Buffer # will holds the hash output - let hashSuccess = poseidon(addr hashInputBuffer, addr outputBuffer) + let hashSuccess = poseidon(addr hashInputBuffer, addr outputBuffer, true) # check whether the hash call is done successfully if not hashSuccess: @@ -192,114 +191,3 @@ proc extractMetadata*(proof: RateLimitProof): RlnRelayResult[ProofMetadata] = externalNullifier: externalNullifier, ) ) - -type RlnMetadata* = object - lastProcessedBlock*: uint64 - chainId*: UInt256 - contractAddress*: string - validRoots*: seq[MerkleNode] - -proc serialize(metadata: RlnMetadata): seq[byte] = - ## serializes the metadata - ## returns the serialized metadata - return concat( - @(metadata.lastProcessedBlock.toBytes()), - @(metadata.chainId.toBytes(Endianness.littleEndian)[0 .. 7]), - @(hexToSeqByte(toLower(metadata.contractAddress))), - @(uint64(metadata.validRoots.len()).toBytes()), - @(serialize(metadata.validRoots)), - ) - -type MerkleNodeSeq = seq[MerkleNode] - -proc deserialize(T: type MerkleNodeSeq, merkleNodeByteSeq: seq[byte]): T = - ## deserializes a byte seq to a seq of MerkleNodes - ## the order of serialization is |merkle_node_len<8>|merkle_node[len]| - - var roots = newSeq[MerkleNode]() - let len = uint64.fromBytes(merkleNodeByteSeq[0 .. 7], Endianness.littleEndian) - trace "length of valid roots", len - for i in 0'u64 ..< len: - # convert seq[byte] to array[32, byte] - let fromByte = 8 + i * 32 - let toByte = fromByte + 31 - let rawRoot = merkleNodeByteSeq[fromByte .. toByte] - trace "raw root", rawRoot = rawRoot - var root: MerkleNode - discard root.copyFrom(rawRoot) - roots.add(root) - return roots - -proc setMetadata*(rlnInstance: ptr RLN, metadata: RlnMetadata): RlnRelayResult[void] = - ## sets the metadata of the RLN instance - ## returns an error if the metadata could not be set - ## returns void if the metadata is set successfully - - # serialize the metadata - let metadataBytes = serialize(metadata) - trace "setting metadata", - metadata = metadata, metadataBytes = metadataBytes, len = metadataBytes.len - var metadataBuffer = metadataBytes.toBuffer() - let metadataBufferPtr = addr metadataBuffer - - # set the metadata - let metadataSet = set_metadata(rlnInstance, metadataBufferPtr) - - if not metadataSet: - return err("could not set the metadata") - return ok() - -proc getMetadata*(rlnInstance: ptr RLN): RlnRelayResult[Option[RlnMetadata]] = - ## gets the metadata of the RLN instance - ## returns an error if the metadata could not be retrieved - ## returns the metadata if the metadata is retrieved successfully - - # read the metadata - var - metadata {.noinit.}: Buffer = Buffer() - metadataPtr = addr(metadata) - getMetadataSuccessful = get_metadata(rlnInstance, metadataPtr) - if not getMetadataSuccessful: - return err("could not get the metadata") - trace "metadata length", metadataLen = metadata.len - - if metadata.len == 0: - return ok(none(RlnMetadata)) - - let - lastProcessedBlockOffset = 0 - chainIdOffset = lastProcessedBlockOffset + 8 - contractAddressOffset = chainIdOffset + 8 - validRootsOffset = contractAddressOffset + 20 - - var - lastProcessedBlock: uint64 - chainId: UInt256 - contractAddress: string - validRoots: MerkleNodeSeq - - # 8 + 8 + 20 + 8 + (5*32) = 204 - var metadataBytes = cast[ptr array[204, byte]](metadata.`ptr`)[] - trace "received metadata bytes", - metadataBytes = metadataBytes, len = metadataBytes.len - - lastProcessedBlock = - uint64.fromBytes(metadataBytes[lastProcessedBlockOffset .. chainIdOffset - 1]) - chainId = UInt256.fromBytes( - metadataBytes[chainIdOffset .. contractAddressOffset - 1], Endianness.littleEndian - ) - contractAddress = - byteutils.toHex(metadataBytes[contractAddressOffset .. validRootsOffset - 1]) - let validRootsBytes = metadataBytes[validRootsOffset .. metadataBytes.high] - validRoots = MerkleNodeSeq.deserialize(validRootsBytes) - - return ok( - some( - RlnMetadata( - lastProcessedBlock: lastProcessedBlock, - chainId: chainId, - contractAddress: "0x" & contractAddress, - validRoots: validRoots, - ) - ) - )