Skip to content

fix: refact rln-relay and post sync test#3434

Merged
darshankabariya merged 39 commits intomasterfrom
refact_groupmanager
Sep 10, 2025
Merged

fix: refact rln-relay and post sync test#3434
darshankabariya merged 39 commits intomasterfrom
refact_groupmanager

Conversation

@darshankabariya
Copy link
Copy Markdown
Contributor

@darshankabariya darshankabariya commented Jun 2, 2025

Description

This refactor was necessary because we’ve already transitioned to a non-synchronous approach, and all sync-related code is being deprecated.

Over time, GroupManager became bloated with tightly coupled and complex logic. This PR initiates a refactor to improve the clarity, maintainability, and future extensibility of the RLN relay protocol.

Changes

  • Restructured the GroupManager hierarchy and introduced offchainGroupManager to replace staticGroupManager.
  • Deprecated the static manager class in favor of the offchainManager interface. (As suggested by @jm-clius, both on-chain and off-chain trees may exist in the future; currently, OffchainManager is just an interface.)
  • Removed all zerokit ffi for the merkle tree along with its associated proof generation and verification wrappers.
  • Deleted all unit tests related to the old merkle tree implementation.
  • Update all effected with onchain anvail

Issue

@github-actions
Copy link
Copy Markdown

github-actions bot commented Jun 2, 2025

You can find the image built from this PR at

quay.io/wakuorg/nwaku-pr:3434

Built from c1dc003

@darshankabariya darshankabariya force-pushed the refact_groupmanager branch 2 times, most recently from c5860b8 to cc3cb7e Compare June 3, 2025 08:13
@darshankabariya darshankabariya changed the title chore: refactor groupmanager chore: refactor groupManager Jun 3, 2025
@darshankabariya darshankabariya requested a review from SionoiS June 3, 2025 13:08
@Ivansete-status
Copy link
Copy Markdown
Collaborator

Thanks so much for it @darshankabariya !
Always keen on simplify things.
Ping me when the tests are not disabled. If a test needs to be disabled, let's reason it.
Thanks again!

@darshankabariya darshankabariya marked this pull request as draft June 16, 2025 06:17
@darshankabariya darshankabariya changed the title chore: refactor groupManager chore: remove off-chain tree Jul 25, 2025
@darshankabariya
Copy link
Copy Markdown
Contributor Author

darshankabariya commented Aug 6, 2025

Hi @Ivansete-status, @jm-clius, @stubbsta
The PR is now ready for review.
A few test cases are taking longer than expected — I’m still looking into that.
However, all the core logic changes for improving the RLN relay protocol are complete.

cc @NagyZoltanPeter

@darshankabariya darshankabariya requested review from stubbsta and removed request for gabrielmer August 6, 2025 09:11
@darshankabariya darshankabariya marked this pull request as ready for review August 6, 2025 09:11
Copy link
Copy Markdown
Contributor

@jm-clius jm-clius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I've just eyeballed the changes for now - I think this is a good step towards simplification. So far one-ish question below.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might just be missing it, but why do we need an OffchainGroupManager at all? We now have the base interface, which we can implement again when we re-add a real offchain implementation?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you got it right. Actually, I couldn’t find any use for the StaticGroupManager class, so I deprecated it along with its unit tests. As you noticed, I introduced the OffchainGroupManager interface—this idea came from your suggestion that we might support both offchain and onchain features in the future. I’ve left it unimplemented for now.

@@ -0,0 +1,3 @@
import off_chain/group_manager
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have a barrel import for off_chain, but not for on_chain?

