Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pnpm lint
pnpm check:pnpm
pnpm check:license
pnpm check:license
pnpm check:committee
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions agent/RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,27 @@ content.
- `tests/` — Integration tests
- `agent/` — LLM context documentation

## Build configuration: preset and committee

Two orthogonal axes pick what gets compiled into `circuits/bin/`:

- **Preset** (`--preset insecure-512` [default] | `secure-8192`): the BFV parameter set.
- **Committee** (`--committee micro` [default] | `small` | `medium`): `(N, T, H)` for the
secret-sharing committee. Mirrors `e3_zk_helpers::CiphernodesCommitteeSize`.

The current selection is the single source of truth at three places that **must** stay in sync:

| File | Owner |
| ----------------------------------------------------------- | ------------------------------------------ |
| `circuits/lib/src/configs/committee/active.nr` | regenerated by `scripts/build-circuits.ts` |
| `packages/enclave-contracts/scripts/utils.ts` (`BFV_DKG_H`) | regenerated by `scripts/build-circuits.ts` |
| `circuits/bin/.active-preset.json` | written by `scripts/build-circuits.ts` |

`scripts/check-committee.sh` (pre-push hook: `pnpm check:committee`) enforces consistency. Always
switch with `pnpm build:circuits --committee <name>`; never hand-edit the three files above.
Supported `(preset, committee)` pairs live in `scripts/circuit-constants.ts`. See
`scripts/README.md#circuit-builder` and `circuits/benchmarks/README.md` for the full recipe.

## Flow-Trace Documentation (`agent/flow-trace/`)

The `agent/flow-trace/` directory contains detailed protocol documentation that traces the complete
Expand Down
40 changes: 31 additions & 9 deletions agent/flow-trace/04_DKG_AND_COMPUTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,13 @@ ThresholdKeyshare receives AllThresholdSharesCollected
│ │ │ → Stored encrypted locally for later decryption │
│ │ └─────────────────────────────────────────────────────┘
├─ 2b. CANONICAL H ROSTER (when H < N):
│ Before C4 witness layout, merge external honest party_ids with own_party_id,
│ sort ascending, and keep the lowest H — same rule as PublicKeyAggregator C5 cap
│ (`e3_zk_helpers::canonical_honest_party_ids_with_own`). Persisted as `honest_parties`.
│ Parties outside the lowest H still complete KeyshareCreated but are not in the
│ aggregator's NodeFold / `honest_committee_addresses` roster.
├─ 3. PUBLISH C4 PROOF REQUESTS:
│ DecryptionShareProofsPending {
│ sk_request: DkgShareDecryptionProofRequest (C4a),
Expand Down Expand Up @@ -548,31 +555,43 @@ ThresholdKeyshare receives AllThresholdSharesCollected
├─ Only the active aggregator's buffer flushes into PublicKeyAggregator
├─ When threshold_n keyshares collected:
├─ When N distinct keyshares collected (committee size from on-chain `threshold_n`):
│ │
│ ├─ C1 verification runs over all N submitters; parties failing C1 are marked dishonest
│ │
│ ├─ Honest-set selection (compile-time H from `committee::active`, may be < N):
│ │ • Require at least H parties with valid C1 proofs; otherwise E3Failed
│ │ • If more than H parties pass C1, keep the H lowest `party_id`s as the canonical
│ │ honest set (extras remain in the full committee roster for `committee_hash`
│ │ binding but do not receive NodeFold / C5 inputs)
│ │
│ ├─ 1. Aggregate public key shares:
│ ├─ 1. Aggregate public key shares (H honest keyshares):
│ │ aggregate_pk = Fhe::get_aggregate_public_key(
│ │ [pk_share_1, pk_share_2, ..., pk_share_N]
│ │ [pk_share for each of the H canonical honest parties]
│ │ )
│ │ → Uses PublicKeyShare::aggregate()
│ │ → Produces the COLLECTIVE public key
│ │ → Anyone can encrypt with this key
│ │ → Only M+1 committee members can decrypt together
│ │
│ ├─ 2. Compute commitment:
│ │ pk_hash = compute_pk_commitment(aggregate_pk)
│ ├─ 2. Build C5 proof request (H canonical honest keyshares):
│ │ proof_request.keyshare_bytes = [pk_share for each H party]
│ │ proof_request.aggregated_pk_bytes = aggregate_pk
│ │ proof_request.committee_n = committee_h = H // C5 circuit sized for H, not N
│ │ (per-share compute_pk_commitment already checked against C1; aggregate
│ │ commitment is proved as a C5 public output, not pre-published here)
│ │
│ ├─ 3. REQUEST C5 PROOF:
│ │ Publish PkAggregationProofPending {
│ │ proof_request: PkAggregationProofRequest,
│ │ proof_request, // H keyshares + aggregate_pk (see step 2)
│ │ public_key: aggregate_pk,
│ │ public_key_hash: pk_hash
│ │ nodes: honest_nodes // H canonical subset
│ │ }
│ │
│ ├─ 4. C5 PROOF GENERATION (ProofRequestActor):
│ │ ├─ Dispatches ComputeRequest::zk(ZkRequest::PkAggregation {...})
│ │ │ → Circuit: PkAggregation (C5)
│ │ │ → Proves aggregate PK was correctly computed from all pk_shares
│ │ │ → Proves aggregate PK was correctly computed from the H canonical honest keyshares
│ │ ├─ ZkActor generates proof via bb binary
│ │ ├─ Signs proof
│ │ └─ Publishes PkAggregationProofSigned {
Expand All @@ -593,6 +612,8 @@ ThresholdKeyshare receives AllThresholdSharesCollected
│ │
│ └─ 6. Publish PublicKeyAggregated {
│ e3_id, pubkey: aggregate_pk, pk_commitment, nodes,
│ committee_addresses, // length N — full on-chain topNodes binding
│ honest_committee_addresses, // length H — canonical honest subset
│ dkg_aggregator_proof
│ }
Expand Down Expand Up @@ -947,7 +968,8 @@ EnclaveSolReader decodes CiphertextOutputPublished event
│ │ │ │ by C6 │
├──────┼────────────────────────────┼───────────────────┼──────────────────────────────┤
│ C5 │ PK Aggregation │ Aggregation │ Aggregate PK correctly │
│ │ │ │ computed from all pk_shares │
│ │ │ │ computed from H canonical │
│ │ │ │ honest keyshares (not all N) │
├──────┼────────────────────────────┼───────────────────┼──────────────────────────────┤
│ C6 │ Threshold Share Decryption │ Decryption │ Decryption share correctly │
│ │ (T5) │ │ derived from sk + ciphertext;│
Expand Down
37 changes: 37 additions & 0 deletions circuits/benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,43 @@ From this directory:

Options and secure-only **config** circuit behavior are documented in the script and `config.json`.

### Selecting committee size (micro / small / medium)

Benchmarks compile and run against whichever committee is **active** in the Noir tree. Default is
`micro` (N=3, T=1, H=3). To benchmark with a different committee, switch it once at the build step
and the Rust integration test, gas-extraction script, and report will all pick it up automatically.

**Step-by-step** (from repository root):

```bash
# 1. Pick the committee. This regenerates committee/active.nr, default/mod.nr,
# and patches BFV_DKG_H / BFV_THRESHOLD_T in utils.ts atomically. It also writes
# the committee into circuits/bin/.active-preset.json.
pnpm build:circuits --preset insecure-512 --committee medium

# 2. (Optional) Verify the four files agree.
pnpm check:committee
# → ✓ check:committee: medium (H=8, T=4) consistent across active.nr, utils.ts, .active-preset.json

# 3. Run the benchmark. ENCLAVE_COMMITTEE_SIZE makes the Rust test pick the same committee
# and panic up-front if it disagrees with the stamp.
ENCLAVE_COMMITTEE_SIZE=medium ./circuits/benchmarks/run_benchmarks.sh --mode insecure

# 4. To go back to micro, run step 1 again with --committee micro.
pnpm build:circuits --preset insecure-512 --committee micro
```

**All `(preset, committee)` pairs are supported.** The parity matrices in
`circuits/lib/src/configs/committee/<name>/parity_{insecure,secure}.nr` are auto-generated by the
`generate_parity_matrices` Rust binary, invoked from `scripts/build-circuits.ts` whenever the
committee changes. The values are deterministic functions of the committee's `(N, T)` and the
preset's threshold `QIS`, so any pair compiles and proves correctly.

**Skipping the build step:** `pnpm check:committee` runs in the pre-push hook and fails the push if
`active.nr`, `utils.ts`, `.active-preset.json`, or any committed `parity_*.nr` disagree with what
`build:circuits --committee <active>` would produce. Always use `pnpm build:circuits --committee` to
switch; manual edits to those files will trip the check.

### Proof aggregation and folding (integration)

The gas / integration stage runs `cargo test -p e3-tests test_trbfv_actor` with **proof aggregation
Expand Down
107 changes: 0 additions & 107 deletions circuits/benchmarks/results_insecure_agg/crisp_verify_gas.json

This file was deleted.

Loading
Loading