Skip to content

Bind useful_bits + const_pin into statement digest; pin hash walkers#2

Open
aryaethn wants to merge 1 commit into
succinctlabs:mainfrom
aryaethn:harden/statement-binding-digest
Open

Bind useful_bits + const_pin into statement digest; pin hash walkers#2
aryaethn wants to merge 1 commit into
succinctlabs:mainfrom
aryaethn:harden/statement-binding-digest

Conversation

@aryaethn

Copy link
Copy Markdown

Summary

Addresses two items from the security audit (#1), both under "bind useful_bits, const_pin, circuit ID":

1. Statement digest completeness. BlockR1cs::statement_digest() absorbed m, k_log, k_skip, and the three matrices, but omitted useful_bits and const_pin — both of which change protocol semantics:

  • useful_bits is the padding boundary (which rows carry witness vs. zero padding), so it changes the lincheck equation.
  • const_pin drives the lincheck β-pin term.

Two instances differing only in those fields produced the same digest, so the Fiat-Shamir binding in bind_statement didn't separate them. This PR absorbs both (with a length-unambiguous Option encoding for const_pin) and bumps the domain tag flock-r1cs-stmt-v0v1, so a v0 transcript can never collide with a v1.

2. Hash walkers advertise the constant pin. Blake3LincheckCircuit and Sha2LincheckCircuit didn't override const_pin_col(), so they inherited the trait default None — silently dropping the lincheck β-pin term if used directly. (The live matrix path already carries the pin via BlockR1cs::{sparse,csc}_lincheck_circuit.) Both now return Some(Z_CONST_POS), matching the setup, closing the all-zero-witness gap if these public circuits are used directly.

Tests

  • New statement_digest_binds_useful_bits_and_const_pin: determinism, plus distinct digests when useful_bits, const_pin presence, or the pin column index changes.
  • Extended lincheck_circuit_matches_sparse (blake3 + sha2) to assert the walker's const_pin_col() matches the pinned sparse circuit.
  • Full suite green (337 tests, 0 failures) on x86-64 Linux via the scalar fallbacks.

Notes

  • The v0 → v1 tag bump changes the digest value, but the prover and verifier compute it identically, so honest proofs still verify (the end-to-end roundtrip test passes). It does invalidate proofs serialized against the old transcript — assumed fine pre-release; happy to handle compatibility differently if not.
  • Can split into two PRs (digest vs. walker pin) if you'd prefer to review them separately.

Addresses two items from the security audit (succinctlabs#1):

- statement_digest() now absorbs useful_bits and const_pin (tag bumped
  v0 -> v1, with a length-unambiguous Option encoding). Both fields
  change the lincheck / padding semantics, so omitting them left a
  statement-substitution gap in the Fiat-Shamir binding.

- Blake3LincheckCircuit / Sha2LincheckCircuit now override
  const_pin_col() -> Some(Z_CONST_POS), so the lincheck beta-pin term is
  not silently dropped when those circuits are used directly.

Adds regression tests: digest-change coverage for both fields, and
walker-vs-sparse constant-pin alignment for both hashes. Full suite
green (337 tests).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SipengXie2024 added a commit to SipengXie2024/flock that referenced this pull request Jul 2, 2026
Review findings (36 agents, 86 candidates, 15 confirmed):

Fixed:
- succinctlabs#7: SSE2 convert-table dispatch missing in s_hat_v partial path
  (copy-paste omission — x86 fell back to scalar in boundary window)
- succinctlabs#8/#12: multi_base.rs imported route.rs (FANOUT=4) instead of
  route_f32.rs (FANOUT=32). Any fanout>4 would panic. Fixed import
  + updated acceptance test to use RouteF32Witness.

Skipped (documented, not fixable without larger changes):
- succinctlabs#1/succinctlabs#3/succinctlabs#6: route_single.rs 3 soundness gaps (documented in header,
  needs wiring sumcheck)
- succinctlabs#2/succinctlabs#4/succinctlabs#9/succinctlabs#10: files >700 LOC (route 810, route_f32 936, route_single
  950 — needs structural refactor, separate PR)
- succinctlabs#5: multi_base missing padding skip (perf-only, not correctness)
- #11: PaddingSpec inconsistency in hash_only PCS open (no effect —
  padding skip only applies to zerocheck, not PCS)
- #13/#14/#15: Ligerito floor magic number, PCS PaddingSpec, target_feature
  annotation — all by-design or no-impact

338 tests pass (279 flock-core + 50 mhot unit + 8 acceptance + 1 profile).
SipengXie2024 added a commit to SipengXie2024/flock that referenced this pull request Jul 2, 2026
Review findings (36 agents, 86 candidates, 15 confirmed):

Fixed:
- succinctlabs#7: SSE2 convert-table dispatch missing in s_hat_v partial path
  (copy-paste omission — x86 fell back to scalar in boundary window)
- succinctlabs#8/#12: multi_base.rs imported route.rs (FANOUT=4) instead of
  route_f32.rs (FANOUT=32). Any fanout>4 would panic. Fixed import
  + updated acceptance test to use RouteF32Witness.

Skipped (documented, not fixable without larger changes):
- succinctlabs#1/succinctlabs#3/succinctlabs#6: route_single.rs 3 soundness gaps (documented in header,
  needs wiring sumcheck)
- succinctlabs#2/succinctlabs#4/succinctlabs#9/succinctlabs#10: files >700 LOC (route 810, route_f32 936, route_single
  950 — needs structural refactor, separate PR)
- succinctlabs#5: multi_base missing padding skip (perf-only, not correctness)
- #11: PaddingSpec inconsistency in hash_only PCS open (no effect —
  padding skip only applies to zerocheck, not PCS)
- #13/#14/#15: Ligerito floor magic number, PCS PaddingSpec, target_feature
  annotation — all by-design or no-impact

338 tests pass (279 flock-core + 50 mhot unit + 8 acceptance + 1 profile).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant