diff --git a/workflow/benches/compression.rs b/workflow/benches/compression.rs index 965e04c..ccb67be 100644 --- a/workflow/benches/compression.rs +++ b/workflow/benches/compression.rs @@ -1,13 +1,14 @@ use anyhow::{anyhow, Result}; -use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use criterion::{criterion_group, criterion_main, Criterion}; use plonky2::gates::noop::NoopGate; use plonky2::hash::hash_types::HashOut; use plonky2::iop::witness::{PartialWitness, WitnessWrite}; use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::circuit_data::CircuitConfig; -use plonky2::plonk::config::GenericConfig; +use plonky2::plonk::circuit_data::{CircuitConfig, VerifierCircuitData}; +use codex_plonky2_circuits::circuit_helper::Plonky2Circuit; -use codex_plonky2_circuits::recursion::uniform::compress::CompressionCircuit; +use codex_plonky2_circuits::recursion::uniform::compress::{CompressionCircuit, CompressionInput}; +use codex_plonky2_circuits::recursion::uniform::tree::get_hash_of_verifier_data; use proof_input::params::{D, C, F, HF}; /// Benchmark for building, proving, and verifying the Plonky2 circuit. @@ -33,24 +34,23 @@ fn bench_compression_runtime(c: &mut Criterion, circuit_size: usize) -> Result<( // 2 virtual hashes (8 field elems) as public input - same as in the recursion tree let mut pi = vec![]; - for i in 0..2{ + for _i in 0..2{ pi.push(builder.add_virtual_hash_public_input()); } let inner_data = builder.build::(); println!("inner circuit size = {:?}", inner_data.common.degree_bits()); + let inner_verifier_data: VerifierCircuitData = inner_data.verifier_data(); // prove with dummy public input let mut pw = PartialWitness::::new(); pw.set_hash_target(pi[0], HashOut::::ZERO)?; - pw.set_hash_target(pi[1], HashOut::::ZERO)?; + pw.set_hash_target(pi[1], get_hash_of_verifier_data::(&inner_verifier_data))?; let inner_proof = inner_data.prove(pw)?; // Compression circuit - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - let compression_circ = CompressionCircuit::::new(inner_data.common.clone()); - let compression_targets = compression_circ.build(&mut builder)?; + let compression_circ = CompressionCircuit::::new(inner_data.common.clone(), inner_data.verifier_only.clone()); + let (compression_targets, compression_circ_data) = compression_circ.build_with_standard_config()?; // Benchmark Group let mut group = c.benchmark_group(format!("Compression Circuit Benchmark for inner-proof size = {}", circuit_size)); @@ -58,33 +58,30 @@ fn bench_compression_runtime(c: &mut Criterion, circuit_size: usize) -> Result<( // 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 _compression_targets = compression_circ.build(&mut local_builder); - let _data = local_builder.build::(); + let _compression_targets = compression_circ.build_with_standard_config(); }) }); // Build the circuit once for proving and verifying benchmarks - let compression_circ_data = builder.build::(); println!("compress circuit size = {:?}", compression_circ_data.common.degree_bits()); - let mut pw = PartialWitness::::new(); - compression_circ.assign_targets(&mut pw, &compression_targets, inner_proof, &inner_data.verifier_only)?; + let compression_input = CompressionInput{ + inner_proof, + }; + + let verifier_data: VerifierCircuitData = compression_circ_data.verifier_data(); + let prover_data = compression_circ_data.prover_data(); group.bench_function("Prove Circuit", |b| { - b.iter_batched( - || pw.clone(), - |local_pw| compression_circ_data.prove(local_pw).expect("Failed to prove circuit"), - BatchSize::SmallInput, - ) + b.iter( || + { + let _ = compression_circ.prove(&compression_targets, &compression_input, &prover_data); + }) }); - let proof = compression_circ_data.prove(pw)?; + let proof = compression_circ.prove(&compression_targets, &compression_input, &prover_data)?; println!("Proof size: {} bytes", proof.to_bytes().len()); - let verifier_data = compression_circ_data.verifier_data(); - // Benchmark the Verifying Phase group.bench_function("Verify Proof", |b| { b.iter(|| { @@ -96,10 +93,9 @@ fn bench_compression_runtime(c: &mut Criterion, circuit_size: usize) -> Result<( Ok(()) } -fn bench_compression(c: &mut Criterion) -> Result<()>{ - bench_compression_runtime(c, 13)?; - bench_compression_runtime(c, 14)?; - Ok(()) +fn bench_compression(c: &mut Criterion){ + bench_compression_runtime(c, 13).expect("bench failed"); + bench_compression_runtime(c, 14).expect("bench failed"); } /// Criterion benchmark group diff --git a/workflow/benches/merkle_circuit.rs b/workflow/benches/merkle_circuit.rs index bd6c772..a0258e1 100644 --- a/workflow/benches/merkle_circuit.rs +++ b/workflow/benches/merkle_circuit.rs @@ -2,7 +2,6 @@ use criterion::{criterion_group, criterion_main, Criterion}; use anyhow::Result; use proof_input::merkle_tree::merkle_safe::{MerkleTree}; -use plonky2::field::types::Field; use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData}; use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, Hasher, PoseidonGoldilocksConfig}; use plonky2::iop::witness::{PartialWitness, WitnessWrite}; @@ -28,13 +27,13 @@ fn prepare_data< const D: usize, C: GenericConfig, H: Hasher + AlgebraicHasher, ->(N: usize, max_depth: usize) -> Result<( +>(n: usize, max_depth: usize) -> Result<( Vec>, HashOut, )> { // Generate random leaf data - let nleaves = 16; // Number of leaves - let data = (0..nleaves) + let n_leaves = 16; // Number of leaves + let data = (0..n_leaves) .map(|i| F::from_canonical_u64(i)) .collect::>(); // Hash the data to obtain leaf hashes @@ -53,7 +52,7 @@ fn prepare_data< let tree = MerkleTree::::new(&leaves, zero_hash)?; // Select N leaf indices to prove - let leaf_indices: Vec = (0..N).collect(); + let leaf_indices: Vec = (0..n).collect(); // Get the Merkle proofs for the selected leaves let proofs: Vec<_> = leaf_indices @@ -63,9 +62,9 @@ fn prepare_data< let mut circ_inputs = vec![]; - for i in 0..N{ + for i in 0..n { let path_bits = usize_to_bits_le(leaf_indices[i], max_depth); - let last_index = (nleaves - 1) as usize; + let last_index = (n_leaves - 1) as usize; let last_bits = usize_to_bits_le(last_index, max_depth); let mask_bits = usize_to_bits_le(last_index, max_depth+1); @@ -118,7 +117,7 @@ fn build_circuit< //assign input assign_witness(&mut pw, &mut targets, circ_inputs[i].clone())?; - pw.set_hash_target(expected_root_target, expected_root); + pw.set_hash_target(expected_root_target, expected_root)?; } // Build the circuit @@ -136,9 +135,9 @@ fn merkle_proof_benchmark< let mut group = c.benchmark_group("Merkle Proof Benchmark"); // Prepare the data that will be used in all steps - let N = 5; // Number of leaves to prove + let n = 5; // Number of leaves to prove let max_depth = 4; - let (circ_input, expected_root) = prepare_data::(N, max_depth).unwrap(); + let (circ_input, expected_root) = prepare_data::(n, max_depth).unwrap(); // Benchmark the circuit building group.bench_function("Merkle Proof Build", |b| { diff --git a/workflow/benches/sample_cells.rs b/workflow/benches/sample_cells.rs index f360cf5..1dc7a89 100644 --- a/workflow/benches/sample_cells.rs +++ b/workflow/benches/sample_cells.rs @@ -1,9 +1,7 @@ use anyhow::Result; -use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; -use plonky2::iop::witness::PartialWitness; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::circuit_data::CircuitConfig; -use plonky2::plonk::config::GenericConfig; +use criterion::{criterion_group, criterion_main, Criterion}; +use plonky2::plonk::circuit_data::{CircuitData, VerifierCircuitData}; +use codex_plonky2_circuits::circuit_helper::Plonky2Circuit; use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit; use proof_input::gen_input::gen_testing_circuit_input; @@ -12,14 +10,12 @@ 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) -> Result<()>{ - let n_samples = N; // get default parameters - let params = Params::default(); - let mut test_params = params.input_params; - test_params.n_samples = n_samples; + let mut params = Params::default(); + params.set_n_samples(N); - let mut circuit_params = params.circuit_params; - circuit_params.n_samples = n_samples; + let test_params = params.input_params; + let circuit_params = params.circuit_params; #[cfg(feature = "parallel")] println!("Parallel feature is ENABLED"); @@ -27,62 +23,33 @@ fn bench_prove_verify(c: &mut Criterion) -> Result<()>{ // gen the circuit input let circ_input = gen_testing_circuit_input::(&test_params); - // Create the circuit configuration - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - // Initialize the SampleCircuit with the parameters 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, &targets, &circ_input.clone()); + let (targets, data) = circ.build_with_standard_config()?; + let verifier_data:VerifierCircuitData = data.verifier_data(); + let prover_data = data.prover_data(); // Benchmark Group: Separate benchmarks for building, proving, and verifying - let mut group = c.benchmark_group(format!("Sampling Circuit Benchmark for N= {}", N)); + let mut group = c.benchmark_group(format!("Sampling Circuit Benchmark for N= {} Samples", N)); // 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 _targets = circ.sample_slot_circuit_with_public_input(&mut local_builder); - let _data = local_builder.build::(); + let _: (_, CircuitData) = circ.build_with_standard_config().unwrap(); }) }); - // Build the circuit once for proving and verifying benchmarks - let build_start = std::time::Instant::now(); - let data = builder.build::(); - let build_duration = build_start.elapsed(); - println!("Build time: {:?}", build_duration); - println!("Circuit size (degree bits): {:?}", data.common.degree_bits()); - - // let num_constr: usize = data.common - // .gates - // .iter() - // .map(|gate| gate.0.num_constraints()) - // .sum(); - // - // println!("Number of constraints: {}", num_constr); - // println!("Number of gates used: {}", data.common.gates.len()); + // circuit size + println!("Circuit size (degree bits): {:?}", prover_data.common.degree_bits()); group.bench_function("Prove Circuit", |b| { - b.iter_batched( - || pw.clone(), - |local_pw| data.prove(local_pw).expect("Failed to prove circuit"), - BatchSize::SmallInput, - ) + b.iter(|| { + let _ = circ.prove(&targets, &circ_input, &prover_data); + }) }); // Generate the proof once for verification benchmarking - let prove_start = std::time::Instant::now(); - let proof_with_pis = data.prove(pw.clone()).expect("Failed to prove circuit"); - let prove_duration = prove_start.elapsed(); - println!("prove time: {:?}", prove_duration); - let verifier_data = data.verifier_data(); - + let proof_with_pis = circ.prove(&targets, &circ_input, &prover_data)?; println!("Proof size: {} bytes", proof_with_pis.to_bytes().len()); // Benchmark the Verifying Phase @@ -96,11 +63,10 @@ fn bench_prove_verify(c: &mut Criterion) -> Result<()>{ Ok(()) } -fn bench_sampling(c: &mut Criterion) -> Result<()>{ - bench_prove_verify::<10>(c)?; - bench_prove_verify::<50>(c)?; - bench_prove_verify::<100>(c)?; - Ok(()) +fn bench_sampling(c: &mut Criterion){ + bench_prove_verify::<10>(c).expect("bench failed"); + bench_prove_verify::<50>(c).expect("bench failed"); + bench_prove_verify::<100>(c).expect("bench failed"); } /// Criterion benchmark group diff --git a/workflow/src/bin/aggregate.rs b/workflow/src/bin/aggregate.rs index e2a507c..e6d0c44 100644 --- a/workflow/src/bin/aggregate.rs +++ b/workflow/src/bin/aggregate.rs @@ -1,18 +1,13 @@ use std::env; -use plonky2::plonk::circuit_data::CircuitConfig; -use plonky2::plonk::config::GenericConfig; -use plonky2::iop::witness::PartialWitness; -use plonky2::plonk::circuit_builder::CircuitBuilder; use anyhow::Result; use plonky2::plonk::proof::ProofWithPublicInputs; -use codex_plonky2_circuits::circuits::sample_cells::SampleCircuit; use codex_plonky2_circuits::recursion::uniform::tree::TreeRecursion; -use proof_input::gen_input::gen_testing_circuit_input; -use proof_input::params::{D, C, F, HF, Params}; +use proof_input::params::{D, C, F, HF}; +use proof_input::serialization::file_paths::{PROOF_JSON, TREE_PROOF_JSON, VERIFIER_CIRC_DATA_JSON}; +use proof_input::serialization::json::{export_tree_proof_with_pi, import_proof_with_pi, import_verifier_circuit_data}; fn main() -> Result<()> { // load the parameters from environment variables - let params = Params::from_env()?; const N: usize = 1; const M: usize = 2; @@ -26,31 +21,24 @@ fn main() -> Result<()> { 4 }; - // generate circuit input with given parameters - let circ_input = gen_testing_circuit_input::(¶ms.input_params); + // Read the proof + let proof_with_pi = import_proof_with_pi::()?; + println!("Proof with public input imported from: {}", PROOF_JSON); - // create the circuit - let config = CircuitConfig::standard_recursion_config(); - let mut builder = CircuitBuilder::::new(config); - let circ = SampleCircuit::::new(params.circuit_params); - let mut targets = circ.sample_slot_circuit_with_public_input(&mut builder)?; + // read the circuit data + let verifier_data = import_verifier_circuit_data::()?; + println!("Verifier circuit data imported from: {}", VERIFIER_CIRC_DATA_JSON); - // create a PartialWitness and assign - let mut pw = PartialWitness::new(); - circ.sample_slot_assign_witness(&mut pw, &targets, &circ_input)?; + // duplicate the proof to get k proofs + // this is just for testing - in real scenario we would need to load k proofs + let proofs: Vec> = (0..k).map(|_i| proof_with_pi.clone()).collect(); - // Build the circuit - let data = builder.build::(); - - // Prove the inner-circuit with the assigned witness - let inner_proof = data.prove(pw)?; - - // dummy proofs - let proofs: Vec> = (0..k).map(|i| inner_proof.clone()).collect(); - - let mut tree = TreeRecursion::::build_with_standard_config(data.common.clone(), data.verifier_only.clone()).unwrap(); + let mut tree = TreeRecursion::::build_with_standard_config(verifier_data.common.clone(), verifier_data.verifier_only.clone()).unwrap(); let tree_proof = tree.prove_tree(&proofs).unwrap(); + //export the proof to json file + export_tree_proof_with_pi(&tree_proof)?; + println!("Tree proof written to: {}", TREE_PROOF_JSON); let inner_pi: Vec> = proofs.iter().map(|p| p.public_inputs.clone()).collect(); diff --git a/workflow/src/bin/gen_input.rs b/workflow/src/bin/gen_input.rs index 380de90..51c3dbc 100644 --- a/workflow/src/bin/gen_input.rs +++ b/workflow/src/bin/gen_input.rs @@ -1,5 +1,4 @@ use std::time::Instant; -use plonky2::plonk::config::GenericConfig; use anyhow::Result; use proof_input::serialization::circuit_input::export_circ_input_to_json; use proof_input::gen_input::gen_testing_circuit_input; diff --git a/workflow/src/bin/prove.rs b/workflow/src/bin/prove.rs index 8ce9308..94faa1f 100644 --- a/workflow/src/bin/prove.rs +++ b/workflow/src/bin/prove.rs @@ -1,4 +1,3 @@ -use plonky2::plonk::config::GenericConfig; use anyhow::Result; use std::time::Instant; use codex_plonky2_circuits::circuit_helper::Plonky2Circuit; @@ -6,7 +5,7 @@ use proof_input::serialization::circuit_input::import_circ_input_from_json; use codex_plonky2_circuits::circuits::sample_cells::{SampleCircuit, SampleCircuitInput, SampleTargets}; use codex_plonky2_circuits::circuits::params::CircuitParams; use proof_input::params::{D, C, F, HF}; -use proof_input::serialization::file_paths::{CIRC_INPUT_JSON, PROVER_CIRC_DATA_JSON, TARGETS_JSON}; +use proof_input::serialization::file_paths::{CIRC_INPUT_JSON, PROVER_CIRC_DATA_JSON, TARGETS_JSON, TREE_PROOF_JSON}; use proof_input::serialization::json::{export_proof_with_pi, import_prover_circuit_data, import_targets}; fn main() -> Result<()> { @@ -34,6 +33,7 @@ fn main() -> Result<()> { //export the proof to json file export_proof_with_pi(&proof_with_pis)?; + println!("Tree proof written to: {}", TREE_PROOF_JSON); Ok(()) } diff --git a/workflow/src/bin/verify.rs b/workflow/src/bin/verify.rs index 6e64d5e..fdf3ee4 100644 --- a/workflow/src/bin/verify.rs +++ b/workflow/src/bin/verify.rs @@ -1,14 +1,10 @@ use std::time::Instant; -use plonky2::plonk::config::GenericConfig; use anyhow::Result; -use codex_plonky2_circuits::circuits::params::CircuitParams; use proof_input::params::{D, C, F}; use proof_input::serialization::file_paths::{PROOF_JSON, VERIFIER_CIRC_DATA_JSON}; use proof_input::serialization::json::{import_proof_with_pi, import_verifier_circuit_data}; fn main() -> Result<()> { - // Load the parameters from environment variables - let circuit_params = CircuitParams::from_env()?; // read the circuit data let verifier_data = import_verifier_circuit_data::()?;