Skip to content
This repository was archived by the owner on Sep 12, 2026. It is now read-only.

Commit fdd9046

Browse files
committed
stop observing some transcript twice in fiat shamir
1 parent bc30f80 commit fdd9046

15 files changed

Lines changed: 67 additions & 129 deletions

File tree

crates/fiat_shamir/src/transcript.rs

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Fiat-Shamir proof transport. `add_scalar` and `next_scalar` transmit and bind together. `observe_scalar` is only for public values both sides derive. Merkle hints are authenticated by their trees and are not absorbed separately.
1+
//! Fiat-Shamir proof transport. `add_scalar` and `next_scalar` transmit and bind together, which is the only way anything enters the state: a transmitted value needs no separate absorb, a value derived from transmitted ones needs none either, and the statement rides the seed the state starts from. So there is no absorb-only method at all. Merkle hints are authenticated by their trees and are not absorbed separately.
22
33
use crate::FiatShamirState;
44
use crate::merkle::{Hash, PrunedMerklePaths, RawMerklePath, hash_to_scalars, scalars_to_hash};
@@ -36,18 +36,6 @@ pub enum Error {
3636
pub trait Challenger {
3737
fn sample(&mut self) -> F192;
3838
fn sample_vec(&mut self, n: usize) -> Vec<F192>;
39-
/// Bind a value both sides derive themselves (never transmitted), so it is
40-
/// side-agnostic and lives here rather than on the two halves below.
41-
fn observe_scalar(&mut self, x: F192);
42-
43-
/// Bind a root both sides already hold (a commitment that is part of the
44-
/// statement) as its two scalars, not as a byte string, so the recursion
45-
/// guest replays one shape for every digest.
46-
fn observe_root(&mut self, root: &Hash) {
47-
for s in hash_to_scalars(root) {
48-
self.observe_scalar(s);
49-
}
50-
}
5139
}
5240

5341
/// The prover half of a transmitting sub-protocol (WHIR and its sumchecks):
@@ -323,9 +311,6 @@ impl Challenger for ProverState {
323311
fn sample_vec(&mut self, n: usize) -> Vec<F192> {
324312
self.fs.sample_vec(n)
325313
}
326-
fn observe_scalar(&mut self, x: F192) {
327-
self.fs.observe(x);
328-
}
329314
}
330315

331316
impl Challenger for VerifierState<'_> {
@@ -335,12 +320,6 @@ impl Challenger for VerifierState<'_> {
335320
fn sample_vec(&mut self, n: usize) -> Vec<F192> {
336321
self.fs.sample_vec(n)
337322
}
338-
/// Absorb a value both parties compute themselves (never transmitted):
339-
/// protocol steps that bind derived values before sampling, e.g. the
340-
/// stacked-bytecode claim reduction (`leaf::verify_balance`).
341-
fn observe_scalar(&mut self, x: F192) {
342-
self.fs.observe(x);
343-
}
344323
}
345324

346325
#[cfg(test)]

crates/flock/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
//! gadgets, forwards and transposed, kept separate because the fused
2626
//! three-operand adder's bit boundaries are the subtlest thing here.
2727
28-
pub mod hash;
2928
mod gf2;
29+
pub mod hash;
3030
pub mod lincheck;
3131
/// The circuit driven through the whole reduction. A `src` module rather than
3232
/// its own test binary so it shares the process, and so the slow

crates/lean_compiler/tests/suite/inline_expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
//! `let`.
88
99
use lean_compiler::{compile, parse};
10-
use lean_vm::hash_flock::warm_setup;
1110
use lean_vm::cpu::{prove, verify};
11+
use lean_vm::hash_flock::warm_setup;
1212
use primitives::field::{F64, F192};
1313

1414
#[test]

crates/lean_compiler/tests/suite/pack64x2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use lean_compiler::{compile, parse};
2-
use lean_vm::hash_flock::warm_setup;
32
use lean_vm::cpu::{prove, verify};
3+
use lean_vm::hash_flock::warm_setup;
44
use primitives::field::{F64, F192};
55

66
use crate::common::mix;

crates/lean_compiler/tests/suite/print_debug.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
//! witness generation, and leave proving/verification untouched.
33
44
use lean_compiler::{compile, parse};
5-
use lean_vm::hash_flock::warm_setup;
65
use lean_vm::cpu::{prove, verify};
6+
use lean_vm::hash_flock::warm_setup;
77
use primitives::field::{F64, F192};
88

99
#[test]

crates/lean_compiler/tests/suite/stack_buf.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
//!: the reference `compress` is fed that lane layout.
1111
1212
use lean_compiler::{compile, parse};
13-
use lean_vm::hash_flock::{compression, digest, metadata, unpack_metadata, warm_setup};
1413
use lean_vm::cpu::{Op, prove, verify};
14+
use lean_vm::hash_flock::{compression, digest, metadata, unpack_metadata, warm_setup};
1515
use lean_vm::vmhash::compress;
1616
use primitives::field::{F64, F192};
1717

crates/lean_compiler/tests/suite/vm_proofs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
//! duplicating their knowledge of what a dummy row looks like.
88
99
use lean_compiler::{compile, parse};
10-
use lean_vm::hash_flock::warm_setup;
1110
use lean_vm::cpu::{Error, Proof, prove, verify};
11+
use lean_vm::hash_flock::warm_setup;
1212
use lean_vm::vmhash::compress;
1313
use primitives::field::{F64, F192};
1414

crates/lean_vm/src/cpu/mod.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -832,11 +832,7 @@ mod tests {
832832
ins: [2, 3, 4, 5],
833833
cv: 0,
834834
out: 6,
835-
metadata: crate::hash_flock::metadata(
836-
crate::hash_flock::PINNED_T,
837-
crate::hash_flock::FINAL_FLAG,
838-
0,
839-
),
835+
metadata: crate::hash_flock::metadata(crate::hash_flock::PINNED_T, crate::hash_flock::FINAL_FLAG, 0),
840836
},
841837
]; // c → cells 6,7
842838
// 16 slots: 5 executed, then 10 filler SETs step the pc to 15, whose slot is
@@ -923,11 +919,7 @@ mod tests {
923919
ins: [2, 3, 2, 3],
924920
cv: 0,
925921
out: 4,
926-
metadata: crate::hash_flock::metadata(
927-
crate::hash_flock::PINNED_T,
928-
crate::hash_flock::FINAL_FLAG,
929-
0,
930-
),
922+
metadata: crate::hash_flock::metadata(crate::hash_flock::PINNED_T, crate::hash_flock::FINAL_FLAG, 0),
931923
},
932924
];
933925
// 8 slots: 3 executed, 4 filler SETs stepping the pc, then the sentinel.

crates/lean_vm/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
//! - [`hash_flock`]: the `BLAKE2s` glue: flock's R1CS validity proof over the same commitment.
2121
//! - [`vmhash`]: VM-native hashing (one-block compression and standard BLAKE2s slice hashing).
2222
23-
pub mod hash_flock;
2423
pub mod colval;
2524
pub mod constraints;
2625
pub mod cpu;
2726
pub mod gkr;
27+
pub mod hash_flock;
2828
pub mod leaf;
2929
pub mod pcs;
3030
pub mod tables;

crates/pcs/src/stack_open.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@
3131
//! ## Transcript order (identical on both sides)
3232
//!
3333
//! label -> shared linear map sampled ([`super::ring_switch`]'s own label; the
34-
//! claims' slices were bound by the caller, so none are sent here) -> per point
35-
//! claim (label + value observed) -> lambda (ONE challenge for both families) ->
36-
//! WHIR, with domain-separated labels for every phase.
34+
//! claims' slices were bound by the caller, so none are sent here) -> lambda (ONE
35+
//! challenge for both families) -> WHIR, with domain-separated labels for every
36+
//! phase. No claim value is observed here: each was bound by the stream read that
37+
//! produced it, so lambda already depends on every one of them.
3738
//!
3839
//! ## The combined weight
3940
//!
@@ -393,11 +394,9 @@ pub fn open_batch_mixed_whir_stacked(
393394
let map_challenges = ring_switch::sample_map_challenges(ps);
394395
let coordinate_weights = ring_switch::build_coordinate_weights(&map_challenges);
395396

396-
// 2. Point-claim values, then the ONE batching challenge both families take
397-
// disjoint power ranges of.
398-
for claim in point_claims {
399-
ps.observe_scalar(claim.value());
400-
}
397+
// 2. The ONE batching challenge both families take disjoint power ranges of. Nothing is
398+
// observed first: every claim value reached the caller through a binding stream read, so
399+
// the challenge already depends on all of them (`lean_vm::pcs::open`).
401400
let lambdas = powers(ps.sample(), ring.claims.len() + point_claims.len());
402401
let (lambdas_rs, lambdas_pd) = lambdas.split_at(ring.claims.len());
403402

@@ -514,11 +513,8 @@ pub fn verify_opening_batch_mixed_whir_stacked(
514513
let map_challenges = ring_switch::sample_map_challenges(vs);
515514
let coordinate_weights = ring_switch::build_coordinate_weights(&map_challenges);
516515

517-
// 2. Point-claim values, then the one batching challenge, then fold both
518-
// families into the target over disjoint power ranges.
519-
for claim in point_claims {
520-
vs.observe_scalar(claim.value());
521-
}
516+
// 2. The one batching challenge (see the opener: the claim values are bound by the read that
517+
// produced them), then fold both families into the target over disjoint power ranges.
522518
let lambdas = powers(vs.sample(), n_rs + point_claims.len());
523519
let (lambdas_rs, lambdas_pd) = lambdas.split_at(n_rs);
524520

0 commit comments

Comments
 (0)