Skip to content

refactor: use lazy IMT for ciphernode registry#1387

Merged
hmzakhalid merged 4 commits into
mainfrom
refactor/leanimt-ciphernodes
Mar 5, 2026
Merged

refactor: use lazy IMT for ciphernode registry#1387
hmzakhalid merged 4 commits into
mainfrom
refactor/leanimt-ciphernodes

Conversation

@cedoor

@cedoor cedoor commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

Closes #1385

Summary by CodeRabbit

  • New Features

    • Deregistration simplified to a single CLI command (no proof or sibling input required).
  • Documentation

    • Exit guide updated to remove proof-generation and sibling-proof saving steps.
  • Bug Fixes

    • Improved deregistration reliability by removing manual sibling/proof handling.
  • Refactor

    • Registry membership redesigned with a lazy tree implementation; adds per-node enabled state and explicit indexing, and updates emitted index/size info.

@cedoor cedoor requested review from ctrlc03 and hmzakhalid March 5, 2026 13:34
@vercel

vercel Bot commented Mar 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
crisp Ready Ready Preview, Comment Mar 5, 2026 8:03pm
enclave-docs Ready Ready Preview, Comment Mar 5, 2026 8:03pm

Request Review

@coderabbitai

coderabbitai Bot commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c7f811fb-cc02-4db3-884c-f5d52801a077

📥 Commits

Reviewing files that changed from the base of the PR and between dfcdd9f and 830b5e0.

📒 Files selected for processing (4)
  • packages/enclave-contracts/artifacts/contracts/interfaces/IBondingRegistry.sol/IBondingRegistry.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/ISlashingManager.sol/ISlashingManager.json

📝 Walkthrough

Walkthrough

Deregistration flow was simplified: sibling/IMT proof handling removed across CLI, tasks, contracts, tests, and docs; registry migrated from LeanIMT to LazyIMT with per-node index and enabled tracking; contract and ABI signatures for deregister/remove were updated to be parameterless.

Changes

