fix and improve the workflow scripts and bench.

This commit is contained in:
M Alghazwi 2025-04-10 10:54:56 +02:00
parent 950cd6bd0d
commit 5e7d210322
No known key found for this signature in database
GPG Key ID: 646E567CAD7DB607
7 changed files with 74 additions and 130 deletions

View File

@ -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::<C>();
println!("inner circuit size = {:?}", inner_data.common.degree_bits());
let inner_verifier_data: VerifierCircuitData<F,C,D> = inner_data.verifier_data();
// prove with dummy public input
let mut pw = PartialWitness::<F>::new();
pw.set_hash_target(pi[0], HashOut::<F>::ZERO)?;
pw.set_hash_target(pi[1], HashOut::<F>::ZERO)?;
pw.set_hash_target(pi[1], get_hash_of_verifier_data::<F,D,C,HF>(&inner_verifier_data))?;
let inner_proof = inner_data.prove(pw)?;
// Compression circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let compression_circ = CompressionCircuit::<F,D,C,HF>::new(inner_data.common.clone());
let compression_targets = compression_circ.build(&mut builder)?;
let compression_circ = CompressionCircuit::<F,D,C,HF>::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::<F, D>::new(config);
let _compression_targets = compression_circ.build(&mut local_builder);
let _data = local_builder.build::<C>();
let _compression_targets = compression_circ.build_with_standard_config();
})
});
// Build the circuit once for proving and verifying benchmarks
let compression_circ_data = builder.build::<C>();
println!("compress circuit size = {:?}", compression_circ_data.common.degree_bits());
let mut pw = PartialWitness::<F>::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<F,C,D> = 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

View File

@ -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<D, F = F>,
H: Hasher<F> + AlgebraicHasher<F>,
>(N: usize, max_depth: usize) -> Result<(
>(n: usize, max_depth: usize) -> Result<(
Vec<MerkleTreeCircuitInput<F, D>>,
HashOut<F>,
)> {
// 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::<Vec<_>>();
// Hash the data to obtain leaf hashes
@ -53,7 +52,7 @@ fn prepare_data<
let tree = MerkleTree::<F, D>::new(&leaves, zero_hash)?;
// Select N leaf indices to prove
let leaf_indices: Vec<usize> = (0..N).collect();
let leaf_indices: Vec<usize> = (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::<F, D,C,H>(N, max_depth).unwrap();
let (circ_input, expected_root) = prepare_data::<F, D,C,H>(n, max_depth).unwrap();
// Benchmark the circuit building
group.bench_function("Merkle Proof Build", |b| {

View File

@ -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<const N: usize>(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<const N: usize>(c: &mut Criterion) -> Result<()>{
// gen the circuit input
let circ_input = gen_testing_circuit_input::<F,D>(&test_params);
// Create the circuit configuration
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
// Initialize the SampleCircuit with the parameters
let circ = SampleCircuit::<F,D,HF>::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<F,C,D> = 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::<F, D>::new(config);
let _targets = circ.sample_slot_circuit_with_public_input(&mut local_builder);
let _data = local_builder.build::<C>();
let _: (_, CircuitData<F, C, D>) = 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::<C>();
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<const N: usize>(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

View File

@ -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::<F,D>(&params.input_params);
// Read the proof
let proof_with_pi = import_proof_with_pi::<F,C,D>()?;
println!("Proof with public input imported from: {}", PROOF_JSON);
// create the circuit
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let circ = SampleCircuit::<F,D,HF>::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::<F,C,D>()?;
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<ProofWithPublicInputs<F, C, D>> = (0..k).map(|_i| proof_with_pi.clone()).collect();
// Build the circuit
let data = builder.build::<C>();
// Prove the inner-circuit with the assigned witness
let inner_proof = data.prove(pw)?;
// dummy proofs
let proofs: Vec<ProofWithPublicInputs<F, C, D>> = (0..k).map(|i| inner_proof.clone()).collect();
let mut tree = TreeRecursion::<F,D,C,HF, N, M>::build_with_standard_config(data.common.clone(), data.verifier_only.clone()).unwrap();
let mut tree = TreeRecursion::<F,D,C,HF, N, M>::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<Vec<F>> = proofs.iter().map(|p| p.public_inputs.clone()).collect();

View File

@ -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;

View File

@ -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(())
}

View File

@ -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::<F,C,D>()?;