92 lines
3.3 KiB
Rust
Raw Normal View History

2025-01-09 10:32:14 +01:00
use plonky2::plonk::proof::ProofWithPublicInputs;
use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, VerifierCircuitData};
use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::iop::witness::PartialWitness;
2025-01-10 11:29:03 +01:00
use crate::params::{C, D, F};
use crate::recursion::simple::simple_recursion;
2025-01-09 10:32:14 +01:00
// recursion tree width or the number of proofs in each node in the tree
const RECURSION_TREE_WIDTH: usize = 2;
/// aggregate sampling proofs in tree like structure
/// uses the const params: `RECURSION_TREE_WIDTH`
/// In this tree approach the building is done at each level -> very slow!
pub fn aggregate_sampling_proofs_tree(
proofs_with_pi: &[ProofWithPublicInputs<F, C, D>],
data: CircuitData<F, C, D>,
) -> anyhow::Result<(ProofWithPublicInputs<F, C, D>, CircuitData<F, C, D>)> {
// base case: if only one proof remains, return it
if proofs_with_pi.len() == 1 {
return Ok((proofs_with_pi[0].clone(), data));
}
let mut new_proofs = vec![];
let mut new_circuit_data: Option<CircuitData<F, C, D>> = None;
// group proofs according to the tree's width
for chunk in proofs_with_pi.chunks(RECURSION_TREE_WIDTH) {
let proofs_chunk = chunk.to_vec();
// Build an inner-circuit to verify and aggregate the proofs in the chunk
let inner_config = CircuitConfig::standard_recursion_config();
let mut inner_builder = CircuitBuilder::<F, D>::new(inner_config);
let mut inner_pw = PartialWitness::new();
// aggregate proofs
simple_recursion::aggregate_sampling_proofs(
&proofs_chunk,
&data.verifier_data(),
&mut inner_builder,
&mut inner_pw,
)?;
// Build the inner-circuit
// this causes major delay - we can load it but better if we split build and prove
let inner_data = inner_builder.build::<C>();
// Prove the inner-circuit
let proof = inner_data.prove(inner_pw)?;
new_proofs.push(proof);
new_circuit_data = Some(inner_data);
}
// Recursively aggregate the new proofs
aggregate_sampling_proofs_tree(&new_proofs, new_circuit_data.unwrap())
}
/// same as above but takes `VerifierCircuitData`
pub fn aggregate_sampling_proofs_tree2(
proofs_with_pi: &[ProofWithPublicInputs<F, C, D>],
vd: VerifierCircuitData<F, C, D>
) -> anyhow::Result<(ProofWithPublicInputs<F, C, D>, VerifierCircuitData<F, C, D>)> {
if proofs_with_pi.len() == 1 {
return Ok((proofs_with_pi[0].clone(), vd));
}
let mut new_proofs = vec![];
let mut new_circuit_data: Option<VerifierCircuitData<F, C, D>> = None;
for chunk in proofs_with_pi.chunks(RECURSION_TREE_WIDTH) {
let proofs_chunk = chunk.to_vec();
let inner_config = CircuitConfig::standard_recursion_config();
let mut inner_builder = CircuitBuilder::<F, D>::new(inner_config);
let mut inner_pw = PartialWitness::new();
simple_recursion::aggregate_sampling_proofs(
&proofs_chunk,
&vd,
&mut inner_builder,
&mut inner_pw,
)?;
let inner_data = inner_builder.build::<C>();
let proof = inner_data.prove(inner_pw)?;
new_proofs.push(proof);
new_circuit_data = Some(inner_data.verifier_data());
}
aggregate_sampling_proofs_tree2(&new_proofs, new_circuit_data.unwrap())
}