Cohort / File(s) Summary
CLI changes
crates/cli/src/ciphernode/lifecycle.rs, crates/cli/src/ciphernode/mod.rs, crates/cli/src/ciphernode/utils.rs
Removed sibling parsing helpers and siblings parameter from deregister(); CLI deregister no longer accepts or constructs IMT proofs.
Hardhat tasks & config
packages/enclave-contracts/tasks/ciphernode.ts, packages/enclave-contracts/hardhat.config.ts
Deleted ciphernode:siblings task and removed siblings option from remove task; tasks now call deregisterOperator() without arguments and config stops exporting sibling task.
Contract interfaces & ABIs
packages/enclave-contracts/contracts/interfaces/IBondingRegistry.sol, packages/enclave-contracts/contracts/interfaces/ICiphernodeRegistry.sol, packages/enclave-contracts/artifacts/.../IBondingRegistry.json, .../ICiphernodeRegistry.json
Changed deregisterOperator and removeCiphernode signatures to be parameterless (removed uint256[] siblingNodes), and updated corresponding ABI artifacts.
Registry implementation
packages/enclave-contracts/contracts/registry/BondingRegistry.sol, packages/enclave-contracts/contracts/registry/CiphernodeRegistryOwnable.sol
Migrated from LeanIMT→LazyIMT, added TREE_DEPTH, ciphernodeEnabled, ciphernodeTreeIndex; removed sibling-based removal and now remove by stored index; adjusted events/accessors to new semantics.
Tasks, deps & package manifest
packages/enclave-contracts/package.json
Removed ciphernode:siblings npm script; replaced LeanIMT deps with @zk-kit/lazy-imt.sol@2.0.0-beta.12.
Mocks & tests
packages/enclave-contracts/contracts/test/MockCiphernodeRegistry.sol, packages/enclave-contracts/test/*.spec.ts
Updated mock signatures to remove sibling param; removed LeanIMT usage from tests; updated calls and assertions to use no-arg deregister/remove and new registry indices/state.
Docs
docs/pages/ciphernode-operators/exits-and-slashing.mdx
Removed proof-related deregistration steps and CLI proof example; docs now show a plain deregister command.
Artifacts / build metadata
packages/enclave-contracts/artifacts/.../IEnclave.json, .../ISlashingManager.json
Updated buildInfoId values reflecting recompilation; no functional changes to interfaces other than those noted.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant BondingRegistry
    participant CiphernodeRegistry
    participant LazyIMT

    User->>CLI: run "enclave ciphernode deregister"
    CLI->>BondingRegistry: call deregisterOperator()
    BondingRegistry->>CiphernodeRegistry: removeCiphernode(msg.sender)
    CiphernodeRegistry->>CiphernodeRegistry: lookup ciphernodeTreeIndex[msg.sender]
    CiphernodeRegistry->>LazyIMT: removeLeafAt(index)
    LazyIMT-->>CiphernodeRegistry: updated root/size
    CiphernodeRegistry-->>BondingRegistry: emit CiphernodeRemoved(index, newSize)
    BondingRegistry-->>CLI: tx confirmed / event
    CLI-->>User: report success
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • hmzakhalid
  • ctrlc03
  • ryardley

Poem

🐰 I hopped through code with nimble feet,
No siblings now — the flow’s so neat.
LazyIMT hums, indices in view,
Deregister simple, tidy, and true.
🍃

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor: use lazy IMT for ciphernode registry' accurately describes the main change: replacing LeanIMT with LazyIMT in the ciphernode registry.
Linked Issues check ✅ Passed The pull request successfully implements the objective from issue #1385: it replaces LeanIMT with LazyIMT throughout the ciphernode registry, eliminating the requirement for callers to provide sibling nodes during ciphernode removal.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the objective of replacing LeanIMT with LazyIMT; there are no unrelated modifications outside the scope of this refactoring.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/leanimt-ciphernodes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/enclave-contracts/contracts/registry/CiphernodeRegistryOwnable.sol (1)

310-319: ⚠️ Potential issue | 🟠 Major

Reject zero-address inserts in addCiphernode.

Line 310 currently allows address(0). Since Line 333 uses 0 as the removal tombstone (_update(0, index)), allowing zero-address insertion can create ambiguous membership/accounting behavior.

🛠️ Suggested fix
 function addCiphernode(address node) external onlyOwnerOrBondingVault {
+        require(node != address(0), ZeroAddress());
         if (isEnabled(node)) {
             return;
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/enclave-contracts/contracts/registry/CiphernodeRegistryOwnable.sol`
around lines 310 - 319, The addCiphernode function must reject the zero address
to avoid ambiguity with the tombstone value; add a require that node !=
address(0) (with a clear revert message) at the start of addCiphernode (before
isEnabled and before using ciphernodes._insert) so you never insert uint160(0)
into the tree or set ciphernodeEnabled/ciphernodeTreeIndex/numCiphernodes for
address(0); this change pertains to function addCiphernode and the uses of
ciphernodes._insert, ciphernodeEnabled, ciphernodeTreeIndex, and numCiphernodes.
🧹 Nitpick comments (1)
packages/enclave-contracts/test/Registry/CiphernodeRegistryOwnable.spec.ts (1)

569-603: Consider adding a zero-address regression test in this block.

Given the new tombstone-based removal semantics, add a test that addCiphernode(0x000...000) reverts with ZeroAddress to lock in boundary behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/enclave-contracts/test/Registry/CiphernodeRegistryOwnable.spec.ts`
around lines 569 - 603, Add a new test in the "removeCiphernode()" describe
block that asserts addCiphernode called with the zero address reverts with the
custom error ZeroAddress: use the existing setup fixture (e.g., const { registry
} = await loadFixture(setup)), then call
registry.addCiphernode(ethers.constants.AddressZero) (or
registry.addCiphernode("0x000...0")) and expect it
.to.be.revertedWithCustomError(registry, "ZeroAddress"); place this alongside
the other it() tests to lock in the zero-address regression for addCiphernode.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/pages/ciphernode-operators/exits-and-slashing.mdx`:
- Around line 95-101: The summary tables still reference the old proof-based
deregistration; update all table entries that mention "proof-based
deregistration" or show the old command to instead reflect the new no-proof flow
by replacing the proof-based command with the new CLI invocation `enclave
ciphernode deregister` and adjusting any descriptive text to remove
proof-related steps; search for the "Step 1: Deregister" heading and any summary
table rows under it (and the nearby table blocks that previously referenced
proof-based deregistration) and change their command/examples and explanatory
text to the no-proof flow consistently.

---

Outside diff comments:
In `@packages/enclave-contracts/contracts/registry/CiphernodeRegistryOwnable.sol`:
- Around line 310-319: The addCiphernode function must reject the zero address
to avoid ambiguity with the tombstone value; add a require that node !=
address(0) (with a clear revert message) at the start of addCiphernode (before
isEnabled and before using ciphernodes._insert) so you never insert uint160(0)
into the tree or set ciphernodeEnabled/ciphernodeTreeIndex/numCiphernodes for
address(0); this change pertains to function addCiphernode and the uses of
ciphernodes._insert, ciphernodeEnabled, ciphernodeTreeIndex, and numCiphernodes.

---

Nitpick comments:
In `@packages/enclave-contracts/test/Registry/CiphernodeRegistryOwnable.spec.ts`:
- Around line 569-603: Add a new test in the "removeCiphernode()" describe block
that asserts addCiphernode called with the zero address reverts with the custom
error ZeroAddress: use the existing setup fixture (e.g., const { registry } =
await loadFixture(setup)), then call
registry.addCiphernode(ethers.constants.AddressZero) (or
registry.addCiphernode("0x000...0")) and expect it
.to.be.revertedWithCustomError(registry, "ZeroAddress"); place this alongside
the other it() tests to lock in the zero-address regression for addCiphernode.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b93c4759-e13b-4492-ae36-6e963585659c

📥 Commits

Reviewing files that changed from the base of the PR and between c7167ec and dfcdd9f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (15)
  • crates/cli/src/ciphernode/lifecycle.rs
  • crates/cli/src/ciphernode/mod.rs
  • crates/cli/src/ciphernode/utils.rs
  • docs/pages/ciphernode-operators/exits-and-slashing.mdx
  • packages/enclave-contracts/contracts/interfaces/IBondingRegistry.sol
  • packages/enclave-contracts/contracts/interfaces/ICiphernodeRegistry.sol
  • packages/enclave-contracts/contracts/registry/BondingRegistry.sol
  • packages/enclave-contracts/contracts/registry/CiphernodeRegistryOwnable.sol
  • packages/enclave-contracts/contracts/test/MockCiphernodeRegistry.sol
  • packages/enclave-contracts/hardhat.config.ts
  • packages/enclave-contracts/package.json
  • packages/enclave-contracts/tasks/ciphernode.ts
  • packages/enclave-contracts/test/Enclave.spec.ts
  • packages/enclave-contracts/test/Registry/BondingRegistry.spec.ts
  • packages/enclave-contracts/test/Registry/CiphernodeRegistryOwnable.spec.ts
💤 Files with no reviewable changes (3)
  • crates/cli/src/ciphernode/utils.rs
  • packages/enclave-contracts/hardhat.config.ts
  • packages/enclave-contracts/test/Enclave.spec.ts

Comment thread docs/pages/ciphernode-operators/exits-and-slashing.mdx
@vercel vercel Bot temporarily deployed to Preview – enclave-docs March 5, 2026 14:14 Inactive
@vercel vercel Bot temporarily deployed to Preview – crisp March 5, 2026 14:14 Inactive
@cedoor cedoor enabled auto-merge (squash) March 5, 2026 14:41
@hmzakhalid hmzakhalid enabled auto-merge (squash) March 5, 2026 20:11
@hmzakhalid hmzakhalid merged commit 70405fa into main Mar 5, 2026
26 checks passed
@github-actions github-actions Bot deleted the refactor/leanimt-ciphernodes branch March 13, 2026 03:11
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.

Use LazyIMT in the registry contract for ciphernodes

3 participants