#[path = "circuits/aggregatable/poseidon_preimage.rs"]
mod aggregatable_poseidon_preimage;
#[path = "circuits/aggregatable/sha_preimage.rs"]
mod aggregatable_sha_preimage;
use std::time::Instant;
use aggregatable_poseidon_preimage::PoseidonPreimageCircuit as PoseidonCircuit;
use aggregatable_sha_preimage::AggregatableShaPreimageCircuit as ShaCircuit;
use midnight_aggregation::multi_circuit_aggregator::{
AggregationWitness, InnerCircuitsContext, ProofAggregation,
};
use midnight_circuits::{
hash::poseidon::PoseidonState,
verifier::{BlstrsEmulation, SelfEmulation},
};
use midnight_zk_stdlib::{prove, setup_pk, setup_vk, utils::plonk_api::filecoin_srs, ZkStdLibArch};
use rand::rngs::OsRng;
type F = <BlstrsEmulation as SelfEmulation>::F;
fn inner_arch() -> ZkStdLibArch {
ZkStdLibArch {
sha2_256: true,
poseidon: true,
..ZkStdLibArch::default()
}
}
fn main() {
const IVC_K: u32 = 19;
const INNER_K: u32 = 13;
let inner_srs = filecoin_srs(INNER_K);
let inner_ctx = InnerCircuitsContext::new(inner_arch(), INNER_K, inner_srs.verifier_params());
let aggregator_srs = filecoin_srs(IVC_K);
let start = Instant::now();
let (mut aggregator, verifier) = ProofAggregation::setup(aggregator_srs, IVC_K, inner_ctx);
println!("Aggregator setup completed in {:.2?}\n", start.elapsed());
let sha_vk = setup_vk(&inner_srs, &ShaCircuit);
let sha_pk = setup_pk(&ShaCircuit, &sha_vk);
let (sha_x, sha_w) = aggregatable_sha_preimage::random_instance();
let inner_proof = prove::<ShaCircuit, PoseidonState<F>>(
&inner_srs,
&sha_pk,
&ShaCircuit,
&sha_x,
sha_w,
OsRng,
)
.expect("SHA-256 proof generation should not fail");
let witness = AggregationWitness::new::<ShaCircuit>(sha_vk.clone(), sha_x, inner_proof);
let start = Instant::now();
aggregator.aggregate(witness).unwrap();
println!("Aggregate a SHA2-256 proof: {:.2?}", start.elapsed());
let poseidon_vk = setup_vk(&inner_srs, &PoseidonCircuit);
let poseidon_pk = setup_pk(&PoseidonCircuit, &poseidon_vk);
let (poseidon_x, poseidon_w) = aggregatable_poseidon_preimage::random_instance();
let inner_proof = prove::<PoseidonCircuit, PoseidonState<F>>(
&inner_srs,
&poseidon_pk,
&PoseidonCircuit,
&poseidon_x,
poseidon_w,
OsRng,
)
.expect("Poseidon proof generation should not fail");
let witness =
AggregationWitness::new::<PoseidonCircuit>(poseidon_vk.clone(), poseidon_x, inner_proof);
let start = Instant::now();
aggregator.aggregate(witness).unwrap();
println!("Aggregate a Poseidon proof: {:.2?}", start.elapsed());
let (sha_x, sha_w) = aggregatable_sha_preimage::random_instance();
let inner_proof = prove::<ShaCircuit, PoseidonState<F>>(
&inner_srs,
&sha_pk,
&ShaCircuit,
&sha_x,
sha_w,
OsRng,
)
.expect("SHA-256 proof generation should not fail");
let witness = AggregationWitness::new::<ShaCircuit>(sha_vk, sha_x, inner_proof);
let start = Instant::now();
let proof = aggregator.aggregate(witness).unwrap();
println!("Aggregate a SHA2-256 proof: {:.2?}", start.elapsed());
let start = Instant::now();
let instance = aggregator.instance();
verifier.verify_aggregation(&instance, &proof).unwrap();
println!("\nVerification: {:.2?}", start.elapsed());
let claims = instance.state().claims();
println!(
"\nAggregated {} proofs from 2 different circuits:",
claims.len()
);
for (i, claim) in claims.iter().enumerate() {
println!(
" {i}: vk={:?}, statement={:?}",
claim.vk.vk().transcript_repr(),
claim.statement,
);
}
}