Skip to content

Proof aggregation#58

Merged
larraia merged 1 commit into
developfrom
enrique/aggregation
Oct 1, 2025
Merged

Proof aggregation#58
larraia merged 1 commit into
developfrom
enrique/aggregation

Conversation

@larraia

@larraia larraia commented Jul 18, 2025

Copy link
Copy Markdown
Contributor
  • Sequential and batch aggregation
  • Base proofs erased upon successful aggregation

Not in this PR - to be done:

  • Benchmarks. See here.
  • Btree strategy. See here

@larraia larraia requested review from XuyangSong and vveiln July 18, 2025 13:36
@larraia larraia force-pushed the enrique/aggregation branch from 52d5ea3 to 50ba31a Compare July 28, 2025 14:37
@larraia larraia changed the title Sequential aggregation Proof aggregation Jul 28, 2025
@larraia

larraia commented Jul 28, 2025

Copy link
Copy Markdown
Contributor Author

@XuyangSong @vveiln the PR is now ready for review.

@XuyangSong XuyangSong left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good overall. I've left some feedback.

Could you rebase onto the develop branch and resolve the conflicts? We updated some basic structs.

I've reviewed the circuit implementation—it looks nice. I'll run the tests and benchmarks after the rebase.

Comment thread README.md Outdated
Comment thread arm/Cargo.toml Outdated
Comment thread arm/benches/aggregation.rs Outdated
Comment thread examples/aggregation_circuits/batch_aggregation/src/main.rs Outdated
Comment thread examples/aggregation_circuits/batch_aggregation/src/main.rs Outdated
Comment thread examples/aggregation_circuits/batch_aggregation/src/main.rs Outdated
Comment thread arm/src/aggregation/batch.rs Outdated
Comment thread arm/src/aggregation/mod.rs
Comment thread arm/src/aggregation/proof.rs Outdated
Comment thread arm/src/aggregation/proof.rs Outdated
@larraia larraia force-pushed the enrique/aggregation branch 4 times, most recently from 129aba1 to d0949e2 Compare August 29, 2025 09:46
@larraia larraia requested a review from XuyangSong August 29, 2025 09:48
@larraia larraia force-pushed the enrique/aggregation branch 3 times, most recently from a9ef646 to 0db91a0 Compare September 8, 2025 08:10

@XuyangSong XuyangSong left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the work. Left a few comments.

Could you fix cargo clippy --workspace --all-targets -- -D warnings warnings, as the current CI does not automatically cover the aggregation feature.

In most cases, using Result instead of Option is better for proper error handling. I'm also handling errors in arm concurrently. Maybe you can wait until the error handling in arm is done.

Do you have a comparison of the two strategies? When should we use batch versus sequential?

Could you add a brief description in the README about proof types, including inner and aggregated proof types, and how to specify them?

Comment thread arm/src/aggregation/batch.rs Outdated
Comment thread arm/src/aggregation/batch.rs Outdated
#[cfg(feature = "fast_aggregation")]
let prover_opts = ProverOpts::fast();

#[cfg(all(not(feature = "fast_aggregation"), feature = "groth16_aggregation"))]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the inner proof type affect the aggregation proof type?
Default succinct proofs are used in tests. Can other proof types be aggregated?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By inner proof type do you mean the InnerReceipt of the compliance/logic proofs? If so, I would say it does not affect it. RISC0 allows to add a Receipt as an assumption without differentiation.

Aggregation should be agnostic to what is aggregating. This can be empirically confirmed when running benches. (I can't from my machine.)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What inner proof types should we use in practice, and what are the differences between them? Do they vary in performance? I don't fully understand the agnosticism of the inner types—does it mean the outer (aggregation) circuit can verify different inner proof types dynamically?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it mean the outer (aggregation) circuit can verify different inner proof types dynamically

That's my understanding, yes. Boils down to proving a computational trace for a stark/groth16 verifier(s). Aggregating succinct proofs (single stark) should yield the fastest aggregation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added note in the README about this

Comment thread arm/src/compliance_unit.rs
Comment thread arm_circuits/batch_aggregation/src/main.rs
Comment thread arm/src/hash.rs Outdated
Comment thread arm/src/transaction.rs Outdated
Comment on lines +132 to +142
if agg_proof.is_some() {
self.aggregation_proof = bincode::serialize(&agg_proof.unwrap()).ok();
}

if self.aggregation_proof.is_some() {
self.erase_base_proofs();
Some(())
} else {
// Do nothing.
None
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if agg_proof.is_some() {
self.aggregation_proof = bincode::serialize(&agg_proof.unwrap()).ok();
}
if self.aggregation_proof.is_some() {
self.erase_base_proofs();
Some(())
} else {
// Do nothing.
None
}
if agg_proof.is_some() {
self.aggregation_proof = bincode::serialize(&agg_proof.unwrap()).ok();
self.erase_base_proofs();
Some(())
} else {
None
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only want to remove the base proofs if the serialized aggregation actually contains some bytes after L133. (There maybe simpler ways of checking self.aggregation_proof is Some after line 133, but I chose clarity)

Comment thread arm/src/transaction.rs Outdated
Comment thread arm/src/transaction.rs Outdated
Comment thread arm/src/transaction.rs Outdated
@larraia

larraia commented Sep 22, 2025

Copy link
Copy Markdown
Contributor Author

@XuyangSong :

In most cases, using Result instead of Option is better for proper error handling. I'm also handling errors in arm concurrently. Maybe you can wait until the error handling in arm is done.

This PR was created before error handling exist in the library. The use of Option is to later introduce Result with minimal impact in calling code. So, IMO this is technical debt outside this PR's scope. See this issue.

@larraia

larraia commented Sep 22, 2025

Copy link
Copy Markdown
Contributor Author

Could you add a brief description in the README about proof types, including inner and aggregated proof types, and how to specify them?

The README explains how to specify the different aggregation proof types in the Features table. Is that what you mean? Re inner proof types, not sure what you mean, but this comment might be relevant.

@larraia

larraia commented Sep 22, 2025

Copy link
Copy Markdown
Contributor Author

Do you have a comparison of the two strategies? When should we use batch versus sequential?

In the README (proof aggregation section) the difference between batch and sequential is mentioned. When to use each, I guess aggregation (proving) performance is the most relevant metric -- we should wait for benches i guess... :_) Let me know otherwise.

@larraia larraia force-pushed the enrique/aggregation branch from 59749af to 3fb5b15 Compare September 25, 2025 14:56
@larraia

larraia commented Sep 25, 2025

Copy link
Copy Markdown
Contributor Author

This PR also closes #116 (error handling for proof aggregation)

@XuyangSong XuyangSong left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm
We can merge after PA testing.

Comment thread arm/src/aggregation/batch.rs Outdated
))
.map_err(|_| ArmError::InstanceSerializationFailed)?;

println!("[DEBUG:] batch instance: {:?}", batch_instance);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the print here? We can consider adding it to the log in the future.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my bad! thanks for catching it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@agureev

agureev commented Sep 30, 2025

Copy link
Copy Markdown
Contributor

Works as checked in anoma/pa-evm#336

Feel free to merge

Comment thread arm/Cargo.toml
# If you want to try (experimental) std support, add `features = [ "std" ]` to risc0-zkvm
risc0-zkvm = { version = "3.0.3", features = ["std", "unstable"], default-features = false }
serde = { version = "1.0.197", default-features = false }
serde_with = "3.14.1"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to introduce this as a dependency if it is only used once? We should minimize dependencies and be wary of supply chain attacks.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compliance instances are too large to be serialized with serde. What do you suggest instead?

@heueristik heueristik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest removing serde_with or to double check what the other dependencies it introduces are ("darling_core 0.20.11", "darling_macro 0.20.11").

@larraia larraia force-pushed the enrique/aggregation branch from b4810fa to e58093c Compare October 1, 2025 09:42
@larraia larraia force-pushed the enrique/aggregation branch from 1d0eaf2 to cbe9b7a Compare October 1, 2025 10:17
@larraia larraia merged commit 92e61b2 into develop Oct 1, 2025
4 of 10 checks passed
@github-project-automation github-project-automation Bot moved this from Expecting reroll to Released in Anoma SDK - What's Cooking Oct 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Released

Development

Successfully merging this pull request may close these issues.

4 participants