Skip to content

feat: add share-encryption circuit gen [skip-line-limit]#1267

Merged
cedoor merged 5 commits into
mainfrom
port/dkg-c3
Feb 5, 2026
Merged

feat: add share-encryption circuit gen [skip-line-limit]#1267
cedoor merged 5 commits into
mainfrom
port/dkg-c3

Conversation

@0xjei

@0xjei 0xjei commented Feb 5, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added a DKG share-encryption circuit with end-to-end CLI support for sample generation, validation, and artifact output.
  • Chores

    • Consolidated share-encryption configuration into a single public config and adjusted numeric parameters (bit-widths and bounds) used by the circuit.
  • Tests

    • Tests updated to use a specific BFV preset for more deterministic codegen and validation.

@0xjei 0xjei added this to the PHASE 2: PROVE & VERIFY milestone Feb 5, 2026
@0xjei 0xjei self-assigned this Feb 5, 2026
@vercel

vercel Bot commented Feb 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 Feb 5, 2026 5:00pm
enclave-docs Ready Ready Preview, Comment Feb 5, 2026 5:00pm

Request Review

@coderabbitai

coderabbitai Bot commented Feb 5, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds a new share-encryption DKG circuit (circuit, computation, codegen, sample), integrates it into the CLI, unifies/renames SHARE_ENCRYPTION config symbols and adds many bound constants, updates share-encryption bit-widths, and adds compute_msg_bit utility.

Changes

Cohort / File(s) Summary
Config updates
circuits/lib/src/configs/insecure/dkg.nr, circuits/lib/src/configs/secure/dkg.nr
Unified share-encryption configs into SHARE_ENCRYPTION_CONFIGS, removed per-config SHARE_ENCRYPTION_CONFIGS_SK/_E_SM, added numerous bound constants (*_BOUNDS, *_BOUND, etc.), and adjusted SHARE_ENCRYPTION_BIT_* values.
New circuit public surface
crates/zk-helpers/src/circuits/dkg/mod.rs, crates/zk-helpers/src/circuits/dkg/share_encryption/mod.rs, crates/zk-helpers/src/circuits/dkg/share_encryption/circuit.rs
Exports new share_encryption module and adds ShareEncryptionCircuit and ShareEncryptionCircuitInput types.
Computation & witness
crates/zk-helpers/src/circuits/dkg/share_encryption/computation.rs
Adds large computation layer: Configs, Bits, Bounds, Witness, ShareEncryptionOutput; computes bounds, CRT limbs, polynomials, commitments; implements CircuitComputation and JSON serialization.
Codegen & artifacts
crates/zk-helpers/src/circuits/dkg/share_encryption/codegen.rs
Implements CircuitCodegen for share-encryption; adds generate_toml and generate_configs, emits Prover.toml and Noir configs.nr, and includes tests verifying outputs.
Sample generation & tests
crates/zk-helpers/src/circuits/dkg/share_encryption/sample.rs
Adds ShareEncryptionSample generator and prepare_*_for_test, creates DKG keys, plaintext/ciphertext, and RNS components; includes tests.
Module wiring & re-exports
crates/zk-helpers/src/circuits/dkg/share_encryption/mod.rs
Registers public submodules and re-exports types from circuit, codegen, computation, and sample.
CLI integration
crates/zk-helpers/src/bin/zk_cli.rs
Registers ShareEncryptionCircuit in CLI registry and adds codegen dispatch that builds the circuit input from a generated sample.
Utilities
crates/zk-helpers/src/utils.rs
Adds compute_msg_bit(params: &BfvParameters) -> u32 to compute message bit width.
Preset selection in tests
crates/zk-helpers/src/.../* (multiple test files)
Replaces DEFAULT_BFV_PRESET with explicit BfvPreset::InsecureThreshold512 across tests and test codegen paths.
CLI Noir programs
circuits/bin/dkg/e_sm_share_encryption/src/main.nr, circuits/bin/dkg/sk_share_encryption/src/main.nr
Replaced references to per-config constants with unified SHARE_ENCRYPTION_CONFIGS in ShareEncryption constructor calls.

Sequence Diagram

sequenceDiagram
    participant CLI as CLI Handler
    participant Sample as Sample Generator
    participant Compute as Circuit Computation
    participant Codegen as Code Generator
    participant Artifacts as Output Artifacts

    CLI->>Sample: generate(preset, committee, dkg_input_type)
    Sample->>Sample: create DKG keys, plaintext, ciphertext, RNS
    Sample-->>CLI: ShareEncryptionSample

    CLI->>Compute: compute(preset, ShareEncryptionSample)
    Compute->>Compute: derive Bounds & Bits
    Compute->>Compute: build Witness (CRT limbs, polynomials, commitments)
    Compute-->>CLI: ShareEncryptionOutput

    CLI->>Codegen: codegen(preset, ShareEncryptionCircuitInput)
    Codegen->>Codegen: generate_toml(witness)
    Codegen->>Codegen: generate_configs(preset, configs)
    Codegen-->>Artifacts: Prover.toml + configs.nr
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested reviewers

  • cedoor
  • hmzakhalid
  • ryardley

Poem

🐰 I hop through bits and bounds by night,

encrypting shares till morning light.
Samples, witnesses, configs in tune—
Prover.toml hums, configs.nr croons.
A little carrot for tests — the circuit's just right!

🚥 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 title clearly and specifically describes the main change: adding a share-encryption circuit code generation capability to the project.
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 docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch port/dkg-c3

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: 4

🤖 Fix all issues with AI agents
In `@crates/zk-helpers/src/circuits/dkg/share_encryption/circuit.rs`:
- Around line 22-28: The circuit declares the wrong parameter type: in the impl
for ShareEncryptionCircuit the const SUPPORTED_PARAMETER is set to
ParameterType::THRESHOLD but the Noir configs for this circuit use DKG-specific
parameters; update the constant SUPPORTED_PARAMETER in the
ShareEncryptionCircuit impl to ParameterType::DKG so the circuit metadata
matches the actual L/QIS parameter set used by the DKG configs.

In `@crates/zk-helpers/src/circuits/dkg/share_encryption/codegen.rs`:
- Around line 249-267: The test_toml_generation_and_structure creates a sample
with BfvPreset::InsecureThreshold512 via
prepare_share_encryption_sample_for_test but then calls
ShareEncryptionCircuit.codegen using DEFAULT_BFV_PRESET causing a preset
mismatch; fix by calling codegen with the same preset used to create the sample
(pass BfvPreset::InsecureThreshold512 or obtain the preset from the sample) so
ShareEncryptionCircuit::codegen receives matching BFV parameters instead of
DEFAULT_BFV_PRESET.

In `@crates/zk-helpers/src/circuits/dkg/share_encryption/computation.rs`:
- Around line 940-956: The test test_bound_and_bits_computation_consistency
mixes presets: it creates the sample with BfvPreset::InsecureThreshold512 but
calls Bounds::compute and Bits::compute with DEFAULT_BFV_PRESET; update the test
so the same preset is used for sample creation and subsequent
computations/assertions (e.g., introduce a local let preset =
BfvPreset::InsecureThreshold512 and pass preset to
prepare_share_encryption_sample_for_test, Bounds::compute and Bits::compute, and
use that preset for any related expectations) to ensure consistent preset usage
across prepare_share_encryption_sample_for_test, Bounds::compute, Bits::compute
and the assertions.

In `@crates/zk-helpers/src/circuits/dkg/share_encryption/sample.rs`:
- Around line 135-161: The test uses BfvPreset::InsecureThreshold512 to build
the sample but asserts lengths against DEFAULT_BFV_PRESET.metadata().degree,
which can mismatch; update the assertions to use the same preset used to build
the sample by capturing the preset (or its metadata()) used in
prepare_share_encryption_sample_for_test and replace
DEFAULT_BFV_PRESET.metadata().degree with that preset.metadata().degree (or
compute expected_degree from BfvPreset::InsecureThreshold512 directly) so
assert_eq! checks reference the exact same preset; locate uses in
test_generate_secret_key_sample and adjust all four degree-based assertions
accordingly.
🧹 Nitpick comments (7)
crates/zk-helpers/src/circuits/dkg/share_encryption/sample.rs (1)

36-109: Minor: Variable naming inconsistency.

The variable _ct on line 101 uses an underscore prefix, which conventionally indicates an unused variable, but it's actually used in the returned struct. Consider renaming to ct for clarity.

✏️ Suggested fix
-        let (_ct, u_rns, e0_rns, e1_rns) =
+        let (ct, u_rns, e0_rns, e1_rns) =
             dkg_public_key.try_encrypt_extended(&pt, &mut rng).unwrap();
 
         ShareEncryptionSample {
             plaintext: pt,
-            ciphertext: _ct,
+            ciphertext: ct,
             public_key: dkg_public_key,
crates/zk-helpers/src/circuits/dkg/share_encryption/codegen.rs (2)

64-218: Consider extracting format arguments into a struct for maintainability.

The format! macro has 50+ positional arguments, making it difficult to verify correctness and maintain. A typo or off-by-one in the argument list would cause subtle bugs.

Consider grouping related values into a helper struct or using named arguments:

💡 Alternative approach sketch
// Example: use a struct to organize template data
struct ConfigsTemplateData<'a> {
    n: usize,
    l: usize,
    qis_str: &'a str,
    prefix: &'a str,
    bits: &'a Bits,
    // ... etc
}

impl ConfigsTemplateData<'_> {
    fn render(&self) -> String {
        // Use a templating library like `askama` or `minijinja`
        // Or at minimum, build the string in sections
    }
}

This is optional given the PR scope, but worth noting for future maintainability.


126-141: Minor formatting inconsistency.

Line 140 has a closing parenthesis directly after a comma without a newline, unlike the _CONFIGS_SK block above (line 117). This creates visual inconsistency in the generated Noir code.

✏️ Suggested fix
     {}_R1_UP_BOUNDS,
     {}_R2_BOUNDS,
     {}_P1_BOUNDS,
     {}_P2_BOUNDS,
-    {}_MSG_BOUND,);
+    {}_MSG_BOUND,
+);
 "#,
crates/zk-helpers/src/circuits/dkg/share_encryption/computation.rs (4)

326-356: Potential panic on large bound values.

The to_u128().unwrap() calls (lines 329, 334, 337, 341, 345, 349, 353) will panic if any bound value exceeds u128::MAX. While this is unlikely with current BFV parameters, consider adding explicit error handling or documenting the assumption.

✏️ Suggested defensive approach
 Ok(Bounds {
     pk_bounds: pk_bounds
         .iter()
-        .map(|b| BigUint::from(b.to_u128().unwrap()))
+        .map(|b| {
+            BigUint::try_from(b.clone())
+                .expect("pk_bound exceeds BigUint capacity")
+        })
         .collect(),

Or return an error instead of panicking:

.map(|b| b.to_biguint().ok_or_else(|| CircuitsErrors::Other("bound overflow".into())))
.collect::<Result<Vec<_>, _>>()?

518-543: Inconsistent error handling inside unsafe blocks.

The code uses .ok_or_else(...).unwrap() which is verbose and still panics. Either propagate the error properly or use expect() directly for clearer intent.

✏️ Suggested fix
                 let e0i: Vec<BigInt> = unsafe {
                     qi.center_vec_vt(
                         e0_coeffs
                             .as_slice()
-                            .ok_or_else(|| "Cannot center coefficients.".to_string())
-                            .unwrap(),
+                            .expect("e0_coeffs must be contiguous"),
                     )
                     .iter()
                     .rev()
                     .map(|&x| BigInt::from(x))
                     .collect()
                 };

665-667: O(n²) leading zero removal.

Using remove(0) in a loop is O(n) per removal, making the overall complexity O(n²). For large polynomials, consider using drain or finding the first non-zero index and slicing.

✏️ Suggested fix
-                while !ct0i_calculated.is_empty() && ct0i_calculated[0].is_zero() {
-                    ct0i_calculated.remove(0);
-                }
+                let first_nonzero = ct0i_calculated.iter().position(|x| !x.is_zero()).unwrap_or(ct0i_calculated.len());
+                ct0i_calculated.drain(..first_nonzero);

The same pattern appears at lines 761-763.


784-786: Unnecessary clone before sort.

results is already an owned Vec, so .clone() before sorting is unnecessary.

✏️ Suggested fix
-        let mut results = results.clone();
+        let mut results = results;
         results.sort_by_key(|(i, ..)| *i);

Comment thread crates/zk-helpers/src/circuits/dkg/share_encryption/circuit.rs
Comment thread crates/zk-helpers/src/circuits/dkg/share_encryption/codegen.rs
Comment thread crates/zk-helpers/src/circuits/dkg/share_encryption/computation.rs
Comment thread crates/zk-helpers/src/circuits/dkg/share_encryption/sample.rs
cedoor
cedoor previously approved these changes Feb 5, 2026

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

@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)
circuits/lib/src/configs/insecure/dkg.nr (1)

103-118: ⚠️ Potential issue | 🟡 Minor

Remove unused SHARE_ENCRYPTION_CONFIGS_SK constant.

The SHARE_ENCRYPTION_CONFIGS_SK declaration at lines 103–118 is dead code—it is never referenced elsewhere in the codebase. The circuit files (sk_share_encryption and e_sm_share_encryption) import the unified SHARE_ENCRYPTION_CONFIGS instead, making the _SK variant obsolete. Remove it to complete the unification.

Comment thread crates/zk-helpers/src/circuits/dkg/share_encryption/codegen.rs
@cedoor cedoor merged commit 867ac1d into main Feb 5, 2026
44 of 45 checks passed
@github-actions github-actions Bot deleted the port/dkg-c3 branch February 13, 2026 03:18
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.

2 participants