Skip to content

feat: onchain verification for C7, C5 [skip-line-limit]#1443

Merged
cedoor merged 28 commits into
mainfrom
feat/onchain-circuit-verification
Mar 20, 2026
Merged

feat: onchain verification for C7, C5 [skip-line-limit]#1443
cedoor merged 28 commits into
mainfrom
feat/onchain-circuit-verification

Conversation

@cedoor

@cedoor cedoor commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Optional toggle to enable/disable DKG proof aggregation across client, SDK, server, and runtime flows.
    • On-chain public-key verification: contracts accept and verify submitted PK proofs; optional PK verifier support added.
  • Configuration Changes

    • Increased message polynomial capacity from 80 → 100 coefficients.
    • Encryption bit-size and public-key bounds updated.
  • Improvements

    • Event payloads and APIs now carry proof-aggregation flags and encoded proof blobs; system skips aggregation cleanly when disabled.

@vercel

vercel Bot commented Mar 17, 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 20, 2026 2:15pm
enclave-docs Ready Ready Preview, Comment Mar 20, 2026 2:15pm

Request Review

@coderabbitai

coderabbitai Bot commented Mar 17, 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: 59d33f2d-e5b1-4ecb-b96d-bca907998c61

📥 Commits

Reviewing files that changed from the base of the PR and between d0e1e62 and aa03e09.

📒 Files selected for processing (2)
  • crates/aggregator/src/publickey_aggregator.rs
  • examples/CRISP/server/src/cli/commands.rs
✅ Files skipped from review due to trivial changes (1)
  • examples/CRISP/server/src/cli/commands.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/aggregator/src/publickey_aggregator.rs

📝 Walkthrough

Walkthrough

Adds an optional proof-aggregation flag across request/event/actor flows, threads it into SDK/UI/actors, wires PK-aggregation proofs into on‑chain publication and verifier interfaces, changes PK aggregation verification and centering in circuits, and increases MAX_MSG_NON_ZERO_COEFFS 80→100 with CRISP encoding updates.

Changes