(Barrel imports are somewhat controversial, but for now that's beside the point :D )

Copy link
Copy Markdown
Contributor Author

@darshankabariya darshankabariya Aug 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There’s another file in the same directory, waku/waku_rln_relay/group_manager/on_chain.nim, similar to the offchain one. It looks a bit oversimplified — I’ll take a closer look.

cc @Ivansete-status @jm-clius

Copy link
Copy Markdown
Collaborator

@Ivansete-status Ivansete-status left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for it! 🙌
Some comments.
For every snippet code that you remove, kindly add a clear explanation as to why we can remove it, for future reference.
Thanks!


suite "Lightpush attaching RLN proofs":
asyncTest "Message is published when RLN enabled":
xasyncTest "Message is published when RLN enabled":
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why that is commented if may I ask?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unable testcase !!


suite "proofGen":
test "Valid zk proof":
xasyncTest "Valid zk proof":
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for that one. Why skipped?

credentials.add(generateCredentials(rlnInstance))
return credentials

suite "Offchain group manager":
Copy link
Copy Markdown
Collaborator

@Ivansete-status Ivansete-status Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this test suite running any test ?
It seems this whole module can be removed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree — we no longer need the off-chain testcase since there’s nothing left to test. but also there no harm at all, that why not delete.

return err("proof verification failed: " & $proofVerifyRes.error())
return ok(proofVerifyRes.value())
## Dummy implementation for verifyProof
return ok(true)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not the following?

Suggested change
return ok(true)
return err("veryfyProof is not implemented")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea !!

Comment on lines +10 to +11
template initializedGuard*(g: OffchainGroupManager): untyped =
discard
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is everything discarded?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing out, I’ve updated all functions to return an unimplemented error.

@darshankabariya darshankabariya changed the title chore: remove off-chain tree chore: refact rln-relay and post sync test Aug 26, 2025
@darshankabariya darshankabariya changed the title chore: refact rln-relay and post sync test fix: refact rln-relay and post sync test Aug 26, 2025
Copy link
Copy Markdown
Collaborator

@Ivansete-status Ivansete-status left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more comments, thanks ! 🙌

Comment on lines +573 to +574
raise
newException(CatchableError, "Failed to deploy test token contract: " & $error)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it strictly needed the change? I would avoid explicitly raising exceptions, if possible

Copy link
Copy Markdown
Contributor Author

@darshankabariya darshankabariya Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated it with the idea of unification. I noticed we mostly use exceptions in our code, so I replaced asserts with exceptions. But now i realize that is for is for binary not test. so assertion is better idea right ??

let contractAddress = (await executeForgeContractDeployScripts(privateKey, acc, web3)).valueOr:
assert false, "Failed to deploy RLN contract: " & $error
return
raise newException(CatchableError, "Failed to deploy RLN contract: " & $error)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar to above

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same !!


anvilProc = runAnvil()
tempManager =
cast[ptr OnchainGroupManager](allocShared0(sizeof(OnchainGroupManager)))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the manual allocation is needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I need this onchainGroupManager to fetch real-time RLN metadata such as contractAddress and useMessageLimit. If we hardcode these values, then every time the default RLN metadata changes, we’ll also need to update the tests. but yes definatly it's finest way to fetch we also usg RlnConf default value but i feel over code.

let proof = rlnPeer.groupManager.generateProof(input, epoch, 0).valueOr:
# Fetch Merkle proof either when a new root was detected *or* when the cache is empty.
if rootUpdated or manager.merkleProofCache.len == 0:
let proofResult = waitFor manager.fetchMerkleProofElements()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though this is for testing purposes only, the waitFor should be used with care and only in the top logic layers. Better await

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it !!

Comment on lines +39 to +40
): WakuRlnConfig =
let wakuRlnConfig = WakuRlnConfig(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
): WakuRlnConfig =
let wakuRlnConfig = WakuRlnConfig(
): WakuRlnConfig =
## For testing purposes only
let wakuRlnConfig = WakuRlnConfig(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s already in the test file, so why do we need to mention it explicitly ?


suite "RLN Relay v2: serde":
test "toLeaf: converts a rateCommitment to a valid leaf":
xasyncTest "toLeaf: converts a rateCommitment to a valid leaf":
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
xasyncTest "toLeaf: converts a rateCommitment to a valid leaf":
asyncTest "toLeaf: converts a rateCommitment to a valid leaf":

Copy link
Copy Markdown
Contributor Author

@darshankabariya darshankabariya Aug 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same !! as below

check expectedLeaf == leafRes.value.inHex()

test "proofGen: generates a valid zk proof":
xasyncTest "proofGen: generates a valid zk proof":
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
xasyncTest "proofGen: generates a valid zk proof":
asyncTest "proofGen: generates a valid zk proof":

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[tests/waku_rln_relay/test_rln_serde.nim] is no longer needed. It was testing proof generation in isolation, but after moving to the on-chain tree, proof generation requires running a node and registering membership. Since it’s no longer possible to generate proofs fully off-chain, this test case is obsolete. deleting whole file.

if rootUpdated:
if g.membershipIndex.isNone():
error "membershipIndex is not set; skipping proof update"
debug "membershipIndex is not set; skipping proof update"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not this be considered as an error?

Copy link
Copy Markdown
Contributor Author

@darshankabariya darshankabariya Aug 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s no longer required because earlier registering RLN membership was mandatory, but now users can run the code without membership. so removed it. thanks for pointing out, it;s help me think new direction.

Comment on lines +144 to +152
proc getCurrentEpoch*(rlnPeer: WakuRLNRelay, t: float64 = -1.0): Epoch =
## Returns the RLN epoch corresponding to `t` (Unix seconds).
## If `t` is not supplied (or set to a negative value), the current time is used.
let timeToUse =
if t < 0.0:
epochTime()
else:
t
return rlnPeer.calcEpoch(timeToUse)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified, considering that t is never being passed:

Suggested change
proc getCurrentEpoch*(rlnPeer: WakuRLNRelay, t: float64 = -1.0): Epoch =
## Returns the RLN epoch corresponding to `t` (Unix seconds).
## If `t` is not supplied (or set to a negative value), the current time is used.
let timeToUse =
if t < 0.0:
epochTime()
else:
t
return rlnPeer.calcEpoch(timeToUse)
proc getCurrentEpoch*(rlnPeer: WakuRLNRelay): Epoch =
## Returns the RLN epoch corresponding to current epochTimeme is used.
return rlnPeer.calcEpoch(epochTime())

Copy link
Copy Markdown
Contributor Author

@darshankabariya darshankabariya Aug 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing that out. I had made the change for a specific test, but later realized that passing just one test isn’t a good reason to change the structure of this function. I forgot to revert it. finally remove that

@darshankabariya
Copy link
Copy Markdown
Contributor Author

LGTM! I'd make sure we remove all the tests that are not needed and keep the needed ones. F.e., it seems we should not skip the following in `tests/waku_rln_relay/rln/test_wrappers.nim
And also, CI green :D

Hi @Ivansete-status , thank you for the approval. I’ve addressed all your suggestions and updated the changes accordingly. All CI checks are green now and tests have been updated as well. If you see this before merging the PR, kindly have a look.

Copy link
Copy Markdown
Contributor

@stubbsta stubbsta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Copy link
Copy Markdown
Contributor

@jm-clius jm-clius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I'm ready to approve once I understand why the OffchainGroupManager exists at all. :) Will be happy to have a call if I'm missing some context or my comments are unclear.

Comment on lines +5 to +6
# Placeholder for future OffchainGroupManager re-implementation
type OffchainGroupManager* = ref object of GroupManager
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I don't understand why we have this non-implementation as placeholder. There is no real implementation and this is only referenced in tests (and in rln_relay.nim, where it probably shouldn't be included anymore, see my comment there). In other words, wherever you still use OffchainGroupManager in the tests it could just be GroupManager and we delete the files and folders for off_chain for now. Am I missing some important context?

Copy link
Copy Markdown
Contributor Author

@darshankabariya darshankabariya Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for review. main objective for offchainGM is to serve as a future perspective, so that when we revisit the offchain tree, we can leverage the currently unimplemented offchainGM functionality. But I understand your point — we can remove offchainGM for now as well, should i remove or not ??

@@ -447,11 +413,11 @@ proc mount(

if not conf.dynamic:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't support non-dynamic group managers anymore, from what I can see. There's no "OffchainGroupManager" - just a stub with that name that will raise exceptions for every function call. In other words, we can remove this completely and mark the config item as deprecated.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!! we also need to remove that along with offchainGM.

Copy link
Copy Markdown
Contributor

@jm-clius jm-clius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Two comments below, but no need to re-request review once addressed.

let rlnInstance = createRLNInstance(tree_path = conf.treePath).valueOr:
return err("could not create RLN instance: " & $error)

if not conf.dynamic:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this config item must be marked in the external config as deprecated (and then removed within two releases). Presumably it will not break any existing deployments and the default is true in any case?

Copy link
Copy Markdown
Contributor Author

@darshankabariya darshankabariya Sep 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it’s a really good idea. I found that the default value true for dynamic is set only inside NetworkMonitor. we will handle in seperate PR.

let credentials = toSeq(0 .. 1000).mapIt(membershipKeyGen(rlnIns).get())

let manager = StaticGroupManager(
let manager = OffchainGroupManager(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this reference does not exist anymore. Perhaps instantiate the base GroupManager?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update the benchmark accordingly.

@darshankabariya darshankabariya merged commit 7538912 into master Sep 10, 2025
10 of 12 checks passed
@darshankabariya darshankabariya deleted the refact_groupmanager branch September 10, 2025 10:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants