Skip to content

Commit ce9633e

Browse files
committed
rename PCS to WHIR
1 parent 16c6cb5 commit ce9633e

31 files changed

Lines changed: 299 additions & 317 deletions

AGENTS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Dependency order, leaves first:
2121
| `zk_alloc` | proving arena (below) |
2222
| `primitives` | field kernels (NEON/AVX), bit transposes, multilinear helpers, `bench` |
2323
| `fiat_shamir` | VM-native sponge + prover/verifier transcript |
24-
| `pcs` | additive NTT, Merkle, ring switch, stacked Ligerito |
24+
| `pcs` | additive NTT, Merkle, ring switch, stacked WHIR |
2525
| `flock` | batched R1CS over GF(2) for BLAKE3: zerocheck + lincheck |
2626
| `lean_vm` | arithmetization: tables, bus, constraints, `cpu::prove`/`verify` |
2727
| `lean_compiler` | zkDSL (Python subset) → ISA |
@@ -41,7 +41,7 @@ cargo clippy --release --all-targets
4141
cargo fmt --all # max_width = 120
4242
```
4343

44-
Heavy benches and measurement harnesses are `#[ignore]`d; run by name with `-- --ignored --nocapture`: `blake3_batch_prove_verify`, `pcs_throughput`, `recursion_soundness_binds`, `recursion_generic_many`, `recursion_guest_profile`, `print_ligerito_query_counts`, `encoding_grinding_bits`.
44+
Heavy benches and measurement harnesses are `#[ignore]`d; run by name with `-- --ignored --nocapture`: `blake3_batch_prove_verify`, `pcs_throughput`, `recursion_soundness_binds`, `recursion_generic_many`, `recursion_guest_profile`, `print_whir_query_counts`, `encoding_grinding_bits`.
4545

4646
## Benchmarking
4747

@@ -112,5 +112,5 @@ The third is worth understanding before touching the verifier. `guests/recursion
112112
| `LEANVM_XMSS_N`, `LEANVM_HASH_N`, `LEANVM_HASH_UNROLL` | workload sizes in tests |
113113
| `FLOCK_N_LOG`, `FLOCK_PROVE_TRACE`, `FLOCK_ZC_TIMING`, `LINCHECK_TRACE` | flock batch size, stage traces |
114114
| `PCS_LOG_N`, `PCS_LOG_INV_RATE`, `PCS_MIN_MU`, `PCS_SAMPLES` | PCS throughput bench |
115-
| `LIGERITO_TRACE`, `LIGERITO_NUM_VARS`, `LIGERITO_LOG_INV_RATE` | Ligerito NTT/Merkle split |
115+
| `WHIR_TRACE`, `WHIR_NUM_VARS`, `WHIR_LOG_INV_RATE` | WHIR NTT/Merkle split |
116116
| `DBG_PROF{,_DUMP}`, `DBG_LOOPS`, `DBG_DISASM`, `DBG_LOWER`, `DBG_CSE`, `DBG_NO_CSE`, `DBG_PLACEHOLDERS` | compiler / guest-cycle attribution |

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,12 @@ Fibonacci (in the exponent, i.e. modulo 2^64 - 1), N = 2,000,000
6363

6464
## Security
6565

66-
- 128-bit proven (LDR Johnson)
66+
- 128-bit (LDR Johnson, no proximity gaps conjecture)
67+
68+
## Snark machinery
69+
70+
- Binary field of 192 bits
71+
- PCS: [WHIR](https://eprint.iacr.org/2024/1586) (aka [Ligerito](https://eprint.iacr.org/2025/1187))
6772

6873
## Credits
6974

crates/fiat_shamir/src/sponge.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ pub enum TraceOp {
279279
bits: u32,
280280
digest: F64,
281281
},
282-
/// An opening hint consumed (the Ligerito hint channel).
282+
/// An opening hint consumed (the WHIR hint channel).
283283
Opening,
284284
}
285285

crates/fiat_shamir/src/transcript.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//! binding it twice silently desynchronizes the two sides. A challenge is just
1616
//! `sample()`d, bound to everything seeded/sent so far.
1717
//! - **`hint_*` (prover) / `next_*` (verifier)**: transport that is NOT absorbed
18-
//! here, hash-bearing data (the Ligerito `openings`, like leanVM's
18+
//! here, hash-bearing data (the WHIR `openings`, like leanVM's
1919
//! `merkle_paths`) whose binding is the Merkle structure itself.
2020
//! - **`sample` / `sample_vec`**: squeeze a challenge.
2121
//!
@@ -25,13 +25,13 @@
2525
use crate::sponge::{Sponge, TraceOp, trace};
2626
use primitives::field::{F64, F192};
2727

28-
/// A complete proof: the scalar transcript stream plus the Ligerito opening hint
28+
/// A complete proof: the scalar transcript stream plus the WHIR opening hint
2929
/// channel: **two** channels, no bolted-on side field. The commitment root and
30-
/// every transmitted scalar ride `stream`; the hash-bearing Ligerito openings
30+
/// every transmitted scalar ride `stream`; the hash-bearing WHIR openings
3131
/// ride `openings`. flock's BLAKE3 sub-proof is carried the same way: its
3232
/// zerocheck / lincheck / ring-switch scalars are ordinary `add_scalar` words on
3333
/// `stream` (transmitted AND bound at their protocol points, like every other
34-
/// scalar) and its one Ligerito opening rides `openings`.
34+
/// scalar) and its one WHIR opening rides `openings`.
3535
///
3636
/// `Deserialize` as well as `Serialize`, so a proof round-trips over the wire and
3737
/// an independent verifier process reconstructs it: everything lives in these two
@@ -42,7 +42,7 @@ pub struct Proof<O> {
4242
/// Every transmitted field scalar, in protocol order (plus flock's scalar
4343
/// sub-proof as trailing raw transport words).
4444
pub stream: Vec<F192>,
45-
/// Ligerito openings (sumcheck messages + Merkle roots/paths), in order.
45+
/// WHIR openings (sumcheck messages + Merkle roots/paths), in order.
4646
pub openings: Vec<O>,
4747
}
4848

@@ -121,7 +121,7 @@ impl<O> ProverState<O> {
121121
}
122122

123123
/// The raw sponge, for side-agnostic sub-steps shared by prover and
124-
/// verifier (e.g. the Ligerito query sampler).
124+
/// verifier (e.g. the WHIR query sampler).
125125
pub fn sponge_mut(&mut self) -> &mut Sponge {
126126
&mut self.sponge
127127
}

crates/flock/src/blake3.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1553,7 +1553,7 @@ mod tests {
15531553
}
15541554

15551555
// The zerocheck, lincheck, and ring-switch scalars use the shared transcript;
1556-
// the caller carries the Ligerito opening.
1556+
// the caller carries the WHIR opening.
15571557

15581558
/// One claim on the committed packed BLAKE3 witness `q_pkd`, as left by the
15591559
/// Flock reduction and handed to the PCS. `claim` is the `ẑ(point) = value`

crates/flock/src/zerocheck/univariate_skip_optimized.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const N_MEDIUM: usize = 4;
6262
/// four medium constants returned by [`medium_challenges`] — must be
6363
/// **F₂-linearly independent** in F₁₉₂. Zerocheck soundness relies on this
6464
/// (a witness aligned with the friendly subspace would otherwise let the
65-
/// prover cancel the URM message), and so does Ligerito's L0 list-collapse
65+
/// prover cancel the URM message), and so does WHIR's L0 list-collapse
6666
/// argument (the SZ bound `(m−7)/|F|` for MLE collisions at `r` requires
6767
/// the seven friendly coords to span a 7-dim F₂-subspace). Asserted by
6868
/// `tests::friendly_challenges_f2_independent`.
@@ -1101,15 +1101,15 @@ mod tests {
11011101
}
11021102
}
11031103

1104-
/// **Soundness assumption.** Zerocheck and the Ligerito PCS opening at
1104+
/// **Soundness assumption.** Zerocheck and the WHIR PCS opening at
11051105
/// L0 both depend on the seven "friendly" constants — three small
11061106
/// (`φ_8(SMALL_CHAL_F8[k])`, k ∈ 0..3) and four medium
11071107
/// (`γ^{2^i}/(1+γ^{2^i})`, i ∈ 0..4) — being **F₂-linearly independent**
11081108
/// in F₁₉₂.
11091109
///
11101110
/// Zerocheck needs this so that the prover's URM message can't be
11111111
/// trivially canceled by a malicious witness aligned with the friendly
1112-
/// subspace. Ligerito's L0 list-collapse argument (which leans on the
1112+
/// subspace. WHIR's L0 list-collapse argument (which leans on the
11131113
/// zerocheck `(r, v)` claim as an OOD-equivalent) also depends on it
11141114
/// — see the soundness writeup. If any subset of these seven values is
11151115
/// F₂-dependent, the SZ bound `(m−7)/|F|` for collisions between
@@ -1153,7 +1153,7 @@ mod tests {
11531153
assert_eq!(
11541154
rank, 7,
11551155
"friendly challenges must be F₂-linearly independent in F₁₉₂; \
1156-
zerocheck and Ligerito L0 soundness depend on it"
1156+
zerocheck and WHIR L0 soundness depend on it"
11571157
);
11581158
}
11591159

crates/flock/tests/blake3_batch.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! This exercises only Flock's BLAKE3 path over `N` compressions: witness
44
//! generation, F64 commitment, zerocheck + lincheck reduction, the stacked
5-
//! ring-switch/Ligerito opening, and verification. Circuit construction is
5+
//! ring-switch/WHIR opening, and verification. Circuit construction is
66
//! outside the timed region, matching the VM's warmed-setup convention.
77
//!
88
//! Run with the XMSS-sized workload:
@@ -24,13 +24,13 @@ use flock::blake3::{
2424
min_n_blocks_log, pinned_compression,
2525
};
2626
use flock::proof::ZClaim;
27-
use pcs::ligerito::{INITIAL_FOLDING_FACTOR, LOG_INV_RATE_0};
28-
use pcs::ligerito::{commit, configs_for};
2927
use pcs::pack::{LOG_PACKING, PACKING_WIDTH};
3028
use pcs::stack_open::{
31-
RingSwitchClaim, RingSwitchOpen, RingSwitchVerify, open_batch_mixed_ligerito_stacked,
32-
verify_opening_batch_mixed_ligerito_stacked,
29+
RingSwitchClaim, RingSwitchOpen, RingSwitchVerify, open_batch_mixed_whir_stacked,
30+
verify_opening_batch_mixed_whir_stacked,
3331
};
32+
use pcs::whir::{INITIAL_FOLDING_FACTOR, LOG_INV_RATE_0};
33+
use pcs::whir::{commit, configs_for};
3434
use primitives::bench::{Plan, Timing};
3535
use primitives::multilinear::lagrange_weights_naive;
3636
use primitives::{
@@ -125,7 +125,7 @@ fn blake3_batch_prove_verify() {
125125
let setup = Blake3Setup::new(n);
126126
let setup_ms = t.elapsed().as_secs_f64() * 1e3;
127127

128-
let (prover_config, verifier_config) = configs_for(mu).expect("Ligerito configuration");
128+
let (prover_config, verifier_config) = configs_for(mu).expect("WHIR configuration");
129129

130130
// One full prove pass: witness generation, commitment, and the reduction +
131131
// stacked opening. Deterministic in `blocks`, so every pass is the same work
@@ -156,8 +156,7 @@ fn blake3_batch_prove_verify() {
156156
let reduced = setup.prove_reduction_precomputed(&z_packed, &a_packed, &b_packed, &z_lincheck, &mut ps);
157157
drop((z_packed, a_packed, b_packed, z_lincheck));
158158
let ring = prover_ring(&reduced, mu);
159-
let opening =
160-
open_batch_mixed_ligerito_stacked(ps.sponge_mut(), &q_pkd, &prover_data, &prover_config, &[], &ring);
159+
let opening = open_batch_mixed_whir_stacked(ps.sponge_mut(), &q_pkd, &prover_data, &prover_config, &[], &ring);
161160
let open_s = t.elapsed().as_secs_f64();
162161
let prove_s = t_prove.elapsed().as_secs_f64();
163162

@@ -189,7 +188,7 @@ fn blake3_batch_prove_verify() {
189188
let root = pcs::merkle::scalars_to_hash(&vs.next_scalars(2).expect("commitment root"));
190189
let replay = setup.verify_reduction(&mut vs).expect("Flock reduction verifies");
191190
let ring = verifier_ring(&replay.ab, &replay.c, mu);
192-
verify_opening_batch_mixed_ligerito_stacked(vs.sponge_mut(), &verifier_config, mu, &root, &[], &ring, &opening)
191+
verify_opening_batch_mixed_whir_stacked(vs.sponge_mut(), &verifier_config, mu, &root, &[], &ring, &opening)
193192
.expect("stacked PCS opening verifies");
194193
vs.finish().expect("transcript fully consumed");
195194
});

crates/lean_vm/src/blake3_flock.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! as a column in leanVM-b's ONE stacked `F64` witness (§3.1), with no separate flock
55
//! commitment. The VM's `BLAKE3` table binds to it by point-eval equality (its
66
//! value columns and `q_pkd`'s slots are point-evals of the same committed
7-
//! stack), and flock's R1CS validity is discharged by the same stacked Ligerito:
7+
//! stack), and flock's R1CS validity is discharged by the same stacked WHIR:
88
//! the reduction's two tower-field claims pass through
99
//! [`ring_switch_open`] / [`ring_switch_verify`] and join the batch-mixed
1010
//! opening ([`::pcs::stack_open`]).
@@ -530,7 +530,7 @@ mod tests {
530530
}
531531
}
532532

533-
/// flock's validity claims, discharged by ONE stacked Ligerito over a
533+
/// flock's validity claims, discharged by ONE stacked WHIR over a
534534
/// hand-stacked witness containing `q_pkd` (plus a dummy column) together
535535
/// with an ordinary point claim: the full prove_reduction → ring-switch →
536536
/// stack_open seam without the VM pipeline. Proves and verifies on the

crates/lean_vm/src/cpu/layout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub const BFCNT: usize = 4; // per-pc bytecode execution count, g^{A[pc]}
2121
// SOLE copy of the input/output words: the VM's BLAKE3 value columns are
2222
// virtual and their memory-bus claims route to `q_pkd` slots (§blake3_flock), so
2323
// nothing duplicates them. flock's R1CS validity is discharged by the single
24-
// stacked Ligerito opening over this commitment.
24+
// stacked WHIR opening over this commitment.
2525
pub const QPKD: usize = 5;
2626
pub const N_SHARED: usize = 6;
2727

crates/lean_vm/src/cpu/mod.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ fn read_public(vs: &mut VerifierState, prog: &Program, public_input: &[F192; 2])
192192
|| bytecode_size > (1usize << MAX_LOG_BYTECODE)
193193
|| !(MIN_LOG_MEM..=MAX_LOG_MEM).contains(&log_mem)
194194
|| row_counts.iter().any(|&r| r >= (1usize << MAX_LOG_ROWS))
195-
|| ::pcs::ligerito::validate_log_inv_rate(log_inv_rate).is_err()
195+
|| ::pcs::whir::validate_log_inv_rate(log_inv_rate).is_err()
196196
{
197197
return Err(Error::PublicInput);
198198
}
@@ -492,7 +492,7 @@ impl Stats {
492492
/// Fiat-Shamir transcript before the commitment.
493493
#[tracing::instrument(name = "Prove", skip_all, fields(log_inv_rate))]
494494
pub fn prove(program: &Program, public_input: [F192; 2], log_inv_rate: usize) -> (Proof, Stats) {
495-
::pcs::ligerito::validate_log_inv_rate(log_inv_rate).expect("valid log_inv_rate");
495+
::pcs::whir::validate_log_inv_rate(log_inv_rate).expect("valid log_inv_rate");
496496
// One proof is one arena phase: every transient buffer below is bump-allocated
497497
// and reclaimed wholesale here, rather than faulted in and unmapped again per
498498
// proof. Bound first so it outlives them; inert unless `init_prover` opted in.
@@ -535,7 +535,7 @@ pub fn prove(program: &Program, public_input: [F192; 2], log_inv_rate: usize) ->
535535
// `w.q` (≥1 instance, a program with no BLAKE3 carries one padding instance,
536536
// so the proof shape is uniform and there is no has/hasn't-BLAKE3 fork). flock's
537537
// R1CS validity and EVERY leanVM point claim are discharged together by ONE
538-
// Ligerito over this commitment (below). The input/output words bind via the
538+
// WHIR over this commitment (below). The input/output words bind via the
539539
// memory bus (virtual value columns route to q_pkd); the constant pins reuse a
540540
// bus point, so no dedicated binding challenge is drawn. Mirrored in `verify`.
541541
let l = &w.layout;
@@ -582,7 +582,7 @@ pub fn prove(program: &Program, public_input: [F192; 2], log_inv_rate: usize) ->
582582
// Run flock's reduction (zerocheck + lincheck) over the prepared native
583583
// layouts retained from the fused q_pkd build pass; it returns the `(ab, c)`
584584
// validity claims on the committed `q_pkd`, discharged by the PCS below in the
585-
// SAME Ligerito as every leanVM point claim (the point claims become the
585+
// SAME WHIR as every leanVM point claim (the point claims become the
586586
// opener's `point_claims`).
587587
let flock_reduction = w
588588
.flock_reduction
@@ -667,7 +667,7 @@ fn bind_pi_claim(
667667
/// Everything a recursion harness needs from an accepting verify run, named
668668
/// and typed: the deferred bytecode claims, the count-channel root, flock's
669669
/// reduction claims, and the stacked-opening summary (ring-switch challenges +
670-
/// Ligerito fold/query data). The sub-proof scalars themselves live on
670+
/// WHIR fold/query data). The sub-proof scalars themselves live on
671671
/// `proof.stream` at fixed offsets from its tail. Ordinary callers just
672672
/// `?`-discard it.
673673
pub struct VerifySummary {
@@ -691,7 +691,7 @@ pub fn verify(program: &Program, public_input: &[F192; 2], proof: &Proof) -> Res
691691
let root = pcs::read_commitment(&mut vs).map_err(Error::Transcript)?;
692692

693693
// BLAKE3 ↔ flock (single PCS): flock's R1CS validity and every leanVM point
694-
// claim are verified together by ONE Ligerito opening at the end. The executed-
694+
// claim are verified together by ONE WHIR opening at the end. The executed-
695695
// BLAKE3 count is public (announced); its flock sub-proof rides the shared
696696
// `stream`/`openings`, and presence is enforced by consumption below plus
697697
// `vs.finish()` (a proof with `n_b3 = 0` but trailing flock data, or vice versa,
@@ -728,7 +728,7 @@ pub fn verify(program: &Program, public_input: &[F192; 2], proof: &Proof) -> Res
728728

729729
// Replay flock's reduction straight off the shared stream (each scalar bound
730730
// as it is read) to recover its `(ab, c)` validity claims on q_pkd, then
731-
// verify them alongside every point claim in the ONE Ligerito opening
731+
// verify them alongside every point claim in the ONE WHIR opening
732732
// (mirroring `prove`). `n_blocks = max(n_b3, 1)`, always ≥ 1 instance.
733733
let n_blocks = n_b3.max(1);
734734
let offset = l.placements[QPKD].offset;
@@ -811,7 +811,7 @@ mod tests {
811811
/// cell), hash them into the output `c` (cells 6,7), pad with filler SETs so
812812
/// the last executed instruction lands one before the sentinel, and halt
813813
/// there. The flock validity sub-proof plus the memory / state / bytecode bus
814-
/// interactions are verified end-to-end (the proof carries the Ligerito
814+
/// interactions are verified end-to-end (the proof carries the WHIR
815815
/// opening they assert on).
816816
fn blake3_program(a: [F64; 4], b: [F64; 4]) -> Program {
817817
// a → cells 2,3 and b → cells 4,5 (two flock lanes per BLAKE3 cell).
@@ -882,9 +882,9 @@ mod tests {
882882

883883
let (proof, stats) = prove(&program, pi, pcs::LOG_INV_RATE);
884884
assert_eq!(stats.counts[5], 1, "one BLAKE3 row");
885-
// flock's sub-proof rides the shared channels: its Ligerito is the proof's
885+
// flock's sub-proof rides the shared channels: its WHIR is the proof's
886886
// one opening, its scalar reduction trails the `stream`.
887-
assert!(!proof.openings.is_empty(), "BLAKE3 program carries a Ligerito opening");
887+
assert!(!proof.openings.is_empty(), "BLAKE3 program carries a WHIR opening");
888888
verify(&program, &pi, &proof).expect("BLAKE3 program verifies");
889889
}
890890

@@ -953,7 +953,7 @@ mod tests {
953953
verify(&program, &pi, &proof).expect("self-hash BLAKE3 verifies");
954954
}
955955

956-
/// Tampering flock's validity sub-proof (its Ligerito, opened over the same
956+
/// Tampering flock's validity sub-proof (its WHIR, opened over the same
957957
/// stacked commitment) must make verification fail.
958958
#[test]
959959
fn blake3_rejects_tampered_validity() {
@@ -967,8 +967,8 @@ mod tests {
967967

968968
// The stacked opening is the proof's one hint; tamper a sumcheck
969969
// round message (the inner-product transcript); must be rejected.
970-
let lig = proof.openings.last_mut().expect("stacked Ligerito opening");
971-
lig.ligerito.sumcheck_transcript[0].u_0 += F192::ONE;
970+
let lig = proof.openings.last_mut().expect("stacked WHIR opening");
971+
lig.whir.sumcheck_transcript[0].u_0 += F192::ONE;
972972
assert!(
973973
verify(&program, &pi, &proof).is_err(),
974974
"tampered BLAKE3 validity proof must be rejected"
@@ -980,7 +980,7 @@ mod tests {
980980
/// the verifier's reduction/opening replay, so tampering a transport word
981981
/// diverges the recovered `(ab, c)` claims (or breaks decoding) and
982982
/// verification must reject. (Complements `blake3_rejects_tampered_validity`,
983-
/// which tampers the Ligerito opening.)
983+
/// which tampers the WHIR opening.)
984984
#[test]
985985
fn blake3_rejects_tampered_reduction() {
986986
let program = blake3_program(
@@ -1019,7 +1019,7 @@ mod tests {
10191019
let pi = [F192::new(1, 2, 3), F192::new(4, 5, 6)];
10201020
let (proof, stats) = prove(&program, pi, pcs::LOG_INV_RATE);
10211021
assert_eq!(stats.counts[5], 0, "no real BLAKE3 rows");
1022-
// The proof still carries exactly one Ligerito opening (over the padding).
1022+
// The proof still carries exactly one WHIR opening (over the padding).
10231023
assert_eq!(proof.openings.len(), 1, "unified path: one opening always");
10241024
verify(&program, &pi, &proof).expect("non-BLAKE3 program verifies");
10251025
}

0 commit comments

Comments
 (0)