From 37bc8ba9f991ad4e52c456852df76e98e1dae35b Mon Sep 17 00:00:00 2001 From: darshankabariya Date: Wed, 12 Mar 2025 11:54:56 +0530 Subject: [PATCH] feat: isolate generateProof fuction till confidence --- .../test_rln_group_manager_onchain.nim | 11 +- .../group_manager/on_chain/group_manager.nim | 87 ------------ .../on_chain_sync/group_manager.nim | 128 ++++++++++++++++++ 3 files changed, 133 insertions(+), 93 deletions(-) create mode 100644 waku/waku_rln_relay/group_manager/on_chain_sync/group_manager.nim 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 116c7803c..ae1770d97 100644 --- a/tests/waku_rln_relay/test_rln_group_manager_onchain.nim +++ b/tests/waku_rln_relay/test_rln_group_manager_onchain.nim @@ -330,7 +330,7 @@ suite "Onchain group manager": debug "epoch in bytes", epochHex = epoch.inHex() # generate proof - let validProofRes = await manager.generateProof( + let validProofRes = manager.generateProof( data = messageBytes, epoch = epoch, messageId = MessageId(1) ) @@ -364,7 +364,7 @@ suite "Onchain group manager": debug "epoch in bytes", epochHex = epoch.inHex() # generate proof - let proofResult = await manager.generateProof( + let proofResult = manager.generateProof( data = messageBytes, epoch = epoch, messageId = MessageId(0) ) let validProof = proofResult.valueOr: @@ -408,10 +408,9 @@ suite "Onchain group manager": debug "epoch in bytes", epochHex = epoch.inHex() # generate proof - let proofResult = await manager.generateProof( + let validProof = manager.generateProof( data = messageBytes, epoch = epoch, messageId = MessageId(0) - ) - let validProof = proofResult.valueOr: + ).valueOr raiseAssert $error # verify the proof (should be true) @@ -453,7 +452,7 @@ suite "Onchain group manager": debug "epoch in bytes", epochHex = epoch.inHex() # generate proof - let invalidProofRes = await manager.generateProof( + let invalidProofRes = manager.generateProof( data = messageBytes, epoch = epoch, messageId = MessageId(0) ) 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 4d3b9e31a..b1fa8bb79 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 @@ -239,93 +239,6 @@ method withdrawBatch*( ): Future[void] {.async: (raises: [Exception]).} = initializedGuard(g) -method generateProof*( - g: OnchainGroupManager, - data: seq[byte], - epoch: Epoch, - messageId: MessageId, - rlnIdentifier = DefaultRlnIdentifier, -): Future[GroupManagerResult[RateLimitProof]] {.async, gcsafe, raises: [].} = - ## Generates an RLN proof using the cached Merkle proof and custom witness - # Ensure identity credentials and membership index are set - if g.idCredentials.isNone(): - return err("identity credentials are not set") - if g.membershipIndex.isNone(): - return err("membership index is not set") - if g.userMessageLimit.isNone(): - return err("user message limit is not set") - - # Retrieve the cached Merkle proof for the membership index - let index = stuint(g.membershipIndex.get(), 256) - - if not g.merkleProofsByIndex.hasKey(index): - await g.fetchMerkleProof(index) - let merkle_proof = g.merkleProofsByIndex[index] - - if merkle_proof.len == 0: - return err("Merkle proof not found") - - # Prepare the witness - let witness = Witness( - identity_secret: g.idCredentials.get().idSecretHash, - identity_nullifier: g.idCredentials.get().idNullifier, - merkle_proof: merkleProof, - external_nullifier: epoch, - signal: data, - message_id: messageId, - rln_identifier: rlnIdentifier, - ) - let serializedWitness = serialize(witness) - var inputBuffer = toBuffer(serializedWitness) - - # Generate the proof using the new zerokit API - var outputBuffer: Buffer - let success = - generate_proof_with_witness(g.rlnInstance, addr inputBuffer, addr outputBuffer) - if not success: - return err("Failed to generate proof") - - # Parse the proof into a RateLimitProof object - var proofValue = cast[ptr array[320, byte]](outputBuffer.`ptr`) - let proofBytes: array[320, byte] = proofValue[] - debug "proof content", proofHex = proofValue[].toHex - - ## parse the proof as [ proof<128> | root<32> | external_nullifier<32> | share_x<32> | share_y<32> | nullifier<32> ] - let - proofOffset = 128 - rootOffset = proofOffset + 32 - externalNullifierOffset = rootOffset + 32 - shareXOffset = externalNullifierOffset + 32 - shareYOffset = shareXOffset + 32 - nullifierOffset = shareYOffset + 32 - - var - zkproof: ZKSNARK - proofRoot, shareX, shareY: MerkleNode - externalNullifier: ExternalNullifier - nullifier: Nullifier - - discard zkproof.copyFrom(proofBytes[0 .. proofOffset - 1]) - discard proofRoot.copyFrom(proofBytes[proofOffset .. rootOffset - 1]) - discard - externalNullifier.copyFrom(proofBytes[rootOffset .. externalNullifierOffset - 1]) - discard shareX.copyFrom(proofBytes[externalNullifierOffset .. shareXOffset - 1]) - discard shareY.copyFrom(proofBytes[shareXOffset .. shareYOffset - 1]) - discard nullifier.copyFrom(proofBytes[shareYOffset .. nullifierOffset - 1]) - - # Create the RateLimitProof object - let output = RateLimitProof( - proof: zkproof, - merkleRoot: proofRoot, - externalNullifier: externalNullifier, - epoch: epoch, - rlnIdentifier: rlnIdentifier, - shareX: shareX, - shareY: shareY, - nullifier: nullifier, - ) - return ok(output) - # TODO: after slashing is enabled on the contract, use atomicBatch internally proc parseEvent( diff --git a/waku/waku_rln_relay/group_manager/on_chain_sync/group_manager.nim b/waku/waku_rln_relay/group_manager/on_chain_sync/group_manager.nim new file mode 100644 index 000000000..97ae668bf --- /dev/null +++ b/waku/waku_rln_relay/group_manager/on_chain_sync/group_manager.nim @@ -0,0 +1,128 @@ +{.push raises: [].} + +import + std/[tables, options], + chronos, + web3, + stint, + ../on_chain/group_manager as onchain, + ../../rln, + ../../conversion_utils + +logScope: + topics = "waku rln_relay onchain_sync_group_manager" + +type OnChainSyncGroupManager* = ref object of onchain.OnchainGroupManager + # Cache for merkle proofs by index + merkleProofsByIndex*: Table[Uint256, seq[Uint256]] + +method generateProof*( + g: OnChainSyncGroupManager, + data: seq[byte], + epoch: Epoch, + messageId: MessageId, + rlnIdentifier = DefaultRlnIdentifier, +): Future[GroupManagerResult[RateLimitProof]] {.async.} = + ## Generates an RLN proof using the cached Merkle proof and custom witness + # Ensure identity credentials and membership index are set + if g.idCredentials.isNone(): + return err("identity credentials are not set") + if g.membershipIndex.isNone(): + return err("membership index is not set") + if g.userMessageLimit.isNone(): + return err("user message limit is not set") + + # Retrieve the cached Merkle proof for the membership index + let index = stuint(g.membershipIndex.get(), 256) + + if not g.merkleProofsByIndex.hasKey(index): + try: + let merkleProofInvocation = g.wakuRlnContract.get().merkleProofElements(index) + let merkleProof = await merkleProofInvocation.call() + g.merkleProofsByIndex[index] = merkleProof + except CatchableError: + return err("Failed to fetch merkle proof: " & getCurrentExceptionMsg()) + + let merkleProof = g.merkleProofsByIndex[index] + if merkleProof.len == 0: + return err("Merkle proof not found") + + # Prepare the witness + let witness = Witness( + identity_secret: g.idCredentials.get().idSecretHash, + identity_nullifier: g.idCredentials.get().idNullifier, + merkle_proof: merkleProof, + external_nullifier: epoch, + signal: data, + message_id: messageId, + rln_identifier: rlnIdentifier, + ) + let serializedWitness = serialize(witness) + var inputBuffer = toBuffer(serializedWitness) + + # Generate the proof using the zerokit API + var outputBuffer: Buffer + let success = + generate_proof_with_witness(g.rlnInstance, addr inputBuffer, addr outputBuffer) + if not success: + return err("Failed to generate proof") + + # Parse the proof into a RateLimitProof object + var proofValue = cast[ptr array[320, byte]](outputBuffer.`ptr`) + let proofBytes: array[320, byte] = proofValue[] + + ## parse the proof as [ proof<128> | root<32> | external_nullifier<32> | share_x<32> | share_y<32> | nullifier<32> ] + let + proofOffset = 128 + rootOffset = proofOffset + 32 + externalNullifierOffset = rootOffset + 32 + shareXOffset = externalNullifierOffset + 32 + shareYOffset = shareXOffset + 32 + nullifierOffset = shareYOffset + 32 + + var + zkproof: ZKSNARK + proofRoot, shareX, shareY: MerkleNode + externalNullifier: ExternalNullifier + nullifier: Nullifier + + discard zkproof.copyFrom(proofBytes[0 .. proofOffset - 1]) + discard proofRoot.copyFrom(proofBytes[proofOffset .. rootOffset - 1]) + discard + externalNullifier.copyFrom(proofBytes[rootOffset .. externalNullifierOffset - 1]) + discard shareX.copyFrom(proofBytes[externalNullifierOffset .. shareXOffset - 1]) + discard shareY.copyFrom(proofBytes[shareXOffset .. shareYOffset - 1]) + discard nullifier.copyFrom(proofBytes[shareYOffset .. nullifierOffset - 1]) + + # Create the RateLimitProof object + let output = RateLimitProof( + proof: zkproof, + merkleRoot: proofRoot, + externalNullifier: externalNullifier, + epoch: epoch, + rlnIdentifier: rlnIdentifier, + shareX: shareX, + shareY: shareY, + nullifier: nullifier, + ) + return ok(output) + +method register*( + g: OnChainSyncGroupManager, + identityCredential: IdentityCredential, + userMessageLimit: UserMessageLimit, +): Future[void] {.async: (raises: [Exception]).} = + # Call parent's register method first + await procCall onchain.OnchainGroupManager(g).register( + identityCredential, userMessageLimit + ) + + # After registration, fetch and cache the merkle proof + let membershipIndex = g.membershipIndex.get() + try: + let merkleProofInvocation = + g.wakuRlnContract.get().merkleProofElements(stuint(membershipIndex, 256)) + let merkleProof = await merkleProofInvocation.call() + g.merkleProofsByIndex[stuint(membershipIndex, 256)] = merkleProof + except CatchableError: + error "Failed to fetch initial merkle proof: " & getCurrentExceptionMsg()