//! Measure recursive (IVC) proofs of nox runs: proof bytes, prove and
//! verify time, under the recursion profile's WHIR parameters
//! (`ZHENG_RATE=<log inv rate>`, default `ivc::SHIPPED_RATE`; `ZHENG_POW=<bits>`, default `ivc::SHIPPED_POW`;
//! `ZHENG_STEP=<log rows>`, default 15).
//!
//! `cargo run --release -p zheng --example ivc_bench -- [fixture…]`
//! fixtures: add.tri hash.tri merkle-32 tree-<k> rec-<n>

#[path = "../../tests/common/mod.rs"]
mod common;

use std::time::Instant;
use zheng::execution::ExecutionNoun as N;
use zheng::machine;
use zheng::recursion::ivc;

fn fixture(name: &str) -> Option<(N, Vec<u64>)> {
    Some(match name {
        "add.tri" => (common::parse(common::ADD), vec![7, 5]),
        "hash.tri" => (common::parse(common::HASH), vec![7]),
        "merkle-32" => {
            let root = machine::execute(&common::merkle_program(32, None), &[5], 1 << 40).ok()?;
            let r = machine::statement::parse(&root.statement.output).ok()?;
            (common::merkle_program(32, Some(&r)), vec![5])
        }
        t if t.starts_with("tree-") => (common::tree_program(t[5..].parse().ok()?), vec![3]),
        t if t.starts_with("rec-") => (common::rec_program(), vec![t[4..].parse().ok()?]),
        _ => return None,
    })
}

fn env<T: std::str::FromStr>(k: &str, d: T) -> T {
    std::env::var(k)
        .ok()
        .and_then(|v| v.parse().ok())
        .unwrap_or(d)
}

fn main() {
    common::backend();
    let mut whir = zheng::execution::succinct::params_for(20);
    whir.log_inv_rate = env("ZHENG_RATE", ivc::SHIPPED_RATE);
    whir.pow_bits = env("ZHENG_POW", ivc::SHIPPED_POW);
    let n: u32 = env("ZHENG_STEP", 15);
    let args: Vec<String> = std::env::args().skip(1).collect();
    let names = if args.is_empty() {
        vec!["add.tri".into()]
    } else {
        args
    };
    let t0 = Instant::now();
    let key = ivc::key(&whir, n as usize).expect("key");
    let p = &key.params;
    eprintln!(
        "key: 2^{n} rows, β„“ {}, rate 1/{}, pow {}, t {} s {} Β· {:.0} ms",
        p.vars,
        1u32 << whir.log_inv_rate,
        whir.pow_bits,
        p.cfg.queries,
        p.cfg.ood,
        t0.elapsed().as_secs_f64() * 1e3
    );
    for name in names {
        let (prog, input) = fixture(&name).unwrap_or_else(|| panic!("fixture {name}"));
        let t1 = Instant::now();
        let run = machine::execute_exact(&prog, &input, 1 << 40, n).expect("run");
        let t_run = t1.elapsed();
        if std::env::var_os("ZHENG_DRY").is_some() {
            println!(
                "{name}: cycles {} Β· {} steps of 2^{n}",
                run.statement.cycles,
                run.segments()
            );
            continue;
        }
        common::prof_report("key");
        let t2 = Instant::now();
        let proof = ivc::prove_run(&run, &whir).expect("prove");
        let t_prove = t2.elapsed();
        common::prof_report(&name);
        let bytes = proof.to_bytes(&key);
        if let Ok(dir) = std::env::var("ZHENG_PROOF_DIR") {
            std::fs::write(format!("{dir}/{name}.ivc"), &bytes).expect("write proof");
        }
        let parsed =
            ivc::IvcProof::from_bytes(&bytes, |lr| ivc::key(&whir, lr as usize)).expect("parse");
        assert_eq!(parsed, proof);
        let mut v = Vec::new();
        for _ in 0..5 {
            let t3 = Instant::now();
            ivc::verify(&run.statement, &parsed, &whir).expect("verify");
            v.push(t3.elapsed().as_secs_f64() * 1e3);
        }
        v.sort_by(|a, b| a.partial_cmp(b).unwrap());
        let prep = ivc::prepare(
            &run.statement,
            &whir,
            parsed.log_rows,
            parsed.start,
            parsed.segments,
            parsed.chain,
        )
        .expect("prepare");
        let mut vp = Vec::new();
        for _ in 0..5 {
            let t3 = Instant::now();
            ivc::verify_prepared(&prep, &parsed).expect("verify");
            vp.push(t3.elapsed().as_secs_f64() * 1e3);
        }
        vp.sort_by(|a, b| a.partial_cmp(b).unwrap());
        let segs = run.segments();
        let parts: Vec<String> = proof
            .sizes(&key)
            .iter()
            .map(|(k, v)| format!("{k} {v}"))
            .collect();
        println!("{name}: parts {}", parts.join(" Β· "));
        println!(
            "{name}: cycles {} Β· {} steps of 2^{n} rows Β· proof {} B Β· run {:.0} ms Β· prove {:.0} ms ({:.0} ms/step) Β· verify median {:.2} ms (prepared {:.2} ms)",
            run.statement.cycles,
            segs,
            bytes.len(),
            t_run.as_secs_f64() * 1e3,
            t_prove.as_secs_f64() * 1e3,
            t_prove.as_secs_f64() * 1e3 / segs as f64,
            v[2],
            vp[2]
        );
    }
}

Homonyms

cyber/src/main.rs
cyb/cli/src/main.rs
soft3/nox/cli/main.rs
neural/trident/src/main.rs
cyb/optica/src/main.rs
soft3/glia/import/main.rs
cyberia/cyberia-my/src/main.rs
cyb/apps/src/main.rs
soft3/tru/cli/main.rs
neural/rune/cli/main.rs
warriors/trisha/cli/main.rs
warriors/joy/cli/main.rs
cyb/shell/src/main.rs
soft3/conformance/rs/src/main.rs
neural/eidos/cli/src/main.rs
soft3/radio/iroh-dns-server/src/main.rs
soft3/radio/iroh-relay/src/main.rs
soft3/radio/particle/src/main.rs
soft3/strata/cli/src/main.rs
soft3/zheng/cli/src/main.rs
neural/rs/pure-rust-check/src/main.rs
soft3/hemera/cli/src/main.rs
soft3/neuron/cli/src/main.rs
soft3/glia/run/cli/main.rs
neural/rs/link/src/main.rs
soft3/radio/radio-cli/src/main.rs
soft3/foculus/src/bin/main.rs
neural/rs/macho-linker/src/main.rs
soft3/bbg/cli/src/main.rs
neural/rs/rsc/src/main.rs
neural/rs/cli/src/main.rs
soft3/lens/cli/src/main.rs
soft3/cybergraph/cli/src/main.rs
warriors/erga/cli/src/main.rs
soft3/zheng/rs/examples/wrap_plan/main.rs
cyb/honeycrisp/acpu/src/probe/main.rs
soft3/strata/jali/cli/src/main.rs
soft3/zheng/rs/examples/wrap_keys/main.rs
soft3/mudra/audit/quantus-mldsa-crosscheck/src/main.rs
soft3/zheng/rs/examples/envelope_profiles/main.rs
soft3/zheng/specs/proto/zheng_spartan/main.rs
soft3/zheng/rs/examples/wrap_chain/main.rs
warriors/erga/rs/rtable-bench/src/main.rs
soft3/strata/kuro/cli/src/main.rs
soft3/strata/trop/cli/src/main.rs
soft3/zheng/rs/examples/wrap_flip/main.rs
soft3/zheng/rs/examples/wrap_bench/main.rs
warriors/trisha/tools/neptune-policy-oracle/src/main.rs
soft3/zheng/specs/proto/zheng_bug/main.rs
soft3/zheng/specs/proto/zheng_inner/main.rs
soft3/zheng/rs/examples/fast_path/main.rs
soft3/zheng/specs/proto/zheng_spartan_fixed/main.rs
warriors/erga/rs/mine-bench/src/main.rs
soft3/zheng/rs/examples/wrapped_sizes/main.rs
soft3/zheng/rs/examples/wrap_verify/main.rs
soft3/zheng/rs/examples/ivc_plan/main.rs
soft3/zheng/rs/examples/ivc_flip/main.rs
soft3/zheng/rs/examples/machine_bench/main.rs
soft3/zheng/rs/examples/succinct_bakeoff/main.rs
soft3/zheng/specs/proto/zheng_outer/main.rs
neural/inf/rs/cli/src/main.rs
cyb/wysm/crates/cli/src/main.rs
warriors/erga/rs/blake-bench/src/main.rs
soft3/strata/nebu/cli/src/main.rs
soft3/lytics/rs/agent/src/main.rs
cyb/honeycrisp/rane/src/probe/main.rs
neural/trident/silicon/src/bin/main.rs
soft3/strata/genies/cli/src/main.rs
soft3/lytics/rs/ingest/src/main.rs
soft3/radio/audit/2026-10-12-bao-bounded-proof/nostd/src/main.rs
soft3/radio/audit/2026-10-12-bao-proof-research/probe/src/main.rs
soft3/mudra/audit/signature-optimality/xnt-predicate-check/src/main.rs
cyb/honeycrisp/unimem/experiments/hyp_probe/src/main.rs
soft3/radio/audit/2026-10-12-bao-bounded-proof/fixture-probe/src/main.rs
soft3/radio/audit/2026-10-12-bao-bounded-proof/nostd-parent/src/main.rs
soft3/radio/audit/2026-10-12-bao-proof-research/primary-probe/src/main.rs
cyb/honeycrisp/unimem/experiments/iosurface_probe/src/main.rs
cyb/honeycrisp/unimem/experiments/dext_contiguous_alloc/client/src/main.rs
cyb/honeycrisp/unimem/experiments/dext_iosurface_pa/client/src/main.rs

Graph