feat: connect c1 and c5 [skip-line-length]#1460
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR implements cross-circuit verification between C1 (key generation) and C5 (pk aggregation) proofs. It extracts pk_commitment outputs from C1 proofs of honest parties after C1 verification, passes them through to C5 validation, and verifies that C5's expected threshold pk commitments match the actual C1 commitments. On mismatch, the aggregator re-filters parties and re-aggregates; mismatched parties trigger SignedProofFailed events downstream. Changes
Sequence Diagram(s)sequenceDiagram
participant Aggregator as PublicKeyAggregator
participant Multithread as Multithread<br/>(ZkProver)
participant ProofActor as ProofRequest<br/>Actor
participant Events as Event Bus
Note over Aggregator,Events: After C1 verification completes
Aggregator->>Aggregator: Extract C1 signed proofs<br/>from honest parties
Aggregator->>Aggregator: Re-order proofs to match<br/>keyshare_bytes ordering
Aggregator->>Events: Publish PkAggregationProofRequest<br/>with c1_signed_proofs
Note over Multithread: C5 proof generation phase
Multithread->>Multithread: Extract pk_commitment from<br/>each c1_signed_proofs[i]
alt Commitment mismatch detected
Multithread->>Multithread: Identify mismatched indices
Multithread->>Events: Publish ComputeRequestError<br/>(C1CommitmentMismatch)
Events->>Aggregator: handle_c5_error()
Aggregator->>Aggregator: Filter out mismatched parties<br/>from keyshare_bytes & c1_signed_proofs
Aggregator->>Aggregator: Recompute aggregate pk<br/>from remaining parties
Aggregator->>Events: Publish PkAggregationProofRequest<br/>(filtered request)
else All commitments match
Multithread->>Multithread: Proceed to C5 proof generation
end
Note over ProofActor: Mismatch handling downstream
ProofActor->>ProofActor: Recover faulting node address<br/>from c1_signed_proofs[idx]
ProofActor->>Events: Emit SignedProofFailed<br/>for each mismatched party
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
c79b62f to
3ba7ab5
Compare
3ba7ab5 to
aa655ee
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/aggregator/src/publickey_aggregator.rs (1)
441-470:⚠️ Potential issue | 🔴 CriticalValidate the received C5 proof before caching it.
This handler still stores
msg.signed_proof.payload.proofverbatim. The new check incrates/multithread/src/multithread.rsonly validates the locally built request; it does not protect this externally receivedPkAggregationProofSignedpath. A buggy or malicious prover can still send a C5 proof whose public inputs bind differentexpected_threshold_pk_commitments, and we will publishPublicKeyAggregatedanyway. Parse the signed proof’spublic_signalshere and reject it before settingc5_proof_pendingwhen those commitments differ from the cached C1 commitments. You’ll need input extraction for this;extract_outputonly covers the trailing output region.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/aggregator/src/publickey_aggregator.rs` around lines 441 - 470, The handler currently caches msg.signed_proof.payload.proof into c5_proof_pending without validating its public_signals; update the branch that matches PublicKeyAggregatorState::GeneratingC5Proof to parse the signed proof’s public_signals (extract the proof's public inputs from msg.signed_proof.payload.proof using the same extraction logic used elsewhere or a new input extractor since extract_output only handles trailing output), derive the expected_threshold_pk_commitments from those public_signals, and compare them to the cached C1 commitments stored in the state (e.g. data available via c1_signed_proofs or the field that contains the cached commitments); if they differ, reject/ignore the incoming proof (do not set c5_proof_pending and optionally log the mismatch), otherwise set c5_proof_pending: Some(c5_proof) and proceed as before (updating last_ec).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/aggregator/src/publickey_aggregator.rs`:
- Around line 872-915: Persist the original threshold_m in the GeneratingC5Proof
state and re-enforce the minimum-honest-party check before republishing
PkAggregationProofPending: ensure remaining_count >= threshold_m + 1 (return Err
if not) and set committee_threshold: threshold_m in the constructed
PkAggregationProofRequest (instead of 0); update uses of GeneratingC5Proof to
carry threshold_m through to this code path so you can both validate
remaining_count and populate the request.
- Around line 29-58: The current derive_c1_commitments function uses filter_map
which drops entries when proof.extract_output("pk_commitment") fails, shifting
indices and breaking the one-to-one mapping with keyshare_bytes; change it to
preserve positions by using map instead and return a Vec<Option<ArcBytes>> (or
Vec<Result<ArcBytes, YourError>>) so failures are represented per-index rather
than removed: iterate over signed_proofs with .map(|opt|
opt.as_ref().and_then(|sp|
sp.payload.proof.extract_output("pk_commitment").or_else(|| {
tracing::warn!(...); None }))) or return Result on extraction errors, update
callers (e.g., where keyshare_bytes and C1CommitmentMismatch are checked) to
handle the Option/Result and convert extraction failures into explicit
proof-failure/C1CommitmentMismatch handling rather than relying on shifted
indices.
In `@crates/events/src/enclave_event/compute_request/zk.rs`:
- Around line 64-65: The new field c1_commitments on PkAggregationProofRequest
must get a serde default to preserve backward compatibility; update the struct
by adding #[serde(default)] to the c1_commitments declaration (the Vec<ArcBytes>
field) so older serialized payloads deserialize to an empty vector while keeping
the existing validation in crates/multithread/src/multithread.rs that checks C1
commitments intact.
In `@crates/multithread/src/multithread.rs`:
- Around line 348-361: The code currently only validates c1_commitments length
but not the per-party keyshare count; before calling PkAggInputs::compute, add a
guard that checks req.keyshare_bytes.len() == req.committee_h and return
Err(make_zk_error(&request, format!("keyshare_bytes length {} != committee_h
{}", req.keyshare_bytes.len(), req.committee_h))) if it mismatches, so
PkAggInputs::compute (which iterates 0..committee_h) cannot panic or silently
truncate.
---
Outside diff comments:
In `@crates/aggregator/src/publickey_aggregator.rs`:
- Around line 441-470: The handler currently caches
msg.signed_proof.payload.proof into c5_proof_pending without validating its
public_signals; update the branch that matches
PublicKeyAggregatorState::GeneratingC5Proof to parse the signed proof’s
public_signals (extract the proof's public inputs from
msg.signed_proof.payload.proof using the same extraction logic used elsewhere or
a new input extractor since extract_output only handles trailing output), derive
the expected_threshold_pk_commitments from those public_signals, and compare
them to the cached C1 commitments stored in the state (e.g. data available via
c1_signed_proofs or the field that contains the cached commitments); if they
differ, reject/ignore the incoming proof (do not set c5_proof_pending and
optionally log the mismatch), otherwise set c5_proof_pending: Some(c5_proof) and
proceed as before (updating last_ec).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f3bb0269-c91f-4c89-a03d-21cc5d5125b5
📒 Files selected for processing (7)
crates/aggregator/src/publickey_aggregator.rscrates/events/src/enclave_event/compute_request/zk.rscrates/events/src/enclave_event/proof.rscrates/multithread/src/multithread.rscrates/zk-helpers/src/circuits/mod.rscrates/zk-helpers/src/circuits/output_layout.rscrates/zk-helpers/src/circuits/threshold/pk_generation/computation.rs
8a31527 to
bb53583
Compare
hmzakhalid
left a comment
There was a problem hiding this comment.
Thanks Ale!
Could we add an integration test as well?
multithread detecting a mismatch -> error event -> aggregator receiving it -> handling
973894d to
5855adb
Compare
176f108 to
4ce60c8
Compare
4ce60c8 to
1ffff4e
Compare
fix #1452
Summary by CodeRabbit
Bug Fixes
Chores