feat(aggregation_mode): aggregate proofs in chunks
Description
Split the aggregation of proofs in chunks. For this, the aggregation program had to be split in two:
- Chunk aggregator: this runs for each one of the chunks (each chunk is configured to have a max size of 512)
- Aggregates proofs.
- Commits the Merkle root of each chunk as a public input.
- Root aggregator:
- Takes all the chunks proof along with their corresponding leaves (proofs commitments).
- Verifies that each proof originated from the chunk aggregator program.
- Verifies that the merkle root from the proof public input matches the merkle root from the provided proof leaves.
- Computes the Merkle root of all leaves and commits it as a public input.
- Produces the final aggregated proof that is verified on-chain.
Note: Because the root aggregator needs to verify that all input proofs were produced by the chunk aggregator, it must know the chunk aggregator’s program ID. This introduces a dependency between the two programs, requiring the root aggregator to be built after the chunk aggregator.
A script was created to automates this process. Running make agg_mode_write_program_ids now will:
- Compile programs.
- Copy the chunk aggregator's program ID and replace it in the root aggregator program as a constant.
- Recompile programs (this step is necessary since changing the root aggregator's constant affects its own program ID).
Considerations
-
Hash32type andMerkleTreeBackendis defined three times:- In the sdk
- In sp1 root aggregator program
- In Risc0 root aggregator program
We should consider having a
typescrates to share this kind of types. We can tackle this once we re-define the structure for the rust projects to have a single workspace with acratesfolder containing them all.
How to test
- Start a local devnet:
make ethereum_package_start
- Send many proofs to the batcher:
# Run it as much as you want to process more chunks
make batcher_send_sp1_burst
# Leave this in the background to generate batches with different merkle roots
batcher_send_burst_groth16
- Wait some time until enough proofs have been sent to run the proof aggregator with many chunks (consider lowering the
MAX_PROOFS_PER_AGGREGATIONvariable to wait less):
make start_proof_aggregator_gpu AGGREGATOR=sp1
make start_proof_aggregator_gpu AGGREGATOR=risc0
- You should see via the logs the number of chunks to be processed. You can also inspect the gpu usage via
nvtop. - Finally, once the aggregator finishes, you can verify that one of the proofs you sent has been aggregated via the aligned-cli and sdk:
cd batcher/aligned
# For SP1
cargo run verify-agg-proof \
--network devnet \
--from-block 0 \
--proving_system SP1 \
--public_input ../../scripts/test_files/sp1/sp1_fibonacci_4_1_3.pub \
--program-id-file ../../scripts/test_files/sp1/sp1_fibonacci_4_1_3.vk \
--beacon_url http://localhost:58801 \
--rpc_url http://localhost:8545
# For Risc0
cargo run verify-agg-proof \
--network devnet \
--from-block 0 \
--proving_system Risc0 \
--program-id-file ../../scripts/test_files/risc_zero/fibonacci_proof_generator/fibonacci_id_2_0.bin \
--public_input ../../scripts/test_files/risc_zero/fibonacci_proof_generator/risc_zero_fibonacci_2_0.pub \
--beacon_url http://localhost:58801 \
--rpc_url http://localhost:8545
Type of change
- [x] New feature
Checklist
- [ ] “Hotfix” to
testnet, everything else tostaging - [ ] Linked to Github Issue
- [ ] This change depends on code or research by an external entity
- [ ] Acknowledgements were updated to give credit
- [ ] Unit tests added
- [ ] This change requires new documentation.
- [ ] Documentation has been added/updated.
- [ ] This change is an Optimization
- [ ] Benchmarks added/run
- [ ] Has a known issue
- Link to the open issue addressing it
- [ ] If your PR changes the Operator compatibility (Ex: Upgrade prover versions)
- [ ] This PR adds compatibility for operator for both versions and do not change batcher/docs/examples
- [ ] This PR updates batcher and docs/examples to the newer version. This requires the operator are already updated to be compatible
This is unsound, you need to check if the aggregated proof came from the right ELF, you can test hacking it with another program that has the right public inputs but it's not fro man Agg proof. Also, don't do something that commits and with an if you don't commit in one case, make it more explicit
Changes to gas cost
Generated at commit: 322584a6c4a2e84dbce86f7f0d637fd6434f8aa5, compared to commit: deecb46ea9c59608bb51dbc3c8ca81e3b2e125e9
🧾 Summary (10% most significant diffs)
| Contract | Method | Avg (+/-) | % |
|---|---|---|---|
| AlignedLayerServiceManager | createNewTask | +94 ❌ | +0.12% |
Full diff report 👇
| Contract | Deployment Cost (+/-) | Method | Min (+/-) | % | Avg (+/-) | % | Median (+/-) | % | Max (+/-) | % | # Calls (+/-) |
|---|---|---|---|---|---|---|---|---|---|---|---|
| AlignedLayerServiceManager | 4,398,072 (0) | createNewTask receive |
56,898 (-48) 23,301 (0) |
-0.08% 0.00% |
76,984 (+94) 46,928 (+93) |
+0.12% +0.20% |
77,080 (-6) 47,115 (0) |
-0.01% 0.00% |
77,824 (0) 47,115 (0) |
0.00% 0.00% |
256 (0) 256 (0) |