use std::time::Instant;
use ark_ff::FftField;
use ark_std::rand::{distributions::Standard, prelude::Distribution, thread_rng, Rng};
use provekit_whir::{
algebra::fields::Field256,
hash,
parameters::ProtocolParameters,
protocols::whir_zk::Config,
transcript::{codecs::Empty, Codec, DomainSeparator, ProverState},
};
const WARMUP: usize = 3;
const ITERS: usize = 5;
fn main() {
eprintln!("=========================================");
eprintln!("zkWHIR Commit Benchmark (MontgomeryEncoder)");
eprintln!("=========================================\n");
bench::<Field256>("Field256", 40, 19, 4);
bench::<Field256>("Field256", 1, 19, 4);
}
fn bench<F>(field_name: &str, num_polys: usize, num_vars: usize, folding: usize)
where
F: FftField + Codec,
Standard: Distribution<F>,
{
let mut rng = thread_rng();
let num_coeffs = 1usize << num_vars;
let params = ProtocolParameters {
security_level: 128,
pow_bits: 10,
initial_folding_factor: folding,
folding_factor: folding,
unique_decoding: false,
starting_log_inv_rate: 1,
batch_size: num_polys,
hash_id: hash::BLAKE3,
};
let config = Config::<F>::new(num_vars, ¶ms);
let vectors: Vec<Vec<F>> = (0..num_polys)
.map(|_| (0..num_coeffs).map(|_| rng.gen()).collect())
.collect();
let vec_refs: Vec<&[F]> = vectors.iter().map(Vec::as_slice).collect();
let ds = DomainSeparator::protocol(&config)
.session(&format!("bench n={num_polys} mu={num_vars}"))
.instance(&Empty);
for _ in 0..WARMUP {
let mut ps = ProverState::new_std(&ds);
let _ = config.commit(&mut ps, &vec_refs);
}
let mut times = Vec::with_capacity(ITERS);
for _ in 0..ITERS {
let mut ps = ProverState::new_std(&ds);
let start = Instant::now();
let _ = config.commit(&mut ps, &vec_refs);
times.push(start.elapsed());
}
let avg = times.iter().sum::<std::time::Duration>() / ITERS as u32;
let min = *times.iter().min().unwrap();
eprintln!("{field_name} | n={num_polys} | μ={num_vars} | k=2^{folding}");
eprintln!(" avg={avg:>10.2?} min={min:>10.2?} ({ITERS} iters)");
eprintln!();
}