provekit-whir 0.1.1

An implementation of the WHIR polynomial commitment scheme
Documentation
//! Benchmark: zkWHIR commit with MontgomeryEncoder — compare against baseline.
//!
//! RUSTFLAGS="-C target-cpu=native" cargo run --release --features asm --bin bench_commit

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, &params);

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

    // Warmup
    for _ in 0..WARMUP {
        let mut ps = ProverState::new_std(&ds);
        let _ = config.commit(&mut ps, &vec_refs);
    }

    // Timed runs
    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!();
}