use std::time::Instant;
use ark_ff::FftField;
use ark_std::rand::{distributions::Standard, prelude::Distribution, thread_rng, Rng};
use provekit_whir::{
algebra::{
fields::{Field128, Field192, Field256, Field64, Field64_2, Field64_3},
linear_form::MultilinearExtension,
},
parameters::ProtocolParameters,
protocols::whir_zk::Config,
transcript::{codecs::Empty, Codec, DomainSeparator, ProverState},
};
const NUM_POLYNOMIALS: usize = 42;
const NUM_VARIABLES: usize = 19;
const NUM_COEFFS: usize = 1 << NUM_VARIABLES;
fn main() {
println!("=====================================================");
println!("Commit Benchmark: {} poly × 2^{}", NUM_POLYNOMIALS, NUM_VARIABLES);
println!("Flags: opt-level=3, lto=fat, codegen-units=1");
println!(" target-cpu=native, --features asm");
println!("=====================================================\n");
println!("Warming up...");
bench::<Field192>("warmup", 128, 20, 1, 4, 4);
println!("\n--- Head-to-head: 128-bit security, 3 runs each ---");
for i in 1..=3 {
println!("\nRun {i}:");
bench::<Field64_3>(" Field64_3 (Goldilocks^3)", 128, 20, 1, 4, 4);
bench::<Field192>(" Field192 (192-bit prime)", 128, 20, 1, 4, 4);
bench::<Field256>(" Field256/BN254", 128, 20, 1, 4, 4);
}
}
fn bench<F>(label: &str, security_level: usize, pow_bits: usize, rate: usize, iff: usize, ff: usize)
where
F: FftField + Codec,
Standard: Distribution<F>,
{
print!("{label:<55} ");
let whir_params = ProtocolParameters {
security_level,
pow_bits,
initial_folding_factor: iff,
folding_factor: ff,
unique_decoding: false,
starting_log_inv_rate: rate,
batch_size: NUM_POLYNOMIALS,
hash_id: provekit_whir::hash::BLAKE3,
};
let result = std::panic::catch_unwind(|| {
let params = Config::<F>::new(NUM_VARIABLES, &whir_params);
let ds = DomainSeparator::protocol(¶ms)
.session(&String::from("bench"))
.instance(&Empty);
let mut prover_state = ProverState::new_std(&ds);
let mut rng = thread_rng();
let vectors: Vec<Vec<F>> = (0..NUM_POLYNOMIALS)
.map(|_| (0..NUM_COEFFS).map(|_| rng.gen()).collect())
.collect();
let vec_refs: Vec<&[F]> = vectors.iter().map(Vec::as_slice).collect();
let t = Instant::now();
let _witness = params.commit(&mut prover_state, &vec_refs);
t.elapsed()
});
match result {
Ok(elapsed) => println!("{elapsed:.2?} (sec={security_level}, pow={pow_bits}, rate={rate})"),
Err(_) => println!("FAILED (PoW > 60 or config error)"),
}
}