From af1c337555909d34752454e36f73d30801f5a6bf Mon Sep 17 00:00:00 2001 From: M Alghazwi Date: Tue, 14 Jan 2025 23:03:00 +0100 Subject: [PATCH] fix and refactor benches --- proof-input/src/gen_input.rs | 13 ++ workflow/Cargo.toml | 14 +- workflow/benches/cyclic_recursion.rs | 71 ++++++++ .../{safe_circuit.rs => merkle_circuit.rs} | 14 +- workflow/benches/sample_cells.rs | 34 ++-- workflow/benches/simple_recursion.rs | 100 +++++++----- .../benches/simple_recursion_hashed_pi.rs | 102 ++++++++++++ workflow/benches/simple_tree_recursion.rs | 41 +++-- workflow/benches/tree_recursion1.rs | 153 ++++++++++++++++++ ...ursion_approach2.rs => tree_recursion2.rs} | 55 +++---- workflow/benches/tree_recursion_approach1.rs | 87 ---------- 11 files changed, 488 insertions(+), 196 deletions(-) create mode 100644 workflow/benches/cyclic_recursion.rs rename workflow/benches/{safe_circuit.rs => merkle_circuit.rs} (92%) create mode 100644 workflow/benches/simple_recursion_hashed_pi.rs create mode 100644 workflow/benches/tree_recursion1.rs rename workflow/benches/{tree_recursion_approach2.rs => tree_recursion2.rs} (71%) delete mode 100644 workflow/benches/tree_recursion_approach1.rs diff --git a/proof-input/src/gen_input.rs b/proof-input/src/gen_input.rs index b1d854a..d787901 100644 --- a/proof-input/src/gen_input.rs +++ b/proof-input/src/gen_input.rs @@ -11,6 +11,7 @@ use plonky2::iop::witness::PartialWitness; use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData}; use plonky2::plonk::proof::ProofWithPublicInputs; +use codex_plonky2_circuits::circuits::params::CircuitParams; use crate::data_structs::DatasetTree; use crate::sponge::hash_bytes_no_padding; use crate::params::{C, D, F, HF}; @@ -195,6 +196,18 @@ pub fn prove_circuit(data: &CircuitData, pw: &PartialWitness) -> any /// returns exactly M default circuit input pub fn get_m_default_circ_input() -> [SampleCircuitInput; M]{ let params = Params::default().input_params; + // let one_circ_input = gen_testing_circuit_input::(¶ms); + // let circ_input: [SampleCircuitInput; M] = (0..M) + // .map(|_| one_circ_input.clone()) + // .collect::>() + // .try_into().unwrap(); + // circ_input + get_m_circ_input::(params) +} + +/// returns exactly M default circuit input +pub fn get_m_circ_input(params: InputParams) -> [SampleCircuitInput; M]{ + // let params = Params::default().input_params; let one_circ_input = gen_testing_circuit_input::(¶ms); let circ_input: [SampleCircuitInput; M] = (0..M) .map(|_| one_circ_input.clone()) diff --git a/workflow/Cargo.toml b/workflow/Cargo.toml index ed517fa..90cf0b7 100644 --- a/workflow/Cargo.toml +++ b/workflow/Cargo.toml @@ -39,7 +39,7 @@ name = "prove" path = "src/bin/prove.rs" [[bench]] -name = "safe_circuit" +name = "merkle_circuit" harness = false [[bench]] @@ -51,11 +51,19 @@ name = "simple_recursion" harness = false [[bench]] -name = "tree_recursion_approach1" +name = "simple_recursion_hashed_pi" harness = false [[bench]] -name = "tree_recursion_approach2" +name = "cyclic_recursion" +harness = false + +[[bench]] +name = "tree_recursion1" +harness = false + +[[bench]] +name = "tree_recursion2" harness = false [[bench]] diff --git a/workflow/benches/cyclic_recursion.rs b/workflow/benches/cyclic_recursion.rs new file mode 100644 index 0000000..769ce75 --- /dev/null +++ b/workflow/benches/cyclic_recursion.rs @@ -0,0 +1,71 @@ +use criterion::{Criterion, criterion_group, criterion_main}; +use plonky2::plonk::config::GenericConfig; +use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion; +use codex_plonky2_circuits::recursion::cyclic::CyclicCircuit; +use proof_input::params::{C, D, F,HF}; +use proof_input::gen_input::gen_testing_circuit_input; +use proof_input::params::Params; + + +/// Benchmark for building, proving, and verifying the Plonky2 tree recursion circuit. +fn bench_cyclic_recursion(c: &mut Criterion) -> anyhow::Result<()>{ + + let mut group = c.benchmark_group("Cyclic Recursion Benchmark"); + + let mut params = Params::default(); + let inner_sampling_circuit = SamplingRecursion::::new(params.circuit_params); + let mut circ_inputs = vec![]; + for _i in 0..N { + circ_inputs.push(gen_testing_circuit_input::(¶ms.input_params)); + } + + let mut cyclic_circ = CyclicCircuit::::build_circuit::(inner_sampling_circuit.clone())?; + + // Building Phase + group.bench_function("build cyclic circuit", |b| { + b.iter(|| { + let _cyclic_circ = CyclicCircuit::::build_circuit::(inner_sampling_circuit.clone()); + + }) + }); + + let proof = cyclic_circ.prove_n_layers(circ_inputs.clone())?; + + // Proving Phase + group.bench_function("prove cyclic circuit", |b| { + b.iter(|| { + let _proof = cyclic_circ.prove_n_layers(circ_inputs.clone()); + }) + }); + + println!("num of pi = {}", proof.public_inputs.len()); + println!("pub input: {:?}", proof.public_inputs); + + // Verifying Phase + group.bench_function("verify cyclic circuit proof", |b| { + b.iter(|| { + cyclic_circ.verify_latest_proof(); + }) + }); + + assert!( + cyclic_circ.verify_latest_proof().is_ok(), + "proof verification failed" + ); + + group.finish(); + Ok(()) +} + +fn bench_recursion(c: &mut Criterion){ + const N: usize = 2; // number of proofs to be aggregated + bench_cyclic_recursion::(c); +} + +/// Criterion benchmark group +criterion_group!{ + name = recursion; + config = Criterion::default().sample_size(10); + targets = bench_recursion +} +criterion_main!(recursion); diff --git a/workflow/benches/safe_circuit.rs b/workflow/benches/merkle_circuit.rs similarity index 92% rename from workflow/benches/safe_circuit.rs rename to workflow/benches/merkle_circuit.rs index d5248fc..5e1481c 100644 --- a/workflow/benches/safe_circuit.rs +++ b/workflow/benches/merkle_circuit.rs @@ -1,7 +1,8 @@ use criterion::{criterion_group, criterion_main, Criterion}; use anyhow::Result; -use codex_plonky2_circuits::{merkle_tree::merkle_safe::MerkleTree, circuits::merkle_circuit::MerkleTreeCircuit}; +use proof_input::merkle_tree::merkle_safe::{MerkleTree}; +// use codex_plonky2_circuits::{circuits::merkle_circuit::MerkleTreeCircuit}; use plonky2::field::types::Field; use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, Hasher, PoseidonGoldilocksConfig}; @@ -11,12 +12,11 @@ use plonky2::hash::poseidon::PoseidonHash; use plonky2::field::extension::Extendable; use plonky2::hash::hash_types::RichField; use plonky2_poseidon2::poseidon2_hash::poseidon2::{Poseidon2, Poseidon2Hash}; -use std::marker::PhantomData; use plonky2::plonk::circuit_builder::CircuitBuilder; -use codex_plonky2_circuits::merkle_tree::merkle_safe::MerkleProof; -use plonky2_field::goldilocks_field::GoldilocksField; -use proof_input::recursion::merkle_circuit; -use proof_input::recursion::merkle_circuit::{assign_witness, MerkleTreeCircuitInput}; +// use codex_plonky2_circuits::merkle_tree::merkle_safe::MerkleProof; +// use plonky2_field::goldilocks_field::GoldilocksField; +use proof_input::merkle_tree::merkle_circuit; +use proof_input::merkle_tree::merkle_circuit::{assign_witness, MerkleTreeCircuitInput}; use proof_input::utils::usize_to_bits_le; macro_rules! pretty_print { @@ -109,7 +109,7 @@ fn build_circuit< let mut pw = PartialWitness::new(); for i in 0..circ_inputs.len() { - let (mut targets, reconstructed_root_target) = merkle_circuit::build_circuit(&mut builder, max_depth); + let (mut targets, reconstructed_root_target) = merkle_circuit::build_circuit::(&mut builder, max_depth); // expected Merkle root let expected_root_target = builder.add_virtual_hash(); diff --git a/workflow/benches/sample_cells.rs b/workflow/benches/sample_cells.rs index cfe0f72..7901ea5 100644 --- a/workflow/benches/sample_cells.rs +++ b/workflow/benches/sample_cells.rs @@ -6,18 +6,20 @@ use plonky2::plonk::circuit_data::CircuitConfig; use plonky2::plonk::config::GenericConfig; use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit; -use codex_plonky2_circuits::circuits::params::CircuitParams; use proof_input::gen_input::gen_testing_circuit_input; -use proof_input::params::{D, C, F, Params, TestParams}; +use proof_input::params::{D, C, F, HF, Params}; /// Benchmark for building, proving, and verifying the Plonky2 circuit. -fn bench_prove_verify(c: &mut Criterion) { - // get default parameters - let mut test_params = TestParams::default(); - test_params.n_samples = 100; +fn bench_prove_verify(c: &mut Criterion) -> Result<()>{ - let mut circuit_params = CircuitParams::default(); - circuit_params.n_samples = 100; + let n_samples = 100; + // get default parameters + let params = Params::default(); + let mut test_params = params.input_params; + test_params.n_samples = n_samples; + + let mut circuit_params = params.circuit_params; + circuit_params.n_samples = n_samples; // gen the circuit input let circ_input = gen_testing_circuit_input::(&test_params); @@ -27,25 +29,24 @@ fn bench_prove_verify(c: &mut Criterion) { let mut builder = CircuitBuilder::::new(config); // Initialize the SampleCircuit with the parameters - let circ = SampleCircuit::new(circuit_params.clone()); - let mut targets = circ.sample_slot_circuit_with_public_input(&mut builder); + let circ = SampleCircuit::::new(circuit_params.clone()); + let targets = circ.sample_slot_circuit_with_public_input(&mut builder)?; // Create a PartialWitness and assign the circuit input let mut pw = PartialWitness::new(); - circ.sample_slot_assign_witness(&mut pw, &mut targets, circ_input.clone()); + circ.sample_slot_assign_witness(&mut pw, &targets, &circ_input.clone()); // Benchmark Group: Separate benchmarks for building, proving, and verifying - let mut group = c.benchmark_group("Prove and Verify"); + let mut group = c.benchmark_group("Sampling Circuit Benchmark"); // Benchmark the Circuit Building Phase group.bench_function("Build Circuit", |b| { b.iter(|| { let config = CircuitConfig::standard_recursion_config(); let mut local_builder = CircuitBuilder::::new(config); - let local_circ = SampleCircuit::new(circuit_params.clone()); - let mut local_targets = local_circ.sample_slot_circuit_with_public_input(&mut local_builder); - let mut local_pw = PartialWitness::new(); - local_circ.sample_slot_assign_witness(&mut local_pw, &mut local_targets, circ_input.clone()); + let local_targets = targets.clone(); + let mut local_pw = pw.clone(); + circ.sample_slot_assign_witness(&mut local_pw, &local_targets, &circ_input.clone()); let _data = local_builder.build::(); }) }); @@ -91,6 +92,7 @@ fn bench_prove_verify(c: &mut Criterion) { }); group.finish(); + Ok(()) } /// Criterion benchmark group diff --git a/workflow/benches/simple_recursion.rs b/workflow/benches/simple_recursion.rs index 070d30f..2463bb5 100644 --- a/workflow/benches/simple_recursion.rs +++ b/workflow/benches/simple_recursion.rs @@ -1,86 +1,108 @@ use anyhow::Result; use criterion::{criterion_group, criterion_main, Criterion}; +use plonky2::hash::hash_types::HashOut; use plonky2::iop::witness::PartialWitness; use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData}; +use plonky2::plonk::circuit_data::{CircuitConfig}; use plonky2::plonk::config::GenericConfig; -use codex_plonky2_circuits::recursion::simple::simple_recursion::aggregate_sampling_proofs; -use proof_input::params::{D, C, F, Params, TestParams}; +use plonky2_field::types::Field; +use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion; +use codex_plonky2_circuits::recursion::simple::simple_recursion::{SimpleRecursionCircuit, SimpleRecursionInput}; +use proof_input::params::{D, C, F, HF, Params}; use proof_input::gen_input::{build_circuit, prove_circuit}; /// Benchmark for building, proving, and verifying the Plonky2 recursion circuit. /// Simple recursion approach - verify N proofs in-circuit -fn bench_recursion(c: &mut Criterion) { - // num of inner proofs - let num_of_inner_proofs = 4; - // number of samples in each proof - let n_samples = 10; +fn bench_simple_recursion(c: &mut Criterion) -> Result<()>{ + let mut group = c.benchmark_group("Simple Recursion Benchmark"); - let mut data: Option> = None; + // number of samples in each proof + let n_samples = 5; + // params + let mut circ_params = Params::default().circuit_params; + circ_params.n_samples = n_samples; + // number of inner proofs: + const N_INNER: usize = 4; + + let (data, pw) = build_circuit(n_samples, 3)?; + let proof = prove_circuit(&data, &pw)?; // get proofs - let mut proofs_with_pi = vec![]; - for i in 0..num_of_inner_proofs{ - // build the circuit - let (data_i, pw) = build_circuit(n_samples, 3).unwrap(); - proofs_with_pi.push(prove_circuit(&data_i, &pw).unwrap()); - data = Some(data_i); - } + let mut proofs_with_pi = (0..N_INNER).map(|i| proof.clone()).collect::>(); - // Create the circuit - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - // Create a PartialWitness - let mut pw_agg = PartialWitness::new(); - // aggregate proofs - let data = data.unwrap(); - let vd = data.verifier_data(); - aggregate_sampling_proofs(&proofs_with_pi.clone(), &vd, &mut builder, &mut pw_agg); + println!("inner circuit size = {:?}", data.common.degree_bits()); - let mut group = c.benchmark_group("bench recursion"); + // careful here, the sampling recursion is the default so proofs should be for circuit + // with default params + let sampling_inner_circ = SamplingRecursion::::new(circ_params); + let rec_circuit = SimpleRecursionCircuit::::new(sampling_inner_circ); group.bench_function("Build Circuit", |b| { b.iter(|| { // Create the circuit let local_config = CircuitConfig::standard_recursion_config(); let mut local_builder = CircuitBuilder::::new(local_config); - // Create a PartialWitness - let mut local_pw_agg = PartialWitness::new(); // aggregate proofs - aggregate_sampling_proofs(&proofs_with_pi.clone(), &vd, &mut local_builder, &mut local_pw_agg); - let _data = local_builder.build::(); + let _loc_targets = rec_circuit.build_circuit(&mut local_builder).unwrap(); + let _agg_data = local_builder.build::(); }) }); + + // Create the circuit + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + // Create a PartialWitness + let mut pw = PartialWitness::new(); + + let targets = rec_circuit.build_circuit(&mut builder)?; let agg_data = builder.build::(); - println!("Circuit size (degree bits): {:?}", agg_data.common.degree_bits()); - println!("Number of gates used: {}", agg_data.common.gates.len()); + + println!("agg circuit size = {:?}", agg_data.common.degree_bits()); + + let mut default_entropy = HashOut::ZERO; + default_entropy.elements[0] = F::from_canonical_u64(1234567); + + let w = SimpleRecursionInput{ + proofs: proofs_with_pi, + verifier_data: data.verifier_data(), + entropy: default_entropy, + }; + + rec_circuit.assign_witness(&mut pw,&targets,w)?; group.bench_function("Prove Circuit", |b| { b.iter(|| { - let local_pw = pw_agg.clone(); + let local_pw = pw.clone(); agg_data.prove(local_pw).expect("Failed to prove circuit") }) }); - let agg_proof_with_pis = agg_data.prove(pw_agg.clone()).expect("Failed to prove circuit"); - let agg_verifier_data = agg_data.verifier_data(); - - println!("Proof size: {} bytes", agg_proof_with_pis.to_bytes().len()); + let proof = agg_data.prove(pw)?; + println!("Proof size: {} bytes", proof.to_bytes().len()); + println!("public input count = {:?}", proof.public_inputs.len()); + // Verify the proof + let verifier_data = agg_data.verifier_data(); group.bench_function("Verify Proof", |b| { b.iter(|| { - agg_verifier_data.verify(agg_proof_with_pis.clone()).expect("Failed to verify proof"); + verifier_data.clone().verify(proof.clone()).expect("Failed to verify proof"); }) }); + assert!( + verifier_data.verify(proof).is_ok(), + "proof verification failed" + ); + group.finish(); + Ok(()) } /// Criterion benchmark group criterion_group!{ name = recursion; config = Criterion::default().sample_size(10); - targets = bench_recursion + targets = bench_simple_recursion } criterion_main!(recursion); diff --git a/workflow/benches/simple_recursion_hashed_pi.rs b/workflow/benches/simple_recursion_hashed_pi.rs new file mode 100644 index 0000000..080ac65 --- /dev/null +++ b/workflow/benches/simple_recursion_hashed_pi.rs @@ -0,0 +1,102 @@ +use anyhow::Result; +use criterion::{criterion_group, criterion_main, Criterion}; +use plonky2::iop::witness::PartialWitness; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::circuit_data::{CircuitConfig}; +use plonky2::plonk::config::GenericConfig; +use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion; +use codex_plonky2_circuits::recursion::simple::simple_recursion_hashed_pi::{SimpleRecursionCircuitHashedPI, SimpleRecursionInputHashedPI}; +use proof_input::params::{D, C, F, HF, Params}; +use proof_input::gen_input::{build_circuit, prove_circuit}; + +/// Benchmark for building, proving, and verifying the Plonky2 recursion circuit. +/// Simple recursion approach - verify N proofs in-circuit +fn bench_recursion(c: &mut Criterion) -> Result<()>{ + let mut group = c.benchmark_group("Simple Recursion With Hashed Public Input Benchmark"); + + // number of samples in each proof + let n_samples = 5; + // params + let mut circ_params = Params::default().circuit_params; + circ_params.n_samples = n_samples; + // number of inner proofs: + const N_INNER: usize = 4; + + let (data, pw) = build_circuit(n_samples, 3)?; + let proof = prove_circuit(&data, &pw)?; + + // get proofs + let mut proofs_with_pi = (0..N_INNER).map(|i| proof.clone()).collect::>(); + + println!("inner circuit size = {:?}", data.common.degree_bits()); + + // careful here, the sampling recursion is the default so proofs should be for circuit + // with default params + let sampling_inner_circ = SamplingRecursion::::new(circ_params); + let rec_circuit = SimpleRecursionCircuitHashedPI::::new(sampling_inner_circ); + + group.bench_function("Build Circuit", |b| { + b.iter(|| { + // Create the circuit + let local_config = CircuitConfig::standard_recursion_config(); + let mut local_builder = CircuitBuilder::::new(local_config); + // aggregate proofs + let _loc_targets = rec_circuit.build_circuit::(&mut local_builder).unwrap(); + let _agg_data = local_builder.build::(); + }) + }); + + + // Create the circuit + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + // Create a PartialWitness + let mut pw = PartialWitness::new(); + + let targets = rec_circuit.build_circuit::(&mut builder)?; + let agg_data = builder.build::(); + + println!("agg circuit size = {:?}", agg_data.common.degree_bits()); + + let w = SimpleRecursionInputHashedPI{ + proofs: proofs_with_pi, + verifier_data: data.verifier_data(), + }; + + rec_circuit.assign_witness(&mut pw,&targets,w)?; + + group.bench_function("Prove Circuit", |b| { + b.iter(|| { + let local_pw = pw.clone(); + agg_data.prove(local_pw).expect("Failed to prove circuit") + }) + }); + + let proof = agg_data.prove(pw)?; + println!("Proof size: {} bytes", proof.to_bytes().len()); + println!("public input count = {:?}", proof.public_inputs.len()); + + // Verify the proof + let verifier_data = agg_data.verifier_data(); + group.bench_function("Verify Proof", |b| { + b.iter(|| { + verifier_data.clone().verify(proof.clone()).expect("Failed to verify proof"); + }) + }); + + assert!( + verifier_data.verify(proof).is_ok(), + "proof verification failed" + ); + + group.finish(); + Ok(()) +} + +/// Criterion benchmark group +criterion_group!{ + name = recursion; + config = Criterion::default().sample_size(10); + targets = bench_recursion +} +criterion_main!(recursion); diff --git a/workflow/benches/simple_tree_recursion.rs b/workflow/benches/simple_tree_recursion.rs index 504a1e4..0a30b3f 100644 --- a/workflow/benches/simple_tree_recursion.rs +++ b/workflow/benches/simple_tree_recursion.rs @@ -2,36 +2,42 @@ use criterion::{Criterion, criterion_group, criterion_main}; use plonky2::plonk::circuit_data::VerifierCircuitData; use plonky2::plonk::config::GenericConfig; use plonky2::plonk::proof::ProofWithPublicInputs; -use codex_plonky2_circuits::recursion::simple::simple_tree_recursion::aggregate_sampling_proofs_tree2; -use proof_input::params::{C, D, F}; +use codex_plonky2_circuits::recursion::simple::simple_tree_recursion::aggregate_sampling_proofs_tree; +use proof_input::params::{C, D, F, HF, Params}; use proof_input::gen_input::{build_circuit, prove_circuit}; /// Benchmark for building, proving, and verifying the Plonky2 recursion circuit. -fn bench_tree_recursion(c: &mut Criterion) { - // num of inner proofs - let num_of_inner_proofs = 4; - // number of samples in each proof - let n_samples = 10; +fn bench_tree_recursion(c: &mut Criterion) -> anyhow::Result<()>{ - let (data, pw) = build_circuit(n_samples, 3).unwrap(); + let mut group = c.benchmark_group("Simple Tree Recursion Benchmark"); + + // number of samples in each proof + let n_samples = 5; + // params + let mut circ_params = Params::default().circuit_params; + circ_params.n_samples = n_samples; + // number of inner proofs: + const N_INNER: usize = 4; + // let mut data: Option> = None; + + let (data, pw) = build_circuit(n_samples, 3)?; + let proof = prove_circuit(&data, &pw)?; // get proofs - let mut proofs_with_pi = vec![]; - for i in 0..num_of_inner_proofs{ - proofs_with_pi.push(prove_circuit(&data, &pw).unwrap()); - } - let vd = data.verifier_data(); + let proofs_with_pi = (0..N_INNER).map(|i| proof.clone()).collect::>(); + + println!("inner circuit size = {:?}", data.common.degree_bits()); + - let mut group = c.benchmark_group("bench simple tree recursion"); let mut agg_proof_with_pis: Option> = None; let mut agg_vd: Option> = None; // Benchmark the Circuit Building Phase group.bench_function("build & prove Circuit", |b| { b.iter(|| { - let (agg_p, agg_d) = aggregate_sampling_proofs_tree2(&proofs_with_pi, vd.clone()).unwrap(); - agg_proof_with_pis = Some(agg_p); - agg_vd = Some(agg_d); + let (proof, vd_agg) = aggregate_sampling_proofs_tree::(&proofs_with_pi, data.verifier_data()).unwrap(); + agg_proof_with_pis = Some(proof); + agg_vd = Some(vd_agg); }) }); @@ -47,6 +53,7 @@ fn bench_tree_recursion(c: &mut Criterion) { }); group.finish(); + Ok(()) } /// Criterion benchmark group diff --git a/workflow/benches/tree_recursion1.rs b/workflow/benches/tree_recursion1.rs new file mode 100644 index 0000000..d0b7868 --- /dev/null +++ b/workflow/benches/tree_recursion1.rs @@ -0,0 +1,153 @@ +use anyhow::{anyhow, Result}; +use criterion::{Criterion, criterion_group, criterion_main}; +use plonky2::plonk::config::GenericConfig; +use plonky2::plonk::proof::ProofWithPublicInputs; +use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion; +use codex_plonky2_circuits::recursion::tree1::{tree_circuit::TreeRecursion}; +use proof_input::params::{C, D, F, HF, Params}; +use proof_input::gen_input::{get_m_circ_input}; + + +/// Benchmark for building, proving, and verifying the approach1 Plonky2 tree recursion circuit. +fn bench_node_recursion(c: &mut Criterion) -> Result<()>{ + + let mut group = c.benchmark_group("Tree Recursion - Approach 1 Benchmark"); + + // number of samples in each proof + let n_samples = 5; + // params + let mut circ_params = Params::default().circuit_params; + circ_params.n_samples = n_samples; + let mut input_params = Params::default().input_params; + input_params.n_samples = n_samples; + + let inner_sampling_circuit = SamplingRecursion::::new(circ_params); + + let circ_input = get_m_circ_input::(input_params); + + // Building Phase + group.bench_function("build", |b| { + b.iter(|| { + let _tree_circ = TreeRecursion::::build::(inner_sampling_circuit.clone()); + }) + }); + + let mut tree_circ = TreeRecursion::::build::(inner_sampling_circuit)?; + println!("tree circuit size = {:?}", tree_circ.node_circ.cyclic_circuit_data.common.degree_bits()); + + // prove Phase + group.bench_function("prove with leaf only", |b| { + b.iter(|| { + let _proof = tree_circ.prove(&circ_input,None, true); + }) + }); + + let proof = tree_circ.prove(&circ_input,None, true)?; + println!("Proof size: {} bytes", proof.to_bytes().len()); + println!("num of pi = {}", proof.public_inputs.len()); + + // make N node proofs + let node_proofs: [ProofWithPublicInputs; N] = (0..N) + .map(|_| { + proof.clone() + }) + .collect::>() + .try_into() + .map_err(|_| anyhow!("Expected exactly M inner circuits")).unwrap(); + + // prove Phase for node leaf and node proofs + group.bench_function("prove with leaf and node", |b| { + b.iter(|| { + let _proof = tree_circ.prove(&circ_input,Some(node_proofs.clone()), true); + }) + }); + + // Verifying Phase for node leaf and node proofs + group.bench_function("Verify Proof with leaf and node proofs", |b| { + b.iter(|| { + tree_circ.verify_proof(proof.clone()).expect("Failed to verify proof"); + }) + }); + + assert!( + tree_circ.verify_proof(proof).is_ok(), + "proof verification failed" + ); + + group.finish(); + Ok(()) +} + +fn bench_tree_recursion(c: &mut Criterion) -> Result<()>{ + let mut group = c.benchmark_group("bench tree recursion - approach 1"); + + const M: usize = 1; + const N: usize = 2; + const DEPTH: usize = 3; + + const TOTAL_INPUT: usize = (N.pow(DEPTH as u32) - 1) / (N - 1); + + // number of samples in each proof + let n_samples = 5; + // params + let mut circ_params = Params::default().circuit_params; + circ_params.n_samples = n_samples; + let mut input_params = Params::default().input_params; + input_params.n_samples = n_samples; + + let inner_sampling_circuit = SamplingRecursion::::new(circ_params); + + let circ_input = get_m_circ_input::(input_params).to_vec(); + + // Building Phase + group.bench_function("build", |b| { + b.iter(|| { + let _tree_circ = TreeRecursion::::build::(inner_sampling_circuit.clone()).unwrap(); + }) + }); + + let mut tree_circ = TreeRecursion::::build::(inner_sampling_circuit)?; + println!("tree circuit size = {:?}", tree_circ.node_circ.cyclic_circuit_data.common.degree_bits()); + + // prove Phase + group.bench_function("prove tree", |b| { + b.iter(|| { + let _proof = tree_circ.prove_tree(circ_input.clone(),DEPTH).unwrap(); + }) + }); + + let proof = tree_circ.prove_tree(circ_input,DEPTH)?; + println!("Proof size: {} bytes", proof.to_bytes().len()); + println!("num of pi = {}", proof.public_inputs.len()); + + // Verifying Phase for node leaf and node proofs + group.bench_function("Verify final proof", |b| { + b.iter(|| { + tree_circ.verify_proof(proof.clone()).expect("Failed to verify proof"); + }) + }); + + assert!( + tree_circ.verify_proof(proof).is_ok(), + "proof verification failed" + ); + + group.finish(); + Ok(()) +} + +fn bench_tree_recursion_approach1(c: &mut Criterion){ + const M: usize = 1; + const N: usize = 2; + bench_node_recursion::(c); + bench_tree_recursion(c); +} + + +/// Criterion benchmark group +criterion_group!{ + name = recursion; + config = Criterion::default().sample_size(10); + targets = bench_tree_recursion_approach1 +} +criterion_main!(recursion); diff --git a/workflow/benches/tree_recursion_approach2.rs b/workflow/benches/tree_recursion2.rs similarity index 71% rename from workflow/benches/tree_recursion_approach2.rs rename to workflow/benches/tree_recursion2.rs index 1025a27..2828a52 100644 --- a/workflow/benches/tree_recursion_approach2.rs +++ b/workflow/benches/tree_recursion2.rs @@ -1,37 +1,36 @@ use criterion::{Criterion, criterion_group, criterion_main}; use plonky2::iop::witness::PartialWitness; use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::circuit_data::{CircuitConfig, VerifierCircuitData}; +use plonky2::plonk::circuit_data::{CircuitConfig}; use plonky2::plonk::config::GenericConfig; use plonky2::plonk::proof::ProofWithPublicInputs; -use codex_plonky2_circuits::circuits::params::CircuitParams; -use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit, SampleCircuitInput}; -use codex_plonky2_circuits::recursion::leaf_circuit::{LeafCircuit, LeafInput}; +use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit}; +use codex_plonky2_circuits::recursion::tree2::leaf_circuit::{LeafCircuit, LeafInput}; use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion; -use codex_plonky2_circuits::recursion::tree_recursion2::{NodeCircuit, TreeRecursion}; -use codex_plonky2_circuits::params::{C, D, F}; +use codex_plonky2_circuits::recursion::tree2::{tree_circuit::TreeRecursion}; +use proof_input::params::{C, D, F,HF}; use proof_input::gen_input::gen_testing_circuit_input; -use proof_input::params::TestParams; +use proof_input::params::Params; /// Benchmark for building, proving, and verifying the Plonky2 tree recursion circuit. -fn bench_tree_recursion(c: &mut Criterion){ +fn bench_tree_recursion(c: &mut Criterion) -> anyhow::Result<()>{ - let mut group = c.benchmark_group("bench tree recursion - approach 2"); + let mut group = c.benchmark_group("Tree Recursion - Approach 2 Benchmark"); //------------ sampling inner circuit ---------------------- // Circuit that does the sampling - default input let config = CircuitConfig::standard_recursion_config(); let mut sampling_builder = CircuitBuilder::::new(config); - let mut params = TestParams::default(); - let one_circ_input = gen_testing_circuit_input::(¶ms); - let samp_circ = SampleCircuit::::new(CircuitParams::default()); - let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut sampling_builder); + let mut params = Params::default(); + let one_circ_input = gen_testing_circuit_input::(¶ms.input_params); + let samp_circ = SampleCircuit::::new(params.circuit_params); + let inner_tar = samp_circ.sample_slot_circuit_with_public_input(&mut sampling_builder)?; // get generate a sampling proof let mut pw = PartialWitness::::new(); samp_circ.sample_slot_assign_witness(&mut pw,&inner_tar,&one_circ_input); let inner_data = sampling_builder.build::(); - let inner_proof = inner_data.prove(pw.clone()).unwrap(); + let inner_proof = inner_data.prove(pw.clone())?; // Building Phase group.bench_function("build inner circuit", |b| { @@ -55,8 +54,8 @@ fn bench_tree_recursion(c: &mut Criterion){ // ------------------- leaf -------------------- // leaf circuit that verifies the sampling proof - let inner_circ = SamplingRecursion::default(); - let leaf_circuit = LeafCircuit::new(inner_circ); + let inner_circ = SamplingRecursion::::new(Params::default().circuit_params); + let leaf_circuit = LeafCircuit::::new(inner_circ); let leaf_in = LeafInput{ inner_proof, @@ -64,7 +63,7 @@ fn bench_tree_recursion(c: &mut Criterion){ }; let config = CircuitConfig::standard_recursion_config(); let mut leaf_builder = CircuitBuilder::::new(config); - let leaf_targets = leaf_circuit.build(&mut leaf_builder).unwrap(); + let leaf_targets = leaf_circuit.build::(&mut leaf_builder)?; let leaf_circ_data = leaf_builder.build::(); // Building Phase @@ -72,14 +71,14 @@ fn bench_tree_recursion(c: &mut Criterion){ b.iter(|| { let config = CircuitConfig::standard_recursion_config(); let mut leaf_builder = CircuitBuilder::::new(config); - let _leaf_targets = leaf_circuit.build(&mut leaf_builder).unwrap(); + let _leaf_targets = leaf_circuit.build::(&mut leaf_builder).unwrap(); let _leaf_circ_data = leaf_builder.build::(); }) }); let mut pw = PartialWitness::::new(); - leaf_circuit.assign_targets(&mut pw, &leaf_targets, &leaf_in); - let leaf_proof = leaf_circ_data.prove(pw.clone()).unwrap(); + leaf_circuit.assign_targets::(&mut pw, &leaf_targets, &leaf_in)?; + let leaf_proof = leaf_circ_data.prove(pw.clone())?; // Proving Phase group.bench_function("prove leaf circuit", |b| { @@ -94,17 +93,17 @@ fn bench_tree_recursion(c: &mut Criterion){ // ------------- Node/tree circuit ------------------ // node circuit that verifies leafs or itself - let mut tree = TreeRecursion::::build().unwrap(); + let mut tree = TreeRecursion::::build::<_,HF>(leaf_circuit.clone())?; // Building phase group.bench_function("build tree circuit", |b| { b.iter(|| { - let _tree = TreeRecursion::::build(); + let _tree = TreeRecursion::::build::<_,HF>(leaf_circuit.clone()); }) }); - let leaf_proofs: Vec> = (0..N) + let leaf_proofs: Vec> = (0..K) .map(|_| { leaf_proof.clone() }) @@ -123,24 +122,26 @@ fn bench_tree_recursion(c: &mut Criterion){ println!("tree circuit - num of public input = {}", tree_root_proof.public_inputs.len()); assert!( - tree.verify_proof(tree_root_proof.clone()).is_ok(), + tree.verify_proof(tree_root_proof.clone(), N==K).is_ok(), "proof verification failed" ); // Verifying Phase group.bench_function("verify tree circuit", |b| { b.iter(|| { - tree.verify_proof(tree_root_proof.clone()).expect("verify fail"); + tree.verify_proof(tree_root_proof.clone(), N==K).expect("verify fail"); }) }); group.finish(); + Ok(()) } fn bench_tree_recursion_approach2(c: &mut Criterion){ - const N: usize = 2; - bench_tree_recursion::(c); + const N: usize = 2; // number of child nodes + const K: usize = 2; // number of proofs to be aggregated in the tree + bench_tree_recursion::(c); } /// Criterion benchmark group diff --git a/workflow/benches/tree_recursion_approach1.rs b/workflow/benches/tree_recursion_approach1.rs deleted file mode 100644 index 70d601a..0000000 --- a/workflow/benches/tree_recursion_approach1.rs +++ /dev/null @@ -1,87 +0,0 @@ -use anyhow::anyhow; -use criterion::{Criterion, criterion_group, criterion_main}; -use plonky2::plonk::config::GenericConfig; -use plonky2::plonk::proof::ProofWithPublicInputs; -use codex_plonky2_circuits::recursion::circuits::sampling_inner_circuit::SamplingRecursion; -use codex_plonky2_circuits::recursion::tree_recursion::{NodeCircuit, TreeRecursion}; -use codex_plonky2_circuits::params::{C, D, F}; -use proof_input::gen_input::get_m_default_circ_input; - - -/// Benchmark for building, proving, and verifying the approach1 Plonky2 tree recursion circuit. -fn bench_tree_recursion(c: &mut Criterion) { - - let mut group = c.benchmark_group("bench tree recursion - approach 1"); - - let inner_sampling_circuit = SamplingRecursion::default(); - - let node_circ = NodeCircuit::<_,M,N>::new(inner_sampling_circuit); - let mut tree_circ = TreeRecursion::new(node_circ); - let circ_input = get_m_default_circ_input::(); - - // Building Phase - group.bench_function("build", |b| { - b.iter(|| { - tree_circ.build(); - }) - }); - - let mut proof: Option> = None; - - // prove Phase - group.bench_function("prove with leaf only", |b| { - b.iter(|| { - proof = Some(tree_circ.prove(&circ_input,None, true).unwrap()); - }) - }); - - // Verifying Phase for proof with leaf - group.bench_function("Verify proof with only leaf", |b| { - b.iter(|| { - tree_circ.verify_proof(proof.clone().unwrap()).expect("Failed to verify proof"); - }) - }); - - // make N node proofs - let node_proofs: [ProofWithPublicInputs; N] = (0..N) - .map(|_| { - proof.clone().unwrap() - }) - .collect::>() - .try_into() - .map_err(|_| anyhow!("Expected exactly M inner circuits")).unwrap(); - - // prove Phase for node leaf and node proofs - group.bench_function("prove with leaf and node", |b| { - b.iter(|| { - proof = Some(tree_circ.prove(&circ_input,Some(node_proofs.clone()), true).unwrap()); - }) - }); - - // Verifying Phase for node leaf and node proofs - group.bench_function("Verify Proof with leaf and node proofs", |b| { - b.iter(|| { - tree_circ.verify_proof(proof.clone().unwrap()).expect("Failed to verify proof"); - }) - }); - - // print circuit size - let tree_common_data = tree_circ.node_circ.cyclic_circuit_data.unwrap().common; - println!("Circuit size (degree bits): {:?}", tree_common_data.degree_bits() ); - - group.finish(); -} - -fn bench_tree_recursion_approach1(c: &mut Criterion){ - const M: usize = 1; - const N: usize = 2; - bench_tree_recursion::(c); -} - -/// Criterion benchmark group -criterion_group!{ - name = recursion; - config = Criterion::default().sample_size(10); - targets = bench_tree_recursion_approach1 -} -criterion_main!(recursion);