Conversation
|
Gemini Here is a review of the changes: 🛑 Blockers
|
|
Opus Pro 4.6 Here's my review of PR #62. This is a substantial PR that touches the wormhole module, wallet layer, and developer tooling. I'll break it down by severity. PR #62 ReviewWhat This PR Does
Critical Issues1. The [patch."https://github.com/Quantus-Network/qp-zk-circuits"]
qp-wormhole-circuit = { path = "../qp-zk-circuits/wormhole/circuit" }
...
[patch.crates-io]
qp-dilithium-crypto = { path = "../chain/primitives/dilithium-crypto" }This will break builds for anyone who doesn't have sibling repos at those exact paths. This looks like development-only config that should be removed before merge. 2. Balance verification math appears incorrect in The let partition_amounts = random_partition(amount, num_proofs, min_per_proof);So let total_sent = (num_proofs as u128) * amount; // Bug: should just be `amount`
let final_round_amount = calculate_round_amount(amount, rounds);
let total_received = (num_proofs as u128) * final_round_amount; // Bug: same issueThis multiplies by DRY Violations (High Priority)3. Both functions:
The only difference is how 4. Both submit unsigned aggregated proof transactions and watch for status. 5.
This is inconsistent and means the binary must be compiled with Medium Issues6. The old code had 7. This function is very long and handles wallet loading, secret derivation, transfers, proof generation, aggregation, on-chain verification, balance tracking, and cleanup. Breaking it into clearly named phase functions would improve readability and testability. 8. CLI arg description mismatch /// Amount per transfer in planck (default: 10 DEV)
#[arg(short, long, default_value = "10000000000000")]
amount: u128,The help says "per transfer" but the code uses it as a total that gets partitioned. This will confuse users. 9. At line ~2001 in the new code, Minor / Nits10. 11. 12. No tests for the new functions: 13. The Summary
The main blockers are the |
n13
left a comment
There was a problem hiding this comment.
I've now read through all the diffs thoroughly. Here's my review of PR #62: Flexible Aggregator.
PR #62 Review: Flexible Aggregator
Overview
This is a substantial PR (~5,700 diff lines across 10 files) that introduces dual-output proof support, random output partitioning, a multi-round automated test flow, a developer build-circuits command, and migrates ZK circuit dependencies from git branches to versioned crates. The README gets a comprehensive command reference, and the wallet layer updates to a new HD derivation API.
Positive Highlights
- Well-structured multi-round flow -- the
run_multiroundfunction is broken into focused helpers (derive_round_secrets,execute_initial_transfers,generate_round_proofs, etc.). Nice decomposition. - Binary hash verification via
AggregationConfig::verify_binary_hashes()is a great safety net to catch stale circuit binaries before expensive proof operations. - Dry-run mode for multiround is useful for debugging HD derivation paths and partition logic without on-chain transactions.
- Good test coverage retained -- unit tests for helpers, edge cases, fee constraints, and determinism.
- Dependency stabilization -- moving from git branch deps to versioned crates is a significant improvement for reproducibility.
- Excellent README -- the new command reference is thorough and well-organized.
Issues & Suggestions
1. DRY Violation: verify_aggregated_proof vs verify_aggregated_and_get_events
These two functions both submit an unsigned verify_aggregated_proof tx, watch for InBestBlock / InFinalizedBlock / Error, and inspect events. The core submission + event-watching loop is duplicated. Consider extracting a shared helper that takes a callback for event processing, or returns a generic result struct that both callers can consume.
2. DRY Violation: InBestBlock / InFinalizedBlock arms are copy-pasted
Within verify_aggregated_proof, the InBestBlock and InFinalizedBlock match arms are nearly identical (same event checking, same error handling). Same pattern in verify_aggregated_and_get_events. Each function has ~40 lines duplicated between the two arms.
3. DRY Violation: verify_binary_hashes repeated pattern
The three if let Some(ref expected) / hash_file / mismatches.push blocks are structurally identical. A small loop would be cleaner:
let checks = [
("aggregated_common.bin", &stored_hashes.aggregated_common),
("aggregated_verifier.bin", &stored_hashes.aggregated_verifier),
("prover.bin", &stored_hashes.prover),
];
for (filename, expected_hash) in checks {
if let Some(ref expected) = expected_hash {
if let Some(actual) = hash_file(filename) {
if expected != &actual {
mismatches.push(format!("{}...", filename));
}
}
}
}4. validate_aggregation_params appears to be dead code
The original aggregate_proofs called validate_aggregation_params(proof_files.len(), depth, branching_factor). The new version validates directly against agg_config.num_leaf_proofs. Unless validate_aggregation_params is pub and used externally, it should be removed.
5. Missing tests for new core logic
random_partition and compute_random_output_assignments are non-trivial functions with edge cases (e.g., n=0, n=1, total < min_total, more targets than proof output capacity). Neither has unit tests. Given that these directly affect fund distribution, test coverage here would be valuable.
6. Potential panic in random_partition
parts[idx] = (parts[idx] as i128 + diff) as u128;If diff is negative and |diff| > parts[idx], this wraps to a very large u128. It's unlikely in practice, but a .max(0) guard or saturating_add approach would be safer for production code handling real funds.
7. File size concern: wormhole.rs is becoming very large
The modified file is approaching ~3,500+ lines. The multiround logic, proof generation, aggregation, and verification are all in one file. Consider splitting into submodules (e.g., wormhole/multiround.rs, wormhole/aggregate.rs, wormhole/verify.rs) to improve navigability.
8. TransferInfo.block_hash initialized as H256::default() then overwritten
In parse_transfer_events, the block hash is set to a zero hash and the caller is responsible for overwriting it. This is error-prone -- a future caller might forget. Consider taking block_hash as a parameter to parse_transfer_events instead.
9. AggregationConfig duplicates upstream struct
The PR acknowledges this in comments ("Must match the CircuitBinsConfig struct in qp-wormhole-aggregator/src/config.rs"). If the upstream struct changes, this will silently desync. Consider re-exporting the config struct from the aggregator crate, or at minimum adding a compile-time or test-time assertion that the deserialized format matches.
10. Breaking changes not gated
The Generate, Verify, and multisend commands are removed. Users upgrading will lose these subcommands. If there are any downstream scripts or docs referencing them, they'll break. The PR description mentions this is intentional, but consider whether a deprecation cycle (warn + redirect) would be warranted for a production CLI.
Minor / Nits
- Unused import in original
generate_proof:WormholeVerifierwas imported in the old code'saggregate_proofsbut the new version loads from pre-built bins. If the import is still there, it can be cleaned up. log_print!andlog_verbose!both called for public inputs count inparse_proof_file(lines 3423-3424 of the diff):log_print!already outputs to the user, thelog_verbose!on the next line is redundant.format_balancetruncates to 2 decimal places. For debugging transfers of very precise amounts, consider showing more precision or making it configurable.
Verdict
This is a well-executed feature PR with solid architectural choices (config-driven aggregation, pre-built binaries, HD-derived secrets). The main concerns are around DRY violations in the verification paths, missing tests for the new partitioning logic, and the growing file size of wormhole.rs. None of these are blockers, but addressing them would meaningfully improve maintainability.
…tus-cli into illuzen/new-plonky2
…tus-cli into illuzen/new-plonky2
Summary
Adds dual-output support and random partitioning to the wormhole multiround flow, plus developer tooling improvements.
Key Changes
Dual Output Random Partitioning
compute_random_output_assignments()randomly distributes outputs across targetsNew Developer Command
Builds circuit binaries and copies to CLI/chain directories.
Simplified Verification
verifycommand (useverify-aggregated)--verifyflag toparse-prooffor local cryptographic verificationCleanup
multisendcommandTesting
NativeTransferredevents)