//! Bit-flip scan of a full recursive proof: every bit of the encoded
//! proof flipped in turn, parsed and verified; reports how many decoded
//! and how many were accepted (must be 0).
//!
//! `ivc_flip <fixture> [proof file]` โ€” proves the fixture (or reads the
//! proof bytes from the file, written by an earlier run), then scans on
//! all cores. `ZHENG_STRIDE=<k>` scans every k-th bit only.

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

use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Instant;
use zheng::machine;
use zheng::recursion::ivc;

fn main() {
    let args: Vec<String> = std::env::args().skip(1).collect();
    let mut whir = zheng::execution::succinct::params_for(20);
    whir.log_inv_rate = ivc::SHIPPED_RATE;
    whir.pow_bits = ivc::SHIPPED_POW;
    let n = 15u32;
    let (prog, input) = match args.first().map(String::as_str).unwrap_or("add.tri") {
        "add.tri" => (common::parse(common::ADD), vec![7u64, 5]),
        t if t.starts_with("tree-") => (common::tree_program(t[5..].parse().unwrap()), vec![3]),
        other => panic!("fixture {other}"),
    };
    let run = machine::execute_exact(&prog, &input, 1 << 40, n).expect("run");
    let key = ivc::key(&whir, n as usize).expect("key");
    let bytes = match args.get(1) {
        Some(path) if std::path::Path::new(path).exists() => std::fs::read(path).expect("read"),
        other => {
            let proof = ivc::prove_run(&run, &whir).expect("prove");
            let b = proof.to_bytes(&key);
            if let Some(path) = other {
                std::fs::write(path, &b).expect("write");
            }
            b
        }
    };
    let parse = |b: &[u8]| ivc::IvcProof::from_bytes(b, |lr| ivc::key(&whir, lr as usize));
    let p = parse(&bytes).expect("honest proof parses");
    ivc::verify(&run.statement, &p, &whir).expect("honest proof verifies");
    let prep = ivc::prepare(
        &run.statement,
        &whir,
        p.log_rows,
        p.start,
        p.segments,
        p.chain,
    )
    .expect("prepare");
    let stride: usize = std::env::var("ZHENG_STRIDE")
        .ok()
        .and_then(|v| v.parse().ok())
        .unwrap_or(1);
    let bits = bytes.len() * 8;
    let next = AtomicUsize::new(0);
    let (flips, decoded, accepted) = (
        AtomicUsize::new(0),
        AtomicUsize::new(0),
        AtomicUsize::new(0),
    );
    let t0 = Instant::now();
    let threads = std::thread::available_parallelism()
        .map_or(1, |n| n.get())
        .min(16);
    std::thread::scope(|s| {
        for _ in 0..threads {
            s.spawn(|| {
                let mut buf = bytes.clone();
                loop {
                    let k = next.fetch_add(1, Ordering::Relaxed) * stride;
                    if k >= bits {
                        break;
                    }
                    buf[k / 8] ^= 1 << (k % 8);
                    flips.fetch_add(1, Ordering::Relaxed);
                    if let Ok(q) = parse(&buf) {
                        decoded.fetch_add(1, Ordering::Relaxed);
                        let same = (q.log_rows, q.start, q.segments, q.chain) == prep.header;
                        let ok = if same {
                            ivc::verify_prepared(&prep, &q).is_ok()
                        } else {
                            ivc::verify(&run.statement, &q, &whir).is_ok()
                        };
                        if ok {
                            accepted.fetch_add(1, Ordering::Relaxed);
                            eprintln!("ACCEPTED flip of bit {k}");
                        }
                    }
                    buf[k / 8] ^= 1 << (k % 8);
                    let f = flips.load(Ordering::Relaxed);
                    if f % 50_000 == 0 {
                        eprintln!("  {f} flips ยท {:.0} s", t0.elapsed().as_secs_f64());
                    }
                }
            });
        }
    });
    println!(
        "bit-flip scan: {} bytes ยท {} flips (stride {stride}) ยท {} decoded ยท {} accepted ยท {:.0} s",
        bytes.len(),
        flips.load(Ordering::Relaxed),
        decoded.load(Ordering::Relaxed),
        accepted.load(Ordering::Relaxed),
        t0.elapsed().as_secs_f64()
    );
}

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/ivc_bench/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/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