feat: miner aggregation support#560
Conversation
*Enables staged miner aggregation in the runtime and uses matching circuit artifacts for bundled proof generation and verification. *Improves settlement safety by locking nullifiers while bundles are assembled, rejecting duplicates and reused inputs, and adding optional layer-1 verifier support for multi-stage aggregation.
| .map_err(|_| Error::<T>::L1ProofRejected)?; | ||
|
|
||
| let nullifiers = Self::layer1_nullifier_bytes(&inputs)?; | ||
| pallet_wormhole::Pallet::<T>::mark_locked_nullifiers_used(bundle_id, &nullifiers) |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: HIGH
submit_l1_aggregate marks locked nullifiers as used before calling settle_public_outputs, but settle_public_outputs can still fail. This creates a partial-state failure path where nullifiers are consumed and locks removed while the bundle remains unsettled.
Impact: A malicious or malformed aggregate can cause persistent bundle liveness failure and strand reserved funds, because timeout recovery later cannot unlock already-removed nullifier locks.
| pub fn claim_bundle( | ||
| origin: OriginFor<T>, | ||
| group_key: BundleGroupKey, | ||
| aggregator_address: [u8; 32], |
There was a problem hiding this comment.
🔒 Agentic Security Review
Severity: MEDIUM
claim_bundle accepts caller-supplied aggregator_address and stores it directly in the bundle without enforcing equality to the miner’s registered reward_address. Settlement payouts are later derived from this bundle value.
Impact: A registered miner (or compromised claiming key) can redirect candidate aggregation tips away from the configured registered reward destination, breaking the intended payout-boundary invariant.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit af0ea93. Configure here.
| ); | ||
| Self::deposit_event(Event::AggregatorRegistered { account }); | ||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
Re-registration permanently locks previously reserved aggregator bond
Medium Severity
register_aggregator unconditionally overwrites any existing RegisteredAggregators entry without unreserving the previously held bond. If a registered aggregator calls this again, the old reserved bond is permanently locked (no unreserve path exists), and active_jobs resets to 0, making the counter inconsistent with MinerActiveBundles storage. There is no unregister/withdraw function to recover the stranded funds.
Reviewed by Cursor Bugbot for commit af0ea93. Configure here.
| } | ||
|
|
||
| Ok(total_exit_amount) | ||
| } |
There was a problem hiding this comment.
Duplicated settlement logic risks future inconsistent patches
Low Severity
settle_public_outputs duplicates ~100 lines of complex financial logic (fee calculation, minting, burning, transfer recording) already present inline in verify_aggregated_proof. Both paths compute fees, mint to exit accounts, pay block author, and burn. A bug fix applied to one but not the other would create a divergence in money-handling behavior.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit af0ea93. Configure here.
*Adds transactional execution around bundle and proof flows so failed settlement rolls back cleanly instead of leaving partial state behind. *Refactors public output settlement into prepare/apply steps, validates locked nullifiers before consuming them, and keeps locks, claim status, and active job tracking intact when post-verification settlement fails. *Improves fee and amount validation with safer arithmetic and adds regression tests for rollback behavior and settlement preparation.
*Rejects invalid or mismatched reward addresses so bundles, proofs, and payouts stay bound to the address registered by the aggregator. *Prevents silent fallback to the miner account during settlement, tightens proof validation against the claimed reward destination, and adds coverage for rejection and payout paths.
*Adds update and unregister flows so registration changes can safely resize or release reserved funds instead of leaving old bond amounts locked. *Blocks registration changes while work is still active and verifies active-job accounting after claim, timeout, and settlement to catch inconsistent state early.
*Rewards delegated L1 aggregation with a configurable share of non-burned volume fees, so prover incentives are paid as part of settlement instead of relying only on tips. *Emits settlement and reward events for better accounting, keeps direct settlement fee behavior unchanged, and preserves burn handling when no block author is available.
*Adds configurable slashing and challenger rewards so timeouts, invalid proof submissions, and invalid claims are penalized instead of simply releasing reserved funds. *Allows invalid candidates to be challenged even after bundling, which restores unaffected work safely by unlocking nullifiers, re-queueing valid leftovers, and keeping miner job accounting consistent. *Updates runtime parameters, events, weights, and tests to cover the new dispute and penalty flow.
*Adds stronger MVP checks so settlement rejects mismatched exits, nullifiers, reordered effects, and inconsistent exit slot counts. *Clarifies that the bundle root remains metadata until the L1 circuit constrains it, and adds focused tests to lock in the intended verification behavior.
*Verifies successful aggregate settlement against real L1 fixtures so the positive path no longer relies on cheap rejection checks alone. *Adds targeted mismatch cases to catch metadata drift before settlement and protect balance, bond, and nullifier handling. *Updates testing notes to document release-mode fixture generation and the environment needed to run the L1 proof path.
*Pins the ZK circuit dependencies to an exact revision so downstream builds stay reproducible and aligned across related repos during delegated aggregation work. *Clarifies MVP limitations and the current dependency strategy, and documents that runtime weights are conservative placeholders rather than benchmark output. *Splits aggregate submission estimates by cheap-reject vs valid-proof paths and keeps the dispatchable on the safe upper bound until real benchmarks replace the placeholders.
*Ensures tests verify settlement inputs stay available before a bundle is claimed, then become locked once claimed. *Prevents regressions where direct settlement could proceed after claim and strengthens coverage around bundle state transitions.




Summary
Adds delegated Wormhole L1 aggregation support to the chain through a new
pallet-miner-aggregation, plus Wormhole nullifier locking and L1 verification/settlement helpers.The new flow allows users to submit bounded L0 aggregate proof candidates, lets registered and bonded aggregation miners claim compatible bundles, locks bundle nullifiers while delegated L1 proving is in progress, and settles exits/rewards once a valid L1 aggregate proof is submitted.
What changed
Miner aggregation pallet
pallet-miner-aggregationfor delegated L1 aggregation.BundleGroupKey.pallet-wormhole.Wormhole settlement and nullifiers
LockedNullifiersstate topallet-wormhole.Runtime and workspace wiring
MinerAggregationinto the runtime.qp-zk-circuitsdependencies to the matching delegated L1 aggregation revision so chain, miner, and circuit artifacts stay aligned.Tests, fixtures, and docs