From 4e53a4d7fe7f15a4596ef06cff6260566e29984a Mon Sep 17 00:00:00 2001 From: Piotr Mikolajczyk Date: Tue, 15 Apr 2025 15:06:40 +0200 Subject: [PATCH 1/2] Baseline --- .../src/bin/batch_proving.rs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 crates/shielder-circuits/src/bin/batch_proving.rs diff --git a/crates/shielder-circuits/src/bin/batch_proving.rs b/crates/shielder-circuits/src/bin/batch_proving.rs new file mode 100644 index 00000000..bbd891d3 --- /dev/null +++ b/crates/shielder-circuits/src/bin/batch_proving.rs @@ -0,0 +1,41 @@ +use once_cell::sync::Lazy; +use rand::prelude::StdRng; +use rand_core::SeedableRng; +use shielder_circuits::circuits::Params; +use shielder_circuits::merkle::{MerkleCircuit, MerkleProverKnowledge}; +use shielder_circuits::{ + generate_keys_with_min_k, generate_proof, generate_setup_params, verify, ProverKnowledge, + PublicInputProvider, MAX_K, +}; +use std::time::Instant; + +static PARAMS: Lazy = + Lazy::new(|| generate_setup_params(MAX_K, &mut StdRng::from_seed(Default::default()))); + +const NOTE_TREE_HEIGHT: usize = 13; + +fn main() { + let mut rng = StdRng::from_seed([41; 32]); + + let values = MerkleProverKnowledge::::random_correct_example(&mut rng); + let circuit = values.create_circuit(); + + let (reduced_params, _, pk, vk) = + generate_keys_with_min_k(MerkleCircuit::::default(), PARAMS.clone()) + .unwrap(); + + let public_input = values.serialize_public_input(); + + println!("proving..."); + let proving_start = Instant::now(); + + let proof = generate_proof(&reduced_params, &pk, circuit, &public_input, &mut rng); + + println!("proving duration: {:?}", proving_start.elapsed()); + println!("proof length: {}", proof.len()); + + println!("verifying..."); + let verifying_start = Instant::now(); + verify(&reduced_params, &vk, &proof, &public_input).expect("verification should not fail"); + println!("verifying duration: {:?}", verifying_start.elapsed()); +} From 4ec4432253346a0cdacc813c9973e25de63807a8 Mon Sep 17 00:00:00 2001 From: Piotr Mikolajczyk Date: Tue, 15 Apr 2025 17:36:37 +0200 Subject: [PATCH 2/2] Bench batching --- crates/shielder-circuits/Cargo.toml | 5 + crates/shielder-circuits/benches/batching.rs | 127 ++++++++++++++++++ .../src/bin/batch_proving.rs | 41 ------ 3 files changed, 132 insertions(+), 41 deletions(-) create mode 100644 crates/shielder-circuits/benches/batching.rs delete mode 100644 crates/shielder-circuits/src/bin/batch_proving.rs diff --git a/crates/shielder-circuits/Cargo.toml b/crates/shielder-circuits/Cargo.toml index 53089534..9d9e6e62 100644 --- a/crates/shielder-circuits/Cargo.toml +++ b/crates/shielder-circuits/Cargo.toml @@ -44,3 +44,8 @@ regex = { workspace = true } name = "benchmarks" path = "benches/bench.rs" harness = false + +[[bench]] +name = "batching" +path = "benches/batching.rs" +harness = false diff --git a/crates/shielder-circuits/benches/batching.rs b/crates/shielder-circuits/benches/batching.rs new file mode 100644 index 00000000..0624f385 --- /dev/null +++ b/crates/shielder-circuits/benches/batching.rs @@ -0,0 +1,127 @@ +use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; +use halo2_proofs::halo2curves::bn256::Fr; +use halo2_proofs::plonk::{create_proof, verify_proof}; +use halo2_proofs::poly::commitment::ParamsProver; +use halo2_proofs::poly::kzg::strategy::AccumulatorStrategy; +use halo2_proofs::transcript::TranscriptWriterBuffer; +use rand::prelude::StdRng; +use rand::Rng; +use rand_core::SeedableRng; +use shielder_circuits::circuits::{Params, ProvingKey}; +use shielder_circuits::merkle::MerkleCircuit; +use shielder_circuits::{ + circuits::merkle::MerkleProverKnowledge, + consts::merkle_constants::{ARITY, NOTE_TREE_HEIGHT}, + generate_keys_with_min_k, generate_setup_params, CommitmentScheme, Prover, ProverKnowledge, + PublicInputProvider, Verifier, MAX_K, +}; +use transcript::Keccak256Transcript; + +criterion_main! { + batching +} + +criterion_group! { + name = batching; + config = Criterion::default().sample_size(10); + targets = bench_batching +} + +type Circuit = MerkleCircuit; +type PK = MerkleProverKnowledge; +const BATCH_SIZE: usize = 100; + +pub fn bench_batching(c: &mut Criterion) { + // ==================================== SETUP PHASE ==================================== // + let mut rng = StdRng::from_seed([41; 32]); + + let full_params = generate_setup_params(MAX_K, &mut rng); + let (reduced_params, k, pk, vk) = + generate_keys_with_min_k(Circuit::default(), full_params).unwrap(); + + // ==================================== DATA PHASE ==================================== // + let (mut circuits, mut instances_owned) = (vec![], vec![]); + for _ in 0..BATCH_SIZE { + let prover_knowledge = PK::random_correct_example(&mut rng); + circuits.push(prover_knowledge.create_circuit()); + instances_owned.push(vec![prover_knowledge.serialize_public_input()]); + } + let instances_less_owned = instances_owned + .iter() + .map(|instance_column| { + instance_column + .iter() + .map(|i| i.as_slice()) + .collect::>() + }) + .collect::>(); + let instances = instances_less_owned + .iter() + .map(|instance_column| instance_column.as_slice()) + .collect::>(); + + // ==================================== PROVING PHASE ==================================== // + let mut group = c.benchmark_group("Batch proving / verifying"); + + // Actually generate a proof, for future verification bench. + group.bench_function( + BenchmarkId::new( + "Batch proving", + format!("batch size = {BATCH_SIZE}, k={k}, arity={ARITY}, height={NOTE_TREE_HEIGHT}"), + ), + |b| { + b.iter(|| { + black_box(generate_batched_proof( + &reduced_params, + &pk, + &circuits, + &instances, + &mut rng, + )) + }) + }, + ); + + // Actually generate a proof, for future verification bench. + let proof = generate_batched_proof(&reduced_params, &pk, &circuits, &instances, &mut rng); + + // ==================================== VERIFYING PHASE ==================================== // + group.bench_function( + BenchmarkId::new( + "Batch verifying", + format!("batch size = {BATCH_SIZE}, k={k}, arity={ARITY}, height={NOTE_TREE_HEIGHT}"), + ), + |b| { + b.iter(|| { + let mut transcript = Keccak256Transcript::new(proof.as_slice()); + black_box(verify_proof::( + reduced_params.verifier_params(), + &vk, + AccumulatorStrategy::new(reduced_params.verifier_params()), + &instances, + &mut transcript, + )) + }) + }, + ); +} + +fn generate_batched_proof( + params: &Params, + pk: &ProvingKey, + circuits: &[Circuit], + instances: &[&[&[Fr]]], + rng: &mut impl Rng, +) -> Vec { + let mut transcript = Keccak256Transcript::new(Vec::new()); + create_proof::( + params, + pk, + circuits, + instances, + rng, + &mut transcript, + ) + .unwrap(); + transcript.finalize().to_vec() +} diff --git a/crates/shielder-circuits/src/bin/batch_proving.rs b/crates/shielder-circuits/src/bin/batch_proving.rs deleted file mode 100644 index bbd891d3..00000000 --- a/crates/shielder-circuits/src/bin/batch_proving.rs +++ /dev/null @@ -1,41 +0,0 @@ -use once_cell::sync::Lazy; -use rand::prelude::StdRng; -use rand_core::SeedableRng; -use shielder_circuits::circuits::Params; -use shielder_circuits::merkle::{MerkleCircuit, MerkleProverKnowledge}; -use shielder_circuits::{ - generate_keys_with_min_k, generate_proof, generate_setup_params, verify, ProverKnowledge, - PublicInputProvider, MAX_K, -}; -use std::time::Instant; - -static PARAMS: Lazy = - Lazy::new(|| generate_setup_params(MAX_K, &mut StdRng::from_seed(Default::default()))); - -const NOTE_TREE_HEIGHT: usize = 13; - -fn main() { - let mut rng = StdRng::from_seed([41; 32]); - - let values = MerkleProverKnowledge::::random_correct_example(&mut rng); - let circuit = values.create_circuit(); - - let (reduced_params, _, pk, vk) = - generate_keys_with_min_k(MerkleCircuit::::default(), PARAMS.clone()) - .unwrap(); - - let public_input = values.serialize_public_input(); - - println!("proving..."); - let proving_start = Instant::now(); - - let proof = generate_proof(&reduced_params, &pk, circuit, &public_input, &mut rng); - - println!("proving duration: {:?}", proving_start.elapsed()); - println!("proof length: {}", proof.len()); - - println!("verifying..."); - let verifying_start = Instant::now(); - verify(&reduced_params, &vk, &proof, &public_input).expect("verification should not fail"); - println!("verifying duration: {:?}", verifying_start.elapsed()); -}