Cohort / File(s) Summary
Circuit configs
circuits/lib/src/configs/default/mod.nr, circuits/lib/src/configs/insecure/threshold.nr
Bumped MAX_MSG_NON_ZERO_COEFFS 80→100; updated many CRP polynomial literals and several PK/encryption bit-size and PK bounds constants in insecure config.
PK aggregation & centering
circuits/lib/src/core/threshold/pk_aggregation.nr, crates/zk-helpers/src/circuits/threshold/pk_aggregation/computation.rs, crates/zk-helpers/src/circuits/threshold/pk_generation/utils.rs
Refactored PK aggregation verification into separate pk0/pk1 checks, applied per-modulus centering (center(moduli)), and adjusted Inputs/Bounds and deterministic CRP normalization.
Decrypted-shares circuit
crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/computation.rs, crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/*
Added public constant MAX_MSG_NON_ZERO_COEFFS = 100 and used it in config computation (replacing hardcoded 80).
BFV / user-data utils
crates/zk-helpers/src/circuits/threshold/user_data_encryption/...
Convert BFV public-key polys to CRT with from_fhe_polynomial, reverse(), then center(moduli)?; minor comments/format edits.
Proof-aggregation flag (events & meta)
crates/events/src/enclave_event/*.rs, crates/request/src/meta.rs, crates/keyshare/src/*, crates/sortition/src/*
Added proof_aggregation_enabled (serde-default true) to requests/pending/events and threaded it into E3Meta, keyshare, sortition, and related flows.
Aggregator & fold state
crates/aggregator/src/proof_fold.rs, crates/aggregator/src/publickey_aggregator.rs, crates/aggregator/src/threshold_plaintext_aggregator.rs
Track empty fold inputs (fold_input_was_empty), make node proofs optional (Option<Proof>), buffer early DKG events, remove public_key_hash, skip folding when aggregation disabled, and size plaintext outputs to MAX_MSG_NON_ZERO_COEFFS*8.
EVM helpers & publishing
crates/evm/src/helpers.rs, crates/evm/src/enclave_sol_writer.rs, crates/evm/src/ciphernode_registry_sol.rs, crates/evm-helpers/src/*
Added encode_zk_proof(proof) (validation + tests); on-chain publish paths accept/encode optional proofs; EVM bindings expose pkVerifier and proofAggregationEnabled; publish APIs updated to pass proof bytes.
Prover / multithread / actors
crates/zk-prover/src/actors/*, crates/multithread/src/multithread.rs, crates/zk-prover/src/circuits/dkg/share_computation.rs
Threaded proof_aggregation_enabled into actor metadata and gating, conditionally generate wrapper/fold proofs, added prove_with_variant for circuits, and publish DKGRecursiveAggregationComplete with optional aggregated proof when skipped.
Contracts & interfaces
packages/enclave-contracts/contracts/interfaces/*, packages/enclave-contracts/contracts/Enclave.sol, packages/enclave-contracts/contracts/registry/CiphernodeRegistryOwnable.sol
Added IPkVerifier interface and E3 fields pkVerifier/proofAggregationEnabled; publishCommittee now takes bytes proof, verifies via pkVerifier and extracts commitment from public inputs; added set/get PK verifier functions; updated decryption verifier call signature.
BFV on-chain verifiers & mocks
packages/enclave-contracts/contracts/verifiers/bfv/*, packages/enclave-contracts/contracts/test/MockPkVerifier.sol
Added BfvDecryptionVerifier and BfvPkVerifier (and MockPkVerifier); contracts decode ABI (bytes, bytes32[]), delegate to circuit verifiers, and extract plaintext/PK commitment (MESSAGE_COEFFS_COUNT = 100).
VERIFIER artifacts & HONK keys
packages/enclave-contracts/contracts/verifiers/bfv/honk/*, packages/enclave-contracts/artifacts/...
Updated embedded HONK verification keys (public-input sizes and constants); removed/added many verifier artifact JSONs and updated deployed artifact metadata.
Deployment scripts & ignition
packages/enclave-contracts/scripts/*, packages/enclave-contracts/ignition/modules/*
Added deploy modules/scripts for BFV verifiers and MockPkVerifier; changed verifier discovery to contracts/verifiers/bfv/honk/; deployEnclave accepts withZKVerification and conditionally deploys/sets verifiers.
CRISP SDK / examples
examples/CRISP/packages/crisp-sdk/*, examples/CRISP/crates/crisp-utils/*, examples/CRISP/server/*
Replaced MAX_VOTE_BITS (50) with MAX_MSG_NON_ZERO_COEFFS (100); updated encode/decode to fixed-first-100-coefficients layout; tests and server/config updated to expose proof-aggregation flag.
Templates, tests & fixtures
templates/default/*, crates/zk-prover/tests/*, packages/enclave-contracts/test/*, packages/enclave-contracts/test/fixtures/*
Propagated proofAggregationEnabled into request payloads and tests; added encodePkProof fixture; updated tests to pass ABI-encoded proofs instead of public-key hash and adjusted assertions.
SDK & clients
packages/enclave-sdk/*, packages/enclave-sdk/src/contracts/*, templates/default/client/*
Forwarded proofAggregationEnabled through ContractClient/EnclaveSDK and UI request flows; updated types to include optional flag.
Repo metadata & configs
.gitignore, .solhintignore, deployed_contracts.json, Hardhat config, examples/deploy scripts
Adjusted ignore patterns, updated many deployed / fixture JSON entries, extended Hardhat build inputs, and updated example deploy invocations to include verifier choices and proof-aggregation flags.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Enclave as Enclave (on-chain)
    participant Nodes as Ciphernodes
    participant Aggregator as PublicKeyAggregator
    participant PKVerifier as IPkVerifier (on-chain)
    participant Registry as CiphernodeRegistry

    Client->>Enclave: requestE3(..., proofAggregationEnabled)
    Enclave-->>Nodes: emit ThresholdSharePending (proof_aggregation_enabled)
    Nodes->>Aggregator: submit C5 proofs (Some<Proof> / None)
    Aggregator->>Aggregator: fold proofs (skip if disabled)
    Aggregator->>Enclave: publishCommittee(publicKey, proof?)
    Enclave->>PKVerifier: pkVerifier.verify(proof)
    PKVerifier-->>Enclave: bytes32 pkCommitment
    Enclave->>Registry: publishCommittee(..., proof)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested labels

noir

Suggested reviewers

  • ctrlc03
  • 0xjei

Poem

🐰 I hopped through proofs both big and small,
I stretched our messages to one hundred tall.
A verifier landed to guard the key,
Aggregators learned when to skip with glee.
Hooray — optional folds, and safer harmony.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/onchain-circuit-verification

@cedoor cedoor linked an issue Mar 17, 2026 that may be closed by this pull request
@cedoor cedoor force-pushed the feat/onchain-circuit-verification branch from f69fd53 to 80780e8 Compare March 17, 2026 18:59
@cedoor cedoor changed the title feat: onchain verification for C7, C5, Fold proofs feat: onchain verification for C7, C5, Fold proofs [skip-line-limit] Mar 17, 2026
@cedoor cedoor force-pushed the feat/onchain-circuit-verification branch from 14b175d to 3d252bb Compare March 18, 2026 11:05
@cedoor cedoor changed the title feat: onchain verification for C7, C5, Fold proofs [skip-line-limit] feat: onchain verification for C7, C5 [skip-line-limit] Mar 18, 2026

@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/scripts/deployEnclave.ts (1)

41-49: ⚠️ Potential issue | 🟡 Minor

Use the signer's provider to get the network name instead of hre.globalOptions.network.

hre.globalOptions.network can be undefined and defaults to "localhost" when undefined, which would cause autoCleanForLocalhost() to run incorrectly on non-local networks if called from a non-CLI context. The codebase already uses the provider-based approach in newer deployment scripts for reliability.

🔧 Suggested fix
 export const deployEnclave = async (
   withMocks?: boolean,
   withZKVerification?: boolean,
 ) => {
   const { ethers } = await hre.network.connect();
+  const [owner] = await ethers.getSigners();
 
   // Auto-clean state for local networks to prevent stale state issues
-  const networkName = hre.globalOptions.network ?? "localhost";
+  const networkName = (await owner.provider?.getNetwork())?.name ?? "localhost";
   await autoCleanForLocalhost(networkName);
-
-  const [owner] = await ethers.getSigners();
 
   const ownerAddress = await owner.getAddress();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/enclave-contracts/scripts/deployEnclave.ts` around lines 41 - 49,
The code uses hre.globalOptions.network which can be undefined; update
deployEnclave to derive the network name from the signer's provider instead:
after the existing const { ethers } = await hre.network.connect(), call await
ethers.provider.getNetwork() and use its .name (fallback to "localhost" if
empty) when passing into autoCleanForLocalhost; update any references to
networkName so autoCleanForLocalhost(networkName) uses the provider-derived name
(functions to check: deployEnclave and autoCleanForLocalhost invocation).
🧹 Nitpick comments (2)
crates/evm/src/helpers.rs (1)

326-345: Consider verifying decoded content matches input values.

The test validates structural correctness (decodes as (bytes, bytes32[])) but doesn't verify the decoded values match the original raw_proof and public_signals. Adding value assertions would catch potential encoding/ordering bugs.

💡 Optional enhancement to verify decoded values
         let tuple_type = DynSolType::Tuple(vec![
             DynSolType::Bytes,
             DynSolType::Array(Box::new(DynSolType::FixedBytes(32))),
         ]);
         // Pair encode_zk_proof's abi_encode_params with abi_decode_params (not abi_decode).
-        tuple_type.abi_decode_params(&encoded).expect(
+        let decoded = tuple_type.abi_decode_params(&encoded).expect(
             "encoded proof should decode as (bytes, bytes32[]) - matches contract abi.decode",
         );
+
+        // Verify decoded values match input
+        if let alloy_dyn_abi::DynSolValue::Tuple(parts) = decoded {
+            if let alloy_dyn_abi::DynSolValue::Bytes(decoded_proof) = &parts[0] {
+                assert_eq!(decoded_proof, &raw_proof, "raw proof should match");
+            }
+            if let alloy_dyn_abi::DynSolValue::Array(inputs) = &parts[1] {
+                assert_eq!(inputs.len(), 2, "should have 2 public inputs");
+            }
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/evm/src/helpers.rs` around lines 326 - 345, Test
test_encode_zk_proof_abi_format only checks structure; update it to decode the
params returned by encode_zk_proof and assert the decoded values equal the
original raw_proof and public_signals: call
tuple_type.abi_decode_params(&encoded), extract the first element as bytes and
compare to raw_proof, extract the second element as the bytes32 array (each
FixedBytes(32)) and compare concatenated or per-element equality to
public_signals, and add assertions so encode_zk_proof/Proof encoding errors in
ordering or content are caught.
packages/enclave-contracts/test/Enclave.spec.ts (1)

84-85: Add one explicit failing-proof test to lock verification behavior.

Given this suite now wires PK verification, add a negative-path assertion (e.g., malformed proof or wrong commitment) to ensure proof validation is actually enforced and not only happy-pathed.

Also applies to: 241-254, 297-297

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

In `@packages/enclave-contracts/test/Enclave.spec.ts` around lines 84 - 85, Add a
negative-path test that verifies PK proof validation by calling encodePkProof
and registry.publishCommittee with a malformed proof or wrong commitment and
asserting the call reverts/throws; specifically, reuse the existing setup that
computes proof via encodePkProof(ethers.keccak256(publicKey)) but alter the
proof (e.g., flip a byte or pass a random buffer) or change the commitment value
and then assert registry.publishCommittee(e3Id, nodes, publicKey, badProof) (or
with wrong commitment) fails; add this assertion alongside the existing
happy-path tests that call encodePkProof and registry.publishCommittee so the
suite enforces verification (also add similar negative tests where
publishCommittee is invoked in the other related test blocks).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/enclave-contracts/scripts/deployEnclave.ts`:
- Around line 236-278: When shouldHaveZKVerification is false we currently call
deployMocks() then silently skip setting verifiers if
mockDecryptionVerifierAddress or mockPkVerifierAddress is falsy, leaving the BFV
scheme partially configured; change deploy logic (after deployMocks() returns)
to validate that both mockDecryptionVerifierAddress and mockPkVerifierAddress
are present when shouldHaveZKVerification === false and throw or exit
immediately if either is missing so the process fails fast; update the block
surrounding deployMocks(), mockDecryptionVerifierAddress, mockPkVerifierAddress,
shouldHaveZKVerification, and before calling enclave.setDecryptionVerifier /
enclave.setPkVerifier / enclave.enableE3Program to enforce this check.

---

Outside diff comments:
In `@packages/enclave-contracts/scripts/deployEnclave.ts`:
- Around line 41-49: The code uses hre.globalOptions.network which can be
undefined; update deployEnclave to derive the network name from the signer's
provider instead: after the existing const { ethers } = await
hre.network.connect(), call await ethers.provider.getNetwork() and use its .name
(fallback to "localhost" if empty) when passing into autoCleanForLocalhost;
update any references to networkName so autoCleanForLocalhost(networkName) uses
the provider-derived name (functions to check: deployEnclave and
autoCleanForLocalhost invocation).

---

Nitpick comments:
In `@crates/evm/src/helpers.rs`:
- Around line 326-345: Test test_encode_zk_proof_abi_format only checks
structure; update it to decode the params returned by encode_zk_proof and assert
the decoded values equal the original raw_proof and public_signals: call
tuple_type.abi_decode_params(&encoded), extract the first element as bytes and
compare to raw_proof, extract the second element as the bytes32 array (each
FixedBytes(32)) and compare concatenated or per-element equality to
public_signals, and add assertions so encode_zk_proof/Proof encoding errors in
ordering or content are caught.

In `@packages/enclave-contracts/test/Enclave.spec.ts`:
- Around line 84-85: Add a negative-path test that verifies PK proof validation
by calling encodePkProof and registry.publishCommittee with a malformed proof or
wrong commitment and asserting the call reverts/throws; specifically, reuse the
existing setup that computes proof via
encodePkProof(ethers.keccak256(publicKey)) but alter the proof (e.g., flip a
byte or pass a random buffer) or change the commitment value and then assert
registry.publishCommittee(e3Id, nodes, publicKey, badProof) (or with wrong
commitment) fails; add this assertion alongside the existing happy-path tests
that call encodePkProof and registry.publishCommittee so the suite enforces
verification (also add similar negative tests where publishCommittee is invoked
in the other related test blocks).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1f5f2490-3ec4-4efa-8f82-6056569a9e8d

📥 Commits

Reviewing files that changed from the base of the PR and between b1d8418 and 0c4d7bf.

📒 Files selected for processing (14)
  • crates/evm/src/helpers.rs
  • crates/zk-prover/tests/local_e2e_tests.rs
  • examples/CRISP/enclave.config.yaml
  • examples/CRISP/packages/crisp-contracts/deployed_contracts.json
  • examples/CRISP/server/.env.example
  • examples/CRISP/server/src/config.rs
  • packages/enclave-contracts/.gitignore
  • packages/enclave-contracts/artifacts/contracts/registry/CiphernodeRegistryOwnable.sol/CiphernodeRegistryOwnable.json
  • packages/enclave-contracts/scripts/deployAndSave/bfvPkVerifier.ts
  • packages/enclave-contracts/scripts/deployAndSave/mockPkVerifier.ts
  • packages/enclave-contracts/scripts/deployAndSave/verifiers.ts
  • packages/enclave-contracts/scripts/deployEnclave.ts
  • packages/enclave-contracts/scripts/deployMocks.ts
  • packages/enclave-contracts/test/Enclave.spec.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • examples/CRISP/server/src/config.rs
  • packages/enclave-contracts/.gitignore
  • packages/enclave-contracts/scripts/deployAndSave/mockPkVerifier.ts
  • examples/CRISP/enclave.config.yaml
  • packages/enclave-contracts/scripts/deployMocks.ts
  • crates/zk-prover/tests/local_e2e_tests.rs
  • packages/enclave-contracts/scripts/deployAndSave/verifiers.ts
  • packages/enclave-contracts/scripts/deployAndSave/bfvPkVerifier.ts

Comment thread packages/enclave-contracts/scripts/deployEnclave.ts
cedoor added 3 commits March 20, 2026 13:31
- Override default Provable path that built base-circuit inputs for the wrapper
- Recursive variant runs the full base→chunk→batch→final pipeline
- Other variants return a clear ProveFailed error

Made-with: Cursor
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.

Post and verify C5/C7 proofs

2 participants