fix(stark): review follow-ups for OOD pruning (docs, saturating_sub, hard assert)#833
Merged
MauroToscano merged 3 commits intoJul 16, 2026
Conversation
- lookup.rs: fix the logup_single_source_tests module doc — after forward accumulation the 2-absorbed branch no longer reads next-row aux(1, ·) cells; describe it by what it actually does (folds two absorbed interactions, degree 3). - ood.rs: reword the module doc so the offset illustration is not pinned to [0, 1] — offset 0 is the current-row block, every later offset contributes a next-row block (generic over transition_offsets.len()). - verifier.rs: use num_eval_points.saturating_sub(step_size) to match the shared ood.rs helper (defensive consistency; underflow unreachable). - ood.rs: harden build_pruned_trace_term_coeffs — drop the per-slot `if p < powers.len()` guards and promote the trailing power-count check from debug_assert_eq! to a hard assert_eq!. Both operands are pure functions of AIR metadata (invariant I3), never proof-controlled, so a mismatch is a programmer bug that must not be masked in release builds.
Pre-existing -D warnings clippy errors in test code added on the #823 branch; CI's `make lint` (cargo clippy --workspace --all-targets) flags them but a crate-scoped lib-only clippy did not. - lookup.rs accumulated_column_is_forward_and_circular: iterate `&term_columns` instead of `0..n_term_cols` (needless_range_loop, two sites) and deref the two `get_aux(..).clone()` reads (clone_on_copy; FieldElement<Degree3GoldilocksExtensionField> is Copy). - logup_gpu.rs reference_accumulate: `out.push(acc.clone())` -> `out.push(acc)` (clone_on_copy). Only surfaces under the cuda-feature clippy pass, which the earlier passes stop short of.
Contributor
Author
|
Second commit (009f6de) clears the
Verified locally by running the exact CI |
…erm_coeffs build_pruned_trace_term_coeffs is a shared helper the verifier calls, and the verifier must never contain a panic path: an invalid proof is just a false proof, not a crash. Revert the hardening — restore the per-slot `if p < powers.len()` guards and the `debug_assert_eq!` power-count check. The doc comment still states the strict precondition (powers.len() == num_surviving_trace_openings for the same layout args); that is pure documentation and stays.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Review follow-ups for #823 (forward LogUp accumulation + next-row OOD opening pruning). Docs and consistency only; no behavior change.
logup_single_source_tests(lookup.rs): the module doc claimed the 2-absorbed branch "readsaux(1, ·)next-row cells". That described pre-refactor(logup): forward accumulation so acc is the sole next-row OOD read #823 backward accumulation; after forward accumulation both branches' only next-row read isacc_next, and absorbed operands read offset 0. Replaced with the branch's real distinction — it folds two absorbed interactions (degree 3).ood.rsmodule header: reworded the OOD-table illustration so it is no longer pinned tooffsets [0, 1]. The layout is generic overtransition_offsets.len()(repo has[0]and[0,1,2]example AIRs): offset 0 is the current-row block, every later offset contributes a next-row block.verifier.rs:num_eval_points - step_size→num_eval_points.saturating_sub(step_size), matching the sharedood.rshelper for the identical quantity. Purely defensive; the underflow is unreachable (would require an AIR with emptytransition_offsets, which does not exist and is not proof-controlled).build_pruned_trace_term_coeffs(ood.rs): added aPrecondition:line to the doc comment stating thatpowers.len()must equalnum_surviving_trace_openings(...)for the same layout args (both AIR-metadata-derived, invariant I3), checked in debug builds. Code is unchanged: the per-slotif p < powers.len()guards and thedebug_assert_eq!power-count check stay. Rationale: this is a shared helper the verifier calls, and the verifier must never contain a panic path — an invalid proof is a false proof, not a crash — so the release-mode bounds check is intentional and stays.Also in this PR (clears the base branch's latent
Lintfailure, which is inherited here):lookup.rsaccumulated_column_is_forward_and_circular,logup_gpu.rsreference_accumulate): iterate slices directly instead of0..n(needless_range_loop) and deref instead of.clone()onCopyfield elements (clone_on_copy).make lintrunscargo clippy --workspace --all-targets;--all-targetscovers these test targets. Thelogup_gpu.rsone only surfaces under the cuda-feature clippy pass.ood.rs, the onlycargo fmt --check --allviolation on the base.Validation:
make lint(fmt--check --all+ all four--workspace --all-targetsclippy passes incl. cuda) green;cargo test --release -p starkpassesood::(4),logup_single_source(7), andbus_tests(75).