Skip to content

feat: add decryption share commitments to c6 and c7#1489

Merged
cedoor merged 2 commits into
mainfrom
refactor/c6-c7-commitments
Mar 26, 2026
Merged

feat: add decryption share commitments to c6 and c7#1489
cedoor merged 2 commits into
mainfrom
refactor/c6-c7-commitments

Conversation

@cedoor

@cedoor cedoor commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Share-decryption now exposes d_commitment outputs; aggregation validates those commitments and emits a single unified C7 proof per ciphertext index.
  • Documentation

    • Consolidated C7a/C7b into unified C7 and clarified C6/C7 public-input semantics.
  • Refactor

    • Adjusted public input/output layouts and supporting commitment helpers and constants.
  • Tests

    • Added end-to-end tests to verify commitment consistency between decryption and aggregation.
  • Chores

    • Updated verifier parameters to match the new public-input layout.

@cedoor cedoor requested review from 0xjei and ctrlc03 March 26, 2026 15:50
@cedoor cedoor linked an issue Mar 26, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Mar 26, 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: 1798a7dc-b551-4b7b-8ca9-9c1f22e57516

📥 Commits

Reviewing files that changed from the base of the PR and between 32e1a7d and 82f27df.

📒 Files selected for processing (2)
  • agent/flow-trace/04_DKG_AND_COMPUTATION.md
  • circuits/lib/src/core/threshold/share_decryption.nr
🚧 Files skipped from review as they are similar to previous changes (1)
  • agent/flow-trace/04_DKG_AND_COMPUTATION.md

📝 Walkthrough

Walkthrough

Consolidates C7 (DecryptedSharesAggregation) into a single circuit and wires per-party decryption-share commitments (d_commitment) from C6 into C7 as public inputs; updates configs, commitment helpers, circuit signatures, public-input layouts, verifier artifacts, and tests accordingly.

Changes

Cohort / File(s) Summary
Documentation
agent/flow-trace/00_INDEX.md, agent/flow-trace/04_DKG_AND_COMPUTATION.md, agent/flow-trace/05_FAILURE_REFUND_SLASHING.md
Renamed/merged C7a/C7b → C7 and updated aggregation step text to reference unified C7 and d_commitment semantics.
Circuit Configs
circuits/lib/src/configs/insecure/threshold.nr, circuits/lib/src/configs/secure/threshold.nr
Added DECRYPTED_SHARES_AGGREGATION_BIT_D constants for insecure/secure presets.
Noir Commitment Helpers
circuits/lib/src/math/commitments.nr
Added DS_THRESHOLD_DECRYPTION_SHARE domain separator and compute_threshold_decryption_share_commitment helper.
Rust Commitment Helpers
crates/zk-helpers/src/circuits/commitments.rs
Added DS constant, truncation helper, and compute_threshold_decryption_share_commitment (returns BigInt).
Core Noir Circuits
circuits/lib/src/core/threshold/decrypted_shares_aggregation.nr, circuits/lib/src/core/threshold/share_decryption.nr
Added BIT_D generic, new expected_d_commitments public input and in-circuit commit checks; ShareDecryption now truncates d, computes and returns d_commitment, and absorbs full d into transcript.
Wrapper Noir (recursive)
circuits/bin/recursive_aggregation/wrapper/threshold/decrypted_shares_aggregation/src/main.nr, circuits/bin/recursive_aggregation/wrapper/threshold/share_decryption/src/main.nr
Adjusted N_PUBLIC_INPUTS shapes: aggregation circuit public-input arity reduced; share_decryption public inputs increased by one field.
Wrapper Noir (threshold)
circuits/bin/threshold/decrypted_shares_aggregation/src/main.nr, circuits/bin/threshold/share_decryption/src/main.nr
Made expected_d_commitments a public parameter in decrypted_shares_aggregation main; added MAX_MSG_NON_ZERO_COEFFS param and pub Field return for share_decryption main.
Codegen & Output Layout
crates/zk-helpers/src/circuits/output_layout.rs, crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/codegen.rs
Added THRESHOLD_SHARE_DECRYPTION_OUTPUTS (d_commitment) and extended codegen to emit BIT_D config constant.
Inputs / Computation Plumbing
crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/computation.rs, crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/mod.rs
Added Bits.d_bit, computed expected_d_commitments for Inputs, serialized them to JSON, and updated Bits::compute to derive d_bit from BFV preset.
Events & Proof Mapping
crates/events/src/enclave_event/compute_request/zk.rs, crates/events/src/enclave_event/proof.rs
Docstring tweak for params_preset; mapped ThresholdShareDecryption to fixed output layout (d_commitment).
Prover Tests
crates/zk-prover/tests/local_e2e_tests.rs
Added end-to-end tests asserting circuit-computed d_commitment(s) match proof public signals for C6 and aggregated C7.
Verifier Artifact
packages/enclave-contracts/contracts/verifiers/bfv/honk/ThresholdDecryptedSharesAggregationVerifier.sol
Regenerated HONK verification key constants: NUMBER_OF_PUBLIC_INPUTS changed (518 → 120), VK_HASH updated, and all embedded G1 coordinates replaced to match new VK.

Sequence Diagram(s)

sequenceDiagram
  participant Prover
  participant C6 as ThresholdShareDecryption (C6)
  participant C7 as DecryptedSharesAggregation (C7)
  participant Tool as ProverTool
  participant Verifier as SmartContract/Verifier

  Prover ->> C6: run share-decryption circuit (witness)
  C6 -->> Tool: emit d_commitment (public signal)
  Tool ->> Prover: collect d_commitment(s) into public_inputs
  Prover ->> C7: submit expected_d_commitments + aggregation inputs
  C7 ->> C7: recompute commitments from witness decryption_shares and check vs expected_d_commitments
  C7 -->> Tool: produce aggregated proof + public_signals
  Tool ->> Verifier: submit proof + public_inputs (includes expected_d_commitments)
  Verifier ->> Verifier: verify using updated VK (publicInputsSize = 120)
  Verifier -->> Tool: accept/reject
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • ctrlc03
  • 0xjei
  • hmzakhalid

Poem

🐰 I hopped through circuits, trimmed each polynomial’s tail,

Bound d into signals so proofs won't fail.
C6 left a mark, C7 now checks it through,
One proof sings true where two once flew.
Carrots, commits, and a hop — code anew!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: adding decryption share commitments to circuits C6 and C7, which is the core modification across all affected files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/c6-c7-commitments

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


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.

@vercel

vercel Bot commented Mar 26, 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 26, 2026 4:26pm
enclave-docs Ready Ready Preview, Comment Mar 26, 2026 4:26pm

Request Review

Comment thread agent/flow-trace/04_DKG_AND_COMPUTATION.md

@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: 2

Caution

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

⚠️ Outside diff range comments (1)
circuits/lib/src/core/threshold/share_decryption.nr (1)

151-167: ⚠️ Potential issue | 🔴 Critical

Reassign Vec::push results to fix transcript construction.

Noir's Vec::push returns a new vector and must be reassigned. Lines 155-156 and 167 drop the returned vectors, leaving the transcript incomplete. This means gamma is derived without the commitments and d_commitment, breaking the soundness argument.

🛠️ Proposed fix
 fn payload(self, d_commitment: Field) -> Vec<Field> {
     let mut inputs = Vec::new();

     // Use commitments instead of full polynomials (saves constraints)
-    inputs.push(self.expected_sk_commitment);
-    inputs.push(self.expected_e_sm_commitment);
+    inputs = inputs.push(self.expected_sk_commitment);
+    inputs = inputs.push(self.expected_e_sm_commitment);

     // Flatten ciphertext components (public inputs)
     inputs = flatten::<_, _, BIT_CT>(inputs, self.ct0);
     inputs = flatten::<_, _, BIT_CT>(inputs, self.ct1);

     // Flatten quotient polynomials (secret witnesses)
     inputs = flatten::<_, _, BIT_R1>(inputs, self.r1);
     inputs = flatten::<_, _, BIT_R2>(inputs, self.r2);

     // Bind decryption share via prefix commitment (matches circuit 7)
-    inputs.push(d_commitment);
+    inputs = inputs.push(d_commitment);

     inputs
 }

Additionally, gamma is derived from a commitment to only the first MAX_MSG_NON_ZERO_COEFFS coefficients of d, but the full N-coefficient polynomial is later evaluated at gamma in verify_decryption_share_computation. When MAX_MSG_NON_ZERO_COEFFS < N, the remaining coefficients lack Fiat-Shamir binding. Confirm this is intentional for the constraint-saving design.

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

In `@circuits/lib/src/core/threshold/share_decryption.nr` around lines 151 - 167,
The payload construction drops the results of Noir's Vec::push (which returns a
new Vec) for the initial commitments and d_commitment, so the transcript misses
expected_sk_commitment, expected_e_sm_commitment and d_commitment; update the
payload function (symbol: payload) to reassign the pushes (e.g., inputs =
inputs.push(...)) for expected_sk_commitment, expected_e_sm_commitment and
d_commitment so those fields are actually included, and keep the existing
reassignments for flatten calls (symbols: flatten, ct0, ct1, r1, r2, BIT_CT,
BIT_R1, BIT_R2); also double-check or document the Fiat–Shamir binding gap
noted: gamma is created from only MAX_MSG_NON_ZERO_COEFFS coefficients of d
while verify_decryption_share_computation evaluates the full N-coefficient
polynomial—confirm this is intentional or extend the commitment to cover all N
coefficients.
🧹 Nitpick comments (3)
crates/events/src/enclave_event/proof.rs (1)

195-202: Add a C6 extraction regression test.

Since ThresholdShareDecryption moved from None to Fixed, add a focused test for extracting d_commitment to prevent layout regressions.

🧪 Proposed test addition
 #[cfg(test)]
 mod tests {
     use super::*;
@@
     fn extract_empty_signals() {
         let proof = make_proof(CircuitName::PkGeneration, &[]);
         assert!(proof.extract_output("pk_commitment").is_none());
     }
+
+    #[test]
+    fn extract_c6_d_commitment_after_pub_inputs() {
+        // C6: pub inputs (2 + 2*L*N fields) + 1 output (d_commitment at tail).
+        // Simulate with 2 pub fields + 1 output = 96 bytes total.
+        let mut signals = vec![0xAA; 96];
+        signals[64..96].copy_from_slice(&[0xDD; 32]);
+
+        let proof = make_proof(CircuitName::ThresholdShareDecryption, &signals);
+        assert_eq!(&*proof.extract_output("d_commitment").unwrap(), &[0xDD; 32]);
+    }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/events/src/enclave_event/proof.rs` around lines 195 - 202, Add a
targeted regression test that verifies C6 extraction for the
ThresholdShareDecryption layout now defined as CircuitOutputLayout::Fixed
(referencing CircuitName::ThresholdShareDecryption and
THRESHOLD_SHARE_DECRYPTION_OUTPUTS) and ensure the test specifically extracts
and asserts the presence and correctness of the d_commitment field; place the
test alongside other enclave_event/proof tests, call the same extraction
function used in production (the C6 extraction helper) and construct inputs that
exercise the Fixed layout so future changes to CircuitOutputLayout::Fixed or
THRESHOLD_SHARE_DECRYPTION_OUTPUTS will fail the test if d_commitment is missing
or mis-positioned.
crates/zk-helpers/src/circuits/commitments.rs (1)

83-89: Add a direct unit test for truncated C6/C7 decryption-share commitments.

This path is cross-circuit critical; a focused test will guard against drift in truncation/domain-separator behavior.

🧪 Proposed test addition
 #[cfg(test)]
 mod tests {
     use super::*;
@@
     fn compute_pk_commitment_from_keyshare_roundtrip() {
@@
         assert_eq!(commitment, expected_padded);
     }
+
+    #[test]
+    fn compute_threshold_decryption_share_commitment_truncates_coeffs() {
+        let d_share = CrtPolynomial::from_bigint_vectors(vec![
+            vec![BigInt::from(1), BigInt::from(2), BigInt::from(3)],
+            vec![BigInt::from(4), BigInt::from(5), BigInt::from(6)],
+        ]);
+        let bit_d = 8;
+        let max_k = 2;
+
+        let actual = compute_threshold_decryption_share_commitment(&d_share, bit_d, max_k);
+
+        let truncated = CrtPolynomial::from_bigint_vectors(vec![
+            vec![BigInt::from(1), BigInt::from(2)],
+            vec![BigInt::from(4), BigInt::from(5)],
+        ]);
+        let mut payload = Vec::new();
+        payload = flatten(payload, &truncated.limbs, bit_d);
+        let io_pattern = [0x80000000 | payload.len() as u32, 1];
+        let expected = field_to_bigint(
+            compute_commitments(payload, DS_THRESHOLD_DECRYPTION_SHARE, io_pattern)[0],
+        );
+
+        assert_eq!(actual, expected);
+    }
 }

Also applies to: 486-516

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

In `@crates/zk-helpers/src/circuits/commitments.rs` around lines 83 - 89, Add a
focused unit test that verifies truncated C6/C7 decryption-share commitments use
the DS_THRESHOLD_DECRYPTION_SHARE domain separator correctly: write a test that
constructs the commitment input for a decryption share, computes the commitment
using the same truncation/path logic as in the circuit code, and asserts that
the produced commitment bytes (and/or hash preimage length) match the expected
output when DS_THRESHOLD_DECRYPTION_SHARE (the 64-byte constant) is
truncated/used; locate uses of DS_THRESHOLD_DECRYPTION_SHARE in commitments.rs
and mirror the circuit truncation behavior in the test to catch regressions
(also add equivalent coverage for the other constants referenced around lines
486-516).
circuits/bin/recursive_aggregation/wrapper/threshold/decrypted_shares_aggregation/src/main.nr (1)

13-21: Avoid hard-coding the C7 signal count in another place.

N_PUBLIC_INPUTS here has to stay in lockstep with the inner C7 main signature and packages/enclave-contracts/contracts/verifiers/bfv/honk/ThresholdDecryptedSharesAggregationVerifier.sol’s NUMBER_OF_PUBLIC_INPUTS (after subtracting pairing inputs). A shared constant or consistency test would make the next public-signal change much less brittle.

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

In
`@circuits/bin/recursive_aggregation/wrapper/threshold/decrypted_shares_aggregation/src/main.nr`
around lines 13 - 21, N_PUBLIC_INPUTS is hard-coded and must stay in sync with
the C7 main signature and the Solidity verifier's NUMBER_OF_PUBLIC_INPUTS;
update the code to remove the duplicated literal by sourcing a single canonical
constant or deriving it programmatically: either import the shared public-inputs
constant used by the C7/main signature into this module (replace pub global
N_PUBLIC_INPUTS with that shared symbol) or compute N_PUBLIC_INPUTS from the
same upstream symbols (e.g., keep the T and MAX_MSG_NON_ZERO_COEFFS expressions
in sync) so the main(verification_key, proofs, public_inputs) signature always
matches the verifier's NUMBER_OF_PUBLIC_INPUTS; ensure the symbol names
referenced include N_PUBLIC_INPUTS and the main function signature and add a
note or test to verify parity with the Solidity NUMBER_OF_PUBLIC_INPUTS.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@circuits/lib/src/core/threshold/share_decryption.nr`:
- Around line 115-127: The transcript currently only absorbs the truncated
prefix of self.d via get_truncated_polynomials(), allowing the tail coefficients
to be slack; modify the code so the full d witness (self.d including all N
coefficients) is still committed/absorbed into the Fiat–Shamir transcript (keep
the full-d absorption where verify_decryption_share_computation() evaluates
self.d[basis_idx]) while separately producing and returning the truncated-prefix
Polynomial array (from get_truncated_polynomials) or its commitment for use as
C7; ensure MAX_MSG_NON_ZERO_COEFFS truncation is used only to produce the C7
prefix, not to reduce the witness bound, and apply the same change for the other
occurrence referenced around the block corresponding to lines 172–193.

In
`@crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/computation.rs`:
- Around line 328-340: The code computes expected_d_commitments from the entire
decryption_shares vector but the circuit/interpolation only uses the first
threshold + 1 shares; clamp decryption_shares and associated party IDs to the
same reconstructing subset (first threshold + 1 entries) before both the
interpolation step and before calling
compute_threshold_decryption_share_commitment so expected_d_commitments, the
interpolation logic, and the Inputs struct all use the identical [T + 1] subset.

---

Outside diff comments:
In `@circuits/lib/src/core/threshold/share_decryption.nr`:
- Around line 151-167: The payload construction drops the results of Noir's
Vec::push (which returns a new Vec) for the initial commitments and
d_commitment, so the transcript misses expected_sk_commitment,
expected_e_sm_commitment and d_commitment; update the payload function (symbol:
payload) to reassign the pushes (e.g., inputs = inputs.push(...)) for
expected_sk_commitment, expected_e_sm_commitment and d_commitment so those
fields are actually included, and keep the existing reassignments for flatten
calls (symbols: flatten, ct0, ct1, r1, r2, BIT_CT, BIT_R1, BIT_R2); also
double-check or document the Fiat–Shamir binding gap noted: gamma is created
from only MAX_MSG_NON_ZERO_COEFFS coefficients of d while
verify_decryption_share_computation evaluates the full N-coefficient
polynomial—confirm this is intentional or extend the commitment to cover all N
coefficients.

---

Nitpick comments:
In
`@circuits/bin/recursive_aggregation/wrapper/threshold/decrypted_shares_aggregation/src/main.nr`:
- Around line 13-21: N_PUBLIC_INPUTS is hard-coded and must stay in sync with
the C7 main signature and the Solidity verifier's NUMBER_OF_PUBLIC_INPUTS;
update the code to remove the duplicated literal by sourcing a single canonical
constant or deriving it programmatically: either import the shared public-inputs
constant used by the C7/main signature into this module (replace pub global
N_PUBLIC_INPUTS with that shared symbol) or compute N_PUBLIC_INPUTS from the
same upstream symbols (e.g., keep the T and MAX_MSG_NON_ZERO_COEFFS expressions
in sync) so the main(verification_key, proofs, public_inputs) signature always
matches the verifier's NUMBER_OF_PUBLIC_INPUTS; ensure the symbol names
referenced include N_PUBLIC_INPUTS and the main function signature and add a
note or test to verify parity with the Solidity NUMBER_OF_PUBLIC_INPUTS.

In `@crates/events/src/enclave_event/proof.rs`:
- Around line 195-202: Add a targeted regression test that verifies C6
extraction for the ThresholdShareDecryption layout now defined as
CircuitOutputLayout::Fixed (referencing CircuitName::ThresholdShareDecryption
and THRESHOLD_SHARE_DECRYPTION_OUTPUTS) and ensure the test specifically
extracts and asserts the presence and correctness of the d_commitment field;
place the test alongside other enclave_event/proof tests, call the same
extraction function used in production (the C6 extraction helper) and construct
inputs that exercise the Fixed layout so future changes to
CircuitOutputLayout::Fixed or THRESHOLD_SHARE_DECRYPTION_OUTPUTS will fail the
test if d_commitment is missing or mis-positioned.

In `@crates/zk-helpers/src/circuits/commitments.rs`:
- Around line 83-89: Add a focused unit test that verifies truncated C6/C7
decryption-share commitments use the DS_THRESHOLD_DECRYPTION_SHARE domain
separator correctly: write a test that constructs the commitment input for a
decryption share, computes the commitment using the same truncation/path logic
as in the circuit code, and asserts that the produced commitment bytes (and/or
hash preimage length) match the expected output when
DS_THRESHOLD_DECRYPTION_SHARE (the 64-byte constant) is truncated/used; locate
uses of DS_THRESHOLD_DECRYPTION_SHARE in commitments.rs and mirror the circuit
truncation behavior in the test to catch regressions (also add equivalent
coverage for the other constants referenced around lines 486-516).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ad38d6cc-196e-44c6-a97d-641085e0e25b

📥 Commits

Reviewing files that changed from the base of the PR and between 1f806c9 and 3375c82.

📒 Files selected for processing (21)
  • agent/flow-trace/00_INDEX.md
  • agent/flow-trace/04_DKG_AND_COMPUTATION.md
  • agent/flow-trace/05_FAILURE_REFUND_SLASHING.md
  • circuits/bin/recursive_aggregation/wrapper/threshold/decrypted_shares_aggregation/src/main.nr
  • circuits/bin/recursive_aggregation/wrapper/threshold/share_decryption/src/main.nr
  • circuits/bin/threshold/decrypted_shares_aggregation/src/main.nr
  • circuits/bin/threshold/share_decryption/src/main.nr
  • circuits/lib/src/configs/insecure/threshold.nr
  • circuits/lib/src/configs/secure/threshold.nr
  • circuits/lib/src/core/threshold/decrypted_shares_aggregation.nr
  • circuits/lib/src/core/threshold/share_decryption.nr
  • circuits/lib/src/math/commitments.nr
  • crates/events/src/enclave_event/compute_request/zk.rs
  • crates/events/src/enclave_event/proof.rs
  • crates/zk-helpers/src/circuits/commitments.rs
  • crates/zk-helpers/src/circuits/output_layout.rs
  • crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/codegen.rs
  • crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/computation.rs
  • crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/mod.rs
  • crates/zk-prover/tests/local_e2e_tests.rs
  • packages/enclave-contracts/contracts/verifiers/bfv/honk/ThresholdDecryptedSharesAggregationVerifier.sol

Comment thread circuits/lib/src/core/threshold/share_decryption.nr Outdated
0xjei
0xjei previously approved these changes Mar 26, 2026

@0xjei 0xjei 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.

utACK

@0xjei 0xjei 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.

now's good!

@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.

♻️ Duplicate comments (2)
crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/computation.rs (1)

216-246: ⚠️ Potential issue | 🟡 Minor

Clamp all emitted vectors to the same threshold + 1 subset.

Lines 257-263 only interpolate 0..=threshold, but decryption_shares, party_ids, and expected_d_commitments are still built from the full input vectors. circuits/lib/src/core/threshold/decrypted_shares_aggregation.nr expects [T + 1]-shaped arrays, so any extra reconstructing shares will make the serialized inputs disagree with the circuit arity and fail proof generation.

Also applies to: 328-341

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

In
`@crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/computation.rs`
around lines 216 - 246, The generated vectors decryption_shares, party_ids, and
expected_d_commitments must be trimmed to exactly threshold + 1 elements to
match the circuit arity; update the construction of d_share_polys ->
decryption_shares (CrtPolynomial::from_fhe_polynomial), party_ids (BigInt::from)
and expected_d_commitments to only iterate over the same 0..=threshold subset
(or take(&[..threshold+1])/slice) used by the interpolation, ensuring each
produced Vec has length threshold + 1; apply the same clamping fix to the
analogous code block referenced around the 328-341 region so all emitted arrays
match [T + 1].
circuits/lib/src/core/threshold/share_decryption.nr (1)

186-193: ⚠️ Potential issue | 🔴 Critical

Keep the full d witness bound to Fiat–Shamir.

Even after fixing the push, Lines 186-193 derive gamma from a commitment to only the first MAX_MSG_NON_ZERO_COEFFS coefficients, while verify_decryption_share_computation() still evaluates the full self.d[basis_idx]. The tail coefficients then become slack variables that can satisfy the single-point check without matching the committed prefix. Keep the truncated d_commitment as the C7 output, but absorb the full d (or a full-length commitment to it) into the C6 transcript.

Based on learnings, the sparse MAX_MSG_NON_ZERO_COEFFS handling in circuits/lib/src/core/trbfv_dec_shares_agg.nr is only intended for C7 padding/decoding.

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

In `@circuits/lib/src/core/threshold/share_decryption.nr` around lines 186 - 193,
The Fiat–Shamir challenge (gamma) is currently derived from a commitment to only
the truncated coefficients (d_truncated) which lets the tail of self.d be
unconstrained; instead, keep d_commitment (from
compute_threshold_decryption_share_commitment::<MAX_MSG_NON_ZERO_COEFFS, L,
BIT_D>) as the C7 output but include the full-length d witness (or a full-length
commitment derived from self.d) into the C6 transcript used by
generate_challenge so verify_decryption_share_computation() (which reads
self.d[basis_idx]) is bound to the same values; update the code path around
get_truncated_polynomials(), compute_threshold_decryption_share_commitment, and
generate_challenge to pass/commit the full d (or its full-length commitment)
into generate_challenge while still returning the truncated d_commitment for C7,
and preserve MAX_MSG_NON_ZERO_COEFFS usage only for C7 padding/decoding.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@circuits/lib/src/core/threshold/share_decryption.nr`:
- Around line 186-193: The Fiat–Shamir challenge (gamma) is currently derived
from a commitment to only the truncated coefficients (d_truncated) which lets
the tail of self.d be unconstrained; instead, keep d_commitment (from
compute_threshold_decryption_share_commitment::<MAX_MSG_NON_ZERO_COEFFS, L,
BIT_D>) as the C7 output but include the full-length d witness (or a full-length
commitment derived from self.d) into the C6 transcript used by
generate_challenge so verify_decryption_share_computation() (which reads
self.d[basis_idx]) is bound to the same values; update the code path around
get_truncated_polynomials(), compute_threshold_decryption_share_commitment, and
generate_challenge to pass/commit the full d (or its full-length commitment)
into generate_challenge while still returning the truncated d_commitment for C7,
and preserve MAX_MSG_NON_ZERO_COEFFS usage only for C7 padding/decoding.

In
`@crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/computation.rs`:
- Around line 216-246: The generated vectors decryption_shares, party_ids, and
expected_d_commitments must be trimmed to exactly threshold + 1 elements to
match the circuit arity; update the construction of d_share_polys ->
decryption_shares (CrtPolynomial::from_fhe_polynomial), party_ids (BigInt::from)
and expected_d_commitments to only iterate over the same 0..=threshold subset
(or take(&[..threshold+1])/slice) used by the interpolation, ensuring each
produced Vec has length threshold + 1; apply the same clamping fix to the
analogous code block referenced around the 328-341 region so all emitted arrays
match [T + 1].

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 72f01bf6-aa8f-4028-ad5e-dd4a6a0a2a30

📥 Commits

Reviewing files that changed from the base of the PR and between 3375c82 and 32e1a7d.

📒 Files selected for processing (21)
  • agent/flow-trace/00_INDEX.md
  • agent/flow-trace/04_DKG_AND_COMPUTATION.md
  • agent/flow-trace/05_FAILURE_REFUND_SLASHING.md
  • circuits/bin/recursive_aggregation/wrapper/threshold/decrypted_shares_aggregation/src/main.nr
  • circuits/bin/recursive_aggregation/wrapper/threshold/share_decryption/src/main.nr
  • circuits/bin/threshold/decrypted_shares_aggregation/src/main.nr
  • circuits/bin/threshold/share_decryption/src/main.nr
  • circuits/lib/src/configs/insecure/threshold.nr
  • circuits/lib/src/configs/secure/threshold.nr
  • circuits/lib/src/core/threshold/decrypted_shares_aggregation.nr
  • circuits/lib/src/core/threshold/share_decryption.nr
  • circuits/lib/src/math/commitments.nr
  • crates/events/src/enclave_event/compute_request/zk.rs
  • crates/events/src/enclave_event/proof.rs
  • crates/zk-helpers/src/circuits/commitments.rs
  • crates/zk-helpers/src/circuits/output_layout.rs
  • crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/codegen.rs
  • crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/computation.rs
  • crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/mod.rs
  • crates/zk-prover/tests/local_e2e_tests.rs
  • packages/enclave-contracts/contracts/verifiers/bfv/honk/ThresholdDecryptedSharesAggregationVerifier.sol
✅ Files skipped from review due to trivial changes (4)
  • agent/flow-trace/05_FAILURE_REFUND_SLASHING.md
  • crates/events/src/enclave_event/compute_request/zk.rs
  • circuits/lib/src/configs/secure/threshold.nr
  • agent/flow-trace/04_DKG_AND_COMPUTATION.md
🚧 Files skipped from review as they are similar to previous changes (10)
  • agent/flow-trace/00_INDEX.md
  • crates/events/src/enclave_event/proof.rs
  • circuits/lib/src/configs/insecure/threshold.nr
  • crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/codegen.rs
  • crates/zk-helpers/src/circuits/threshold/decrypted_shares_aggregation/mod.rs
  • crates/zk-helpers/src/circuits/output_layout.rs
  • circuits/bin/threshold/share_decryption/src/main.nr
  • circuits/bin/recursive_aggregation/wrapper/threshold/share_decryption/src/main.nr
  • circuits/lib/src/math/commitments.nr
  • crates/zk-prover/tests/local_e2e_tests.rs

@cedoor cedoor merged commit 4941c4d into main Mar 26, 2026
33 checks passed
@ctrlc03 ctrlc03 deleted the refactor/c6-c7-commitments branch March 27, 2026 10:51
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.

Add decryption-share commitments to C6 and C7

2 participants