Files
zeekay 369c90e94a p3q-verifier: land audit-grade generic STARK/FRI verifier body
Replace the `not yet audit-gated` stub in verify_sha3/verify_keccak with
a real Fiat-Shamir-driven generic STARK / FRI low-degree verifier.
Wraps cleanly: AIR-specific Z-Chain circuit verifiers compose this
kernel and add their boundary/transition checks on top.

What lands

* wire.rs - canonical wire format v1 (10-byte header + public input +
  trace root + FRI layer roots + final polynomial + per-query
  openings). Every length/range/well-formedness check fires BEFORE
  any crypto. Headers reject non-binary arities, out-of-range
  log_blowup/log_degree_bound/num_queries/log_final_poly, reserved
  bits, wrong version.

* transcript.rs - typed wrapper around p3q-challenger. Profile-keyed
  customisation string (LUX-P3Q-V1-SHA3 / LUX-P3Q-V1-KECCAK) plus
  per-observation tag prefixes (HEADER, PUBLIC-INPUT, TRACE-COMMIT,
  FRI-COMMIT, FRI-FINAL, FRI-QUERY). Field-element squeezing uses
  cSHAKE256 rejection sampling with a finite 32-iter cap.

* domain.rs - LDE-domain generator from Goldilocks 2-adicity (g=7),
  binary FRI fold formula with two-test correctness proof, Horner
  evaluation.

* verify.rs - the kernel: phase-1 transcript replay capturing per-
  round fold challenges, phase-2 query-index re-derivation with echo
  check, per-query trace+layer Merkle authentications, colinearity
  check against folded carry, final-poly evaluation comparison. Every
  failure mode maps to a precise P3qError variant - no unwrap, no
  panic.

* prover.rs (feature `prover`) - minimal toy prover that produces
  golden vectors. Used by in-crate roundtrip tests only; not in the
  audited verifier compile graph.

* p3q-field: pow() and two_adic_generator() (g=7 quadratic non-
  residue gives primitive 2^k-th roots up to k=32).

Verification properties tested

* sha3+keccak golden vectors verify (toy AIR: degree-16 poly, blowup
  8, 16 queries, final poly of size 2)
* tampering rejected: profile byte swap, trace root bit-flip, FRI
  layer root bit-flip, final-poly bit-flip, public-input bit-flip,
  echoed query-index bit-flip (precise Transcript variant), arbitrary
  per-query byte flip
* parsing rejects: short header, wrong version, non-binary arity,
  log_final_poly >= log_degree_bound, reserved nonzero, truncated
  body, trailing bytes, oversized Merkle path length
* never panics on random first-byte fuzz
* profiles do not cross-verify (cSHAKE customisation isolates them)

Golden vectors

vectors/p3q_v1_{sha3,keccak}_golden.{proof,public_input}.bin written
by the `write_golden_vectors` ignored test. `persisted_golden_vectors
_verify` reads them back and confirms acceptance - any wire-format
change forces a regen.

Verify wall-clock

Toy AIR (~30 KB proof): ~1 ms per verify in release on M2 Pro.

Workspace state

cargo fmt --check, cargo clippy --all-targets -- -D warnings, and
cargo test all clean. 87 tests passing (1 ignored vector writer).
scripts/lint_forbidden.sh clean (no bn254/kzg/groth16/blake3/poseidon
imports).

Out of scope for this commit

* AIR-specific Z-Chain circuits (boundary + transition constraints)
  - p3q-zchain stays scaffolded, lands in v0.2.x
* recursive STARK composition - p3q-recursion stays scaffolded
* coset FRI / bit-reverse leaf permutation - dual-auth-path v1 wire
  is intentionally simple; v2 can collapse to single path under
  bit-rev
2026-05-30 18:03:19 -07:00
..