From a1db50ba8edc63a5a91cb074c1e8df75b8597039 Mon Sep 17 00:00:00 2001 From: rymnc <43716372+rymnc@users.noreply.github.com> Date: Tue, 27 Feb 2024 18:55:48 +0530 Subject: [PATCH] chore(rln-relay-v2): added tests for onchain rln-relay-v2 --- .github/workflows/ci.yml | 3 +- .../test_rln_group_manager_onchain.nim | 189 ++++++++++++++---- .../test_wakunode_rln_relay.nim | 11 +- .../group_manager/on_chain/group_manager.nim | 17 +- waku/waku_rln_relay/nonce_manager.nim | 2 +- waku/waku_rln_relay/rln/wrappers.nim | 23 ++- waku/waku_rln_relay/rln_relay.nim | 4 +- 7 files changed, 181 insertions(+), 68 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 481a5f82a5..8948ddbee6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -86,6 +86,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] + rln_v2: [true, false] runs-on: ${{ matrix.os }} timeout-minutes: 60 @@ -118,7 +119,7 @@ jobs: sudo docker run --rm -d -e POSTGRES_PASSWORD=test123 -p 5432:5432 postgres:9.6-alpine fi - make V=1 LOG_LEVEL=DEBUG QUICK_AND_DIRTY_COMPILER=1 POSTGRES=1 test testwakunode2 + make RLN_V2=${{matrix.rln_v2}} V=1 LOG_LEVEL=DEBUG QUICK_AND_DIRTY_COMPILER=1 POSTGRES=1 test testwakunode2 build-docker-image: needs: changes 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 63efbf7439..338e903a38 100644 --- a/tests/waku_rln_relay/test_rln_group_manager_onchain.nim +++ b/tests/waku_rln_relay/test_rln_group_manager_onchain.nim @@ -31,6 +31,11 @@ proc generateCredentials(rlnInstance: ptr RLN): IdentityCredential = let credRes = membershipKeyGen(rlnInstance) return credRes.get() +when defined(rln_v2): + proc getRateCommitment(idCredential: IdentityCredential, userMessageLimit: UserMessageLimit): RateCommitment = + return RateCommitment(idCommitment: idCredential.idCommitment, + userMessageLimit: userMessageLimit) + proc generateCredentials(rlnInstance: ptr RLN, n: int): seq[IdentityCredential] = var credentials: seq[IdentityCredential] for i in 0 ..< n: @@ -84,7 +89,11 @@ proc uploadRLNContract*(ethClientAddress: string): Future[Address] {.async.} = debug "Address of the deployed registry contract: ", contractAddress let registryContract = web3.contractSender(WakuRlnRegistry, contractAddress) - let newStorageReceipt = await registryContract.newStorage().send() + when defined(rln_v2): + let initReceipt = await registryContract.initialize().send() + let newStorageReceipt = await registryContract.newStorage(20.u256).send() + else: + let newStorageReceipt = await registryContract.newStorage().send() debug "Receipt of the newStorage transaction: ", newStorageReceipt let newBalance = await web3.provider.eth_getBalance(web3.defaultAccount, "latest") @@ -278,14 +287,24 @@ suite "Onchain group manager": proc callback(registrations: seq[Membership]): Future[void] {.async.} = require: registrations.len == 1 - registrations[0].idCommitment == credentials.idCommitment + registrations[0].index == 0 + when defined(rln_v2): + require: + registrations[0].rateCommitment == getRateCommitment(credentials, UserMessageLimit(1)) + else: + require: + registrations[0].idCommitment == credentials.idCommitment + require: registrations[0].index == 0 fut.complete() return callback try: manager.onRegister(generateCallback(fut)) - await manager.register(credentials) + when defined(rln_v2): + await manager.register(credentials, UserMessageLimit(1)) + else: + await manager.register(credentials) await manager.startGroupSync() except Exception, CatchableError: assert false, "exception raised: " & getCurrentExceptionMsg() @@ -319,11 +338,18 @@ suite "Onchain group manager": proc generateCallback(futs: TestGroupSyncFuts, credentials: seq[IdentityCredential]): OnRegisterCallback = var futureIndex = 0 proc callback(registrations: seq[Membership]): Future[void] {.async.} = - if registrations.len == 1 and - registrations[0].idCommitment == credentials[futureIndex].idCommitment and - registrations[0].index == MembershipIndex(futureIndex): - futs[futureIndex].complete() - futureIndex += 1 + when defined(rln_v2): + if registrations.len == 1 and + registrations[0].rateCommitment == getRateCommitment(credentials[futureIndex], UserMessageLimit(1)) and + registrations[0].index == MembershipIndex(futureIndex): + futs[futureIndex].complete() + futureIndex += 1 + else: + if registrations.len == 1 and + registrations[0].idCommitment == credentials[futureIndex].idCommitment and + registrations[0].index == MembershipIndex(futureIndex): + futs[futureIndex].complete() + futureIndex += 1 return callback try: @@ -331,7 +357,10 @@ suite "Onchain group manager": await manager.startGroupSync() for i in 0 ..< credentials.len(): - await manager.register(credentials[i]) + when defined(rln_v2): + await manager.register(credentials[i], UserMessageLimit(1)) + else: + await manager.register(credentials[i]) except Exception, CatchableError: assert false, "exception raised: " & getCurrentExceptionMsg() @@ -352,7 +381,11 @@ suite "Onchain group manager": let dummyCommitment = default(IDCommitment) try: - await manager.register(dummyCommitment) + when defined(rln_v2): + await manager.register(RateCommitment(idCommitment: dummyCommitment, + userMessageLimit: UserMessageLimit(1))) + else: + await manager.register(dummyCommitment) except CatchableError: assert true except Exception: @@ -375,7 +408,11 @@ suite "Onchain group manager": let merkleRootBefore = merkleRootBeforeRes.get() try: - await manager.register(idCommitment) + when defined(rln_v2): + await manager.register(RateCommitment(idCommitment: idCommitment, + userMessageLimit: UserMessageLimit(1))) + else: + await manager.register(idCommitment) except Exception, CatchableError: assert false, "exception raised when calling register: " & getCurrentExceptionMsg() @@ -396,17 +433,26 @@ suite "Onchain group manager": let fut = newFuture[void]() proc callback(registrations: seq[Membership]): Future[void] {.async.} = + + when defined(rln_v2): + require: + registrations[0].rateCommitment == RateCommitment(idCommitment: idCommitment, userMessageLimit: UserMessageLimit(1)) + else: + require: + registrations[0].idCommitment == idCommitment require: - registrations.len == 1 - registrations[0].idCommitment == idCommitment registrations[0].index == 0 + registrations.len == 1 fut.complete() manager.onRegister(callback) await manager.init() try: await manager.startGroupSync() - await manager.register(idCommitment) + when defined(rln_v2): + await manager.register(RateCommitment(idCommitment: idCommitment, userMessageLimit: UserMessageLimit(1))) + else: + await manager.register(idCommitment) except Exception, CatchableError: assert false, "exception raised: " & getCurrentExceptionMsg() @@ -438,18 +484,27 @@ suite "Onchain group manager": let fut = newFuture[void]() proc callback(registrations: seq[Membership]): Future[void] {.async.} = - if registrations.len == 1 and - registrations[0].idCommitment == credentials.idCommitment and - registrations[0].index == 0: - manager.idCredentials = some(credentials) - manager.membershipIndex = some(registrations[0].index) - fut.complete() + when defined(rln_v2): + if registrations.len == 1 and + registrations[0].rateCommitment == getRateCommitment(credentials, UserMessageLimit(1)) and + registrations[0].index == 0: + manager.idCredentials = some(credentials) + fut.complete() + else: + if registrations.len == 1 and + registrations[0].idCommitment == credentials.idCommitment and + registrations[0].index == 0: + manager.idCredentials = some(credentials) + fut.complete() manager.onRegister(callback) try: await manager.startGroupSync() - await manager.register(credentials) + when defined(rln_v2): + await manager.register(credentials, UserMessageLimit(1)) + else: + await manager.register(credentials) except Exception, CatchableError: assert false, "exception raised: " & getCurrentExceptionMsg() @@ -462,8 +517,14 @@ suite "Onchain group manager": debug "epoch in bytes", epochHex = epoch.inHex() # generate proof - let validProofRes = manager.generateProof(data = messageBytes, - epoch = epoch) + when defined(rln_v2): + let validProofRes = manager.generateProof(data = messageBytes, + epoch = epoch, + messageId = MessageId(1)) + else: + let validProofRes = manager.generateProof(data = messageBytes, + epoch = epoch) + require: validProofRes.isOk() let validProof = validProofRes.get() @@ -488,6 +549,8 @@ suite "Onchain group manager": ## Assume the registration occured out of band manager.idCredentials = some(credentials) manager.membershipIndex = some(MembershipIndex(0)) + when defined(rln_v2): + manager.userMessageLimit = some(UserMessageLimit(1)) let messageBytes = "Hello".toBytes() @@ -496,8 +559,13 @@ suite "Onchain group manager": debug "epoch in bytes", epochHex = epoch.inHex() # generate proof - let validProofRes = manager.generateProof(data = messageBytes, - epoch = epoch) + when defined(rln_v2): + let validProofRes = manager.generateProof(data = messageBytes, + epoch = epoch, + messageId = MessageId(0)) + else: + let validProofRes = manager.generateProof(data = messageBytes, + epoch = epoch) require: validProofRes.isOk() let validProof = validProofRes.get() @@ -517,18 +585,27 @@ suite "Onchain group manager": let fut = newFuture[void]() proc callback(registrations: seq[Membership]): Future[void] {.async.} = - if registrations.len == 1 and - registrations[0].idCommitment == credentials.idCommitment and - registrations[0].index == 0: - manager.idCredentials = some(credentials) - manager.membershipIndex = some(registrations[0].index) - fut.complete() + when defined(rln_v2): + if registrations.len == 1 and + registrations[0].rateCommitment == getRateCommitment(credentials, UserMessageLimit(1)) and + registrations[0].index == 0: + manager.idCredentials = some(credentials) + fut.complete() + else: + if registrations.len == 1 and + registrations[0].idCommitment == credentials.idCommitment and + registrations[0].index == 0: + manager.idCredentials = some(credentials) + fut.complete() manager.onRegister(callback) try: await manager.startGroupSync() - await manager.register(credentials) + when defined(rln_v2): + await manager.register(credentials, UserMessageLimit(1)) + else: + await manager.register(credentials) except Exception, CatchableError: assert false, "exception raised: " & getCurrentExceptionMsg() await fut @@ -540,8 +617,13 @@ suite "Onchain group manager": debug "epoch in bytes", epochHex = epoch.inHex() # generate proof - let validProofRes = manager.generateProof(data = messageBytes, - epoch = epoch) + when defined(rln_v2): + let validProofRes = manager.generateProof(data = messageBytes, + epoch = epoch, + messageId = MessageId(0)) + else: + let validProofRes = manager.generateProof(data = messageBytes, + epoch = epoch) require: validProofRes.isOk() let validProof = validProofRes.get() @@ -566,7 +648,10 @@ suite "Onchain group manager": let idCredential = generateCredentials(manager.rlnInstance) try: - await manager.register(idCredential.idCommitment) + when defined(rln_v2): + await manager.register(getRateCommitment(idCredential, UserMessageLimit(1))) + else: + await manager.register(idCredential.idCommitment) except Exception, CatchableError: assert false, "exception raised when calling startGroupSync: " & getCurrentExceptionMsg() @@ -575,6 +660,8 @@ suite "Onchain group manager": ## Assume the registration occured out of band manager.idCredentials = some(idCredential2) manager.membershipIndex = some(MembershipIndex(0)) + when defined(rln_v2): + manager.userMessageLimit = some(UserMessageLimit(1)) let messageBytes = "Hello".toBytes() @@ -583,8 +670,14 @@ suite "Onchain group manager": debug "epoch in bytes", epochHex = epoch.inHex() # generate proof - let invalidProofRes = manager.generateProof(data = messageBytes, - epoch = epoch) + when defined(rln_v2): + let invalidProofRes = manager.generateProof(data = messageBytes, + epoch = epoch, + messageId = MessageId(0)) + else: + let invalidProofRes = manager.generateProof(data = messageBytes, + epoch = epoch) + require: invalidProofRes.isOk() let invalidProof = invalidProofRes.get() @@ -613,18 +706,28 @@ suite "Onchain group manager": proc generateCallback(futs: TestBackfillFuts, credentials: seq[IdentityCredential]): OnRegisterCallback = var futureIndex = 0 proc callback(registrations: seq[Membership]): Future[void] {.async.} = - if registrations.len == 1 and - registrations[0].idCommitment == credentials[futureIndex].idCommitment and - registrations[0].index == MembershipIndex(futureIndex): - futs[futureIndex].complete() - futureIndex += 1 + when defined(rln_v2): + if registrations.len == 1 and + registrations[0].rateCommitment == getRateCommitment(credentials[futureIndex], UserMessageLimit(1)) and + registrations[0].index == MembershipIndex(futureIndex): + futs[futureIndex].complete() + futureIndex += 1 + else: + if registrations.len == 1 and + registrations[0].idCommitment == credentials[futureIndex].idCommitment and + registrations[0].index == MembershipIndex(futureIndex): + futs[futureIndex].complete() + futureIndex += 1 return callback try: manager.onRegister(generateCallback(futures, credentials)) await manager.startGroupSync() for i in 0 ..< credentials.len(): - await manager.register(credentials[i]) + when defined(rln_v2): + await manager.register(credentials[i], UserMessageLimit(1)) + else: + await manager.register(credentials[i]) except Exception, CatchableError: assert false, "exception raised: " & getCurrentExceptionMsg() diff --git a/tests/waku_rln_relay/test_wakunode_rln_relay.nim b/tests/waku_rln_relay/test_wakunode_rln_relay.nim index c57a68b83f..05361c718f 100644 --- a/tests/waku_rln_relay/test_wakunode_rln_relay.nim +++ b/tests/waku_rln_relay/test_wakunode_rln_relay.nim @@ -251,8 +251,15 @@ procSuite "WakuNode - RLN relay": contentTopicBytes = contentTopic.toBytes input = concat(payload, contentTopicBytes) extraBytes: seq[byte] = @[byte(1),2,3] - rateLimitProofRes = node1.wakuRlnRelay.groupManager.generateProof(concat(input, extraBytes), # we add extra bytes to invalidate proof verification against original payload - epoch) + + when defined(rln_v2): + let nonceManager = node1.wakuRlnRelay.nonceManager + let rateLimitProofRes = node1.wakuRlnRelay.groupManager.generateProof(input, + epoch, + MessageId(0)) + else: + let rateLimitProofRes = node1.wakuRlnRelay.groupManager.generateProof(concat(input, extraBytes), # we add extra bytes to invalidate proof verification against original payload + epoch) require: rateLimitProofRes.isOk() let rateLimitProof = rateLimitProofRes.get().encode().buffer 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 20891d4b26..9ed6de2f65 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 @@ -40,7 +40,9 @@ when defined(rln_v2): # this serves as an entrypoint into the rln storage contract proc register(storageIndex: Uint16, idCommitment: Uint256, userMessageLimit: Uint256) # this creates a new storage on the rln registry - proc newStorage() + proc newStorage(maxMessageLimit: Uint256) + # Initializes the implementation contract (only used in unit tests) + proc initialize() # membership contract interface contract(RlnStorage): @@ -142,10 +144,8 @@ when defined(rln_v2): initializedGuard(g) # convert the rateCommitment struct to a leaf value - let leavesRes = rateCommitments.toLeaves() - if leavesRes.isErr(): - raise newException(CatchableError, "failed to convert rateCommitments to leaves: " & leavesRes.error) - let leaves = cast[seq[seq[byte]]](leavesRes.get()) + let leaves = rateCommitments.toLeaves().valueOr: + raise newException(ValueError, "failed to convert rateCommitments to leaves: " & $error) waku_rln_membership_insertion_duration_seconds.nanosecondTime: let operationSuccess = g.rlnInstance.atomicWrite(some(start), @@ -269,11 +269,10 @@ when defined(rln_v2): let argumentsBytes = arguments # In TX log data, uints are encoded in big endian - userMessageLimit = UInt256.fromBytesBE(argumentsBytes[32..64]) membershipIndex = UInt256.fromBytesBE(argumentsBytes[64..^1]) + g.userMessageLimit = some(userMessageLimit) g.membershipIndex = some(membershipIndex.toMembershipIndex()) - g.userMessageLimit = some(userMessageLimit.toUserMessageLimit()) # don't handle member insertion into the tree here, it will be handled by the event listener return @@ -354,11 +353,11 @@ proc parseEvent(event: type MemberRegistered, try: # Parse the idComm offset += decode(data, offset, idComm) - # Parse the index - offset += decode(data, offset, index) when defined(rln_v2): # Parse the userMessageLimit offset += decode(data, offset, userMessageLimit) + # Parse the index + offset += decode(data, offset, index) when defined(rln_v2): return ok(Membership(rateCommitment: RateCommitment(idCommitment: idComm.toIDCommitment(), userMessageLimit: userMessageLimit.toUserMessageLimit()), diff --git a/waku/waku_rln_relay/nonce_manager.nim b/waku/waku_rln_relay/nonce_manager.nim index 6a0f34b073..d14e9a2811 100644 --- a/waku/waku_rln_relay/nonce_manager.nim +++ b/waku/waku_rln_relay/nonce_manager.nim @@ -52,7 +52,7 @@ proc init*(T: type NonceManager, nonceLimit: Nonce, epoch = EpochUnitSeconds): T ) -proc get*(n: NonceManager): NonceManagerResult[Nonce] = +proc getNonce*(n: NonceManager): NonceManagerResult[Nonce] = let now = getTime().toUnixFloat() var retNonce = n.nextNonce diff --git a/waku/waku_rln_relay/rln/wrappers.nim b/waku/waku_rln_relay/rln/wrappers.nim index da1a1d3b90..769a6e8ffc 100644 --- a/waku/waku_rln_relay/rln/wrappers.nim +++ b/waku/waku_rln_relay/rln/wrappers.nim @@ -161,19 +161,22 @@ proc poseidon*(data: seq[seq[byte]]): RlnRelayResult[array[32, byte]] = return ok(output) when defined(rln_v2): - func toLeaf*(rateCommitment: RateCommitment): RlnRelayResult[MerkleNode] {.inline.} = + proc toLeaf*(rateCommitment: RateCommitment): RlnRelayResult[IDCommitment] = let idCommitment = rateCommitment.idCommitment let userMessageLimit = cast[array[32, byte]](rateCommitment.userMessageLimit) - let leafRes = poseidon(@[@idCommitment, @userMessageLimit]) - return leafRes - - func toLeaves*(rateCommitments: seq[RateCommitment]): RlnRelayResult[seq[MerkleNode]] {.inline.} = - var leaves = newSeq[MerkleNode](rateCommitments.len) + let leaf = poseidon(@[@idCommitment, @userMessageLimit]).valueOr: + return err("could not convert the rate commitment to a leaf") + var retLeaf = newSeq[byte](32) + for i in 0..31: + retLeaf[i] = leaf[i] + return ok(retLeaf) + + proc toLeaves*(rateCommitments: seq[RateCommitment]): RlnRelayResult[seq[IDCommitment]] = + var leaves = newSeq[IDCommitment]() for rateCommitment in rateCommitments: - let leafRes = toLeaf(rateCommitment) - if leafRes.isErr(): - return err("could not convert the rate commitment to a leaf: " & leafRes.error) - leaves.add(leafRes.get()) + let leaf = toLeaf(rateCommitment).valueOr: + return err("could not convert the rate commitment to a leaf: " & $error) + leaves.add(leaf) return ok(leaves) # TODO: collocate this proc with the definition of the RateLimitProof diff --git a/waku/waku_rln_relay/rln_relay.nim b/waku/waku_rln_relay/rln_relay.nim index b1f8859938..33899e72fe 100644 --- a/waku/waku_rln_relay/rln_relay.nim +++ b/waku/waku_rln_relay/rln_relay.nim @@ -89,7 +89,7 @@ type WakuRLNRelay* = ref object of RootObj groupManager*: GroupManager onFatalErrorAction*: OnFatalErrorHandler when defined(rln_v2): - nonceManager: NonceManager + nonceManager*: NonceManager proc stop*(rlnPeer: WakuRLNRelay) {.async: (raises: [Exception]).} = ## stops the rln-relay protocol @@ -303,7 +303,7 @@ proc appendRLNProof*(rlnPeer: WakuRLNRelay, let epoch = calcEpoch(senderEpochTime) when defined(rln_v2): - let nonce = rlnPeer.nonceManager.get().valueOr: + let nonce = rlnPeer.nonceManager.getNonce().valueOr: return err("could not get new message id to generate an rln proof: " & $error) let proof = rlnPeer.groupManager.generateProof(input, epoch, nonce).valueOr: return err("could not generate rln-v2 proof: " & $error)