use nebu::Goldilocks;
use nox::{reduce, NullCalls, Order, Outcome, Reduction, VecTrace};
use zheng::{commit, verify, ProofParams, Statement, TraceProof};
const QUOTE: u64 = 1;
const ADD: u64 = 5;
const MUL: u64 = 7;
fn open_statement() -> Statement {
Statement {
program_hash: [0u8; 32],
input_hash: [0u8; 32],
output_hash: [0u8; 32],
focus_bound: 0,
}
}
fn run_madd(a: u64, b: u64, c: u64) -> (VecTrace, u64) {
let mut r = Reduction::<4096>::new();
let subject = r.atom(Goldilocks::new(0)).expect("subject");
let quote = |r: &mut Reduction<4096>, v: u64| -> Order {
let tag = r.atom(Goldilocks::new(QUOTE)).unwrap();
let val = r.atom(Goldilocks::new(v)).unwrap();
r.pair(tag, val).unwrap() };
let qa = quote(&mut r, a);
let qb = quote(&mut r, b);
let qc = quote(&mut r, c);
let mul_tag = r.atom(Goldilocks::new(MUL)).unwrap();
let mul_body = r.pair(qa, qb).unwrap();
let mul = r.pair(mul_tag, mul_body).unwrap();
let add_tag = r.atom(Goldilocks::new(ADD)).unwrap();
let add_body = r.pair(mul, qc).unwrap();
let formula = r.pair(add_tag, add_body).unwrap();
let mut trace = VecTrace::default();
let result = match reduce(&mut r, subject, formula, 1000, &NullCalls, &mut trace) {
Outcome::Ok(res, _) => r.atom_value(res).expect("atom result").as_u64(),
other => panic!("nox reduce failed: {other:?}"),
};
(trace, result)
}
pub fn prove_madd(a: u64, b: u64, c: u64) -> (TraceProof, Statement, u64) {
let (trace, result) = run_madd(a, b, c);
let statement = open_statement();
let proof = commit(&trace, &[], &[], &[], &statement, &ProofParams::default())
.expect("zheng commit");
(proof, statement, result)
}
pub fn verify_proof(proof: &TraceProof, statement: &Statement) -> bool {
verify(proof, statement, &ProofParams::default()).is_ok()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn madd_proof_verifies_end_to_end() {
let (proof, stmt, result) = prove_madd(3, 5, 7);
assert_eq!(result, 22, "3·5 + 7 computed correctly by nox");
assert!(verify_proof(&proof, &stmt), "the zheng proof verifies");
}
#[test]
fn trace_has_multiple_pattern_rows() {
let (trace, _) = run_madd(6, 7, 1);
assert!(trace.0.len() >= 2, "trace spans several reduction steps");
}
#[test]
fn focus_bound_binds_the_step_count() {
let (trace, _) = run_madd(3, 5, 7);
let mut stmt = open_statement();
stmt.focus_bound = 1; let rejected = commit(&trace, &[], &[], &[], &stmt, &ProofParams::default());
assert!(rejected.is_err(), "understated focus_bound rejected");
}
}