feat: optimize sumcheck in ECCVM and Translator#23615
Merged
Merged
Conversation
Adds dedicated short-monomial variants for point_table, wnaf, transcript, msm, and lookup relations. Selectors and short linear combinations stay in length-2 coefficient basis; promotion to the length-N Lagrange accumulator happens at multiplication boundaries (lookup open-codes the logderivative loop because the shared library constructs UnivariateView<FF, RELATION_LENGTH> directly over the input, which buffer-overreads on length-2 short edges). Removes ecc_short_relation_adapter.hpp now that every relation has a dedicated short impl. Remote benchmark CPU times (vs eccvm_full_*): | benchmark | full | short | delta | |--------------|--------:|--------:|---------------:| | prove/12 | 621 ms | 598 ms | 3.7% faster | | prove/13 | 765 ms | 703 ms | 8.1% faster | | prove/14 | 1036 ms | 918 ms | 11.4% faster | | prove/15 | 1614 ms | 1380 ms | 14.5% faster | | sumcheck/12 | 122 ms | 91.6 ms | 24.9% faster | | sumcheck/13 | 199 ms | 140 ms | 29.6% faster | | sumcheck/14 | 353 ms | 237 ms | 32.9% faster | | sumcheck/15 | 683 ms | 440 ms | 35.6% faster |
Override SUBRELATION_PARTIAL_LENGTHS in each short relation subclass to match
the actual computed degree+1 instead of inheriting the base class's
conservative max. Each subrelation that drops below the previous universal
length now uses its own per-subrelation Accumulator type via
tuple_element_t<INDEX, ContainerOverSubrelations>, following the precedent
set by ECCVMSetShortRelationImpl ({22, 3, 3}).
To preserve sharing of promoted Accumulator-typed intermediates:
- transcript keeps LAMBDA / ACCUMULATOR_X/Y_UPDATE / ACCUMULATOR_EMPTY_UPDATE
at length 8 (shared result_is_lhs/rhs/inf, opcode_is_zero).
- msm keeps ADD/SKEW/DOUBLE_ACC, all SLOPE_*, COLLISION_CHECK_*, IDLE_ROW at
length 8 (shared q_add_scaled / q_double_scaled / q_skew_scaled, q_add_acc /
q_skew_acc, acc_x/y).
- Independent "tail" subrelations (INACTIVE_*, CONTINUITY_*, PHASE_SELECTOR_*,
round transitions, deg-2 infinity/boundary checks, etc.) shrink to their
true minimum (2-5).
MAX_PARTIAL_RELATION_LENGTH is unchanged at the flavor level, so the static
assertion against ECCVMFlavor still holds and the verifier interface is
unaffected.
Remote benchmark CPU times (eccvm_short_monomial_*, vs prior commit):
| benchmark | prev | new | abs | % |
|--------------|--------:|--------:|-------:|-------:|
| sumcheck/12 | 94.7ms | 86.1ms | -8.6ms | -9.1% |
| sumcheck/13 | 141ms | 134ms | -7ms | -5.0% |
| sumcheck/14 | 237ms | 232ms | -5ms | -2.1% |
| sumcheck/15 | 442ms | 434ms | -8ms | -1.8% |
| prove/12-15 | within noise of prior commit |
The absolute saving is roughly constant across sizes (~7ms) because the
ECCVM benchmark runs a fixed-sized MSM workload with the trace power only
controlling padding — the number of active (non-skip) rows is roughly
size-invariant.
…ages into cb/e5446517bda3
Repoints prove_eccvm/prove_translator to ECCVMShortMonomialProver and TranslatorShortMonomialProver. Short-monomial is a prover-side sumcheck optimization that produces an identical proof and VK, so the existing Goblin verifier path is unchanged and the legacy flavors/relations remain for tests and fuzzing. Integration branch for end-to-end VM short-monomial benchmarking.
Remove the env-gated std::cerr/getenv row-skip diagnostics (BB_SUMCHECK_ROW_SKIP_DIAGNOSTICS)
from sumcheck_round.hpp, eccvm_flavor.hpp, and translator_proving_key.{hpp,cpp}, keeping the
production static row-skip manifest logic intact. Diagnostics violated the no-std::cerr C++
invariant and only existed to validate the manifest during development.
Also reverts the eccvm browserstack bench harness (bbapi_eccvm_bench, serve-eccvm-bench.mjs,
browser-test-app wiring) which is unrelated scaffolding for this branch.
Verified: eccvm/translator/goblin/chonk test suites pass; bbapi_tests builds.
compute_row_skip_ranges now takes num_active_op_rows and marks the contiguous op-active prefix [0, num_gates) of each concatenation block directly, instead of scanning every minicircuit op row across 5 columns to rediscover it. The prefix is a superset of the previously-scanned active pairs (the constructor fills op wires only over [0, num_gates) and asserts the rest are zero), so the row-skip manifest stays sound; also collapses up to active_pairs*CONCATENATION_GROUP_SIZE tiny ranges into one contiguous range per block. Verified: translator/goblin/chonk suites pass.
The translator static row-skip manifest over-covered the fixed-size translator trace and regressed the Chonk joint sumcheck (~+50% on execute_joint_sumcheck_rounds, ~2-4% slower end-to-end). The dynamic skip_entire_row scan matches baseline, so translator now uses it and the static-manifest machinery is removed: - ecc_vm keeps its contiguous active-prefix manifest (row_skip_active_prefix_end), which is tight by construction and folds correctly across all sumcheck rounds; - removed RowSkipRange / fold_row_skip_ranges / append_row_skip_range, the row_skip_ranges member, TranslatorProvingKey::compute_row_skip_ranges, and the translator branch in compute_row_skip_scan_ranges. Native EC2 Chonk A/B (vs merge-train baseline), ChonkProve: transfer_0+sponsored: 1.84s -> 1.81s; amm+sponsored: 2.05s -> 1.99s (ECCVM short-monomial win now nets faster instead of being swamped by the translator manifest regression).
# Conflicts: # barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp
The offset-generator and MSM-infinity transcript subrelations are each gated by msm_transition (1 on at most one row per MSM) but are degree-3-5 curve arithmetic computed on every active row. Reorder the base transcript subrelation enum to place these five (OFFSET_GENERATOR_X/Y, MSM_INFINITY_X_DIFF/Y_SUM/INVERSE) contiguously at indices 27-31, and split them in the short flavor into a separate ECCVMTranscriptMsmTransitionShortRelation with skip() = msm_transition.is_zero(), so the prover skips them on the overwhelming majority of rows. Keeping the group contiguous at the end preserves the global subrelation order (and thus the alpha batching) the monolithic verifier expects; legacy/verifier relation logic is unchanged (named std::get<>, uniform partial lengths). Prover-only opt: a wrong skip would only break completeness, never soundness. Also adds ECCVM_SHORT_SKIPPABLE_SPLIT_PLAN.md: an agent spec to extend this split pattern across all ECCVM short relations (MSM ADD/DOUBLE/SKEW phase split is the highest-value next step). eccvm_short_monomial_sumcheck (CPU, vs pre-split): /12 86.1->82.7, /13 134->127, /14 232->214, /15 434->403ms (-7.1%). short_prove/15 now 15.7% faster than full. Verified: eccvm_tests 45/45 (incl. ShortMonomialProverVerifies + relation corruption).
… flavor The provers no longer need to support the legacy flavor: production always uses the short-monomial sumcheck. Collapse ECCVMProver_/TranslatorProver_ and the templated TranslatorProvingKey_ to single non-templated types -- the provers bound to the short flavor, the proving key to the base flavor (it uses no relations). The legacy verifiers (native + recursive) are unchanged and still consume the identical proof/VK; existing prover tests now exercise the short path end-to-end.
…consistency with ECCVM
It links vm2/vm2_stub unconditionally, but benchmark targets are not created under the fuzzing preset (BENCH_SOURCE_FILES AND NOT FUZZING), so CMake configure fails with 'target not built by this project'. Drop the profiling harness.
iakovenkos
commented
Jun 2, 2026
iakovenkos
commented
Jun 2, 2026
notnotraju
reviewed
Jun 2, 2026
notnotraju
reviewed
Jun 3, 2026
notnotraju
reviewed
Jun 3, 2026
notnotraju
reviewed
Jun 3, 2026
notnotraju
reviewed
Jun 3, 2026
notnotraju
reviewed
Jun 3, 2026
| PartiallyEvaluatedMultivariates& dest_polynomials, | ||
| const FF& round_challenge) | ||
| { | ||
| size_t next_row_skip_active_prefix_end = 0; |
notnotraju
reviewed
Jun 3, 2026
|
|
||
| // ECCVM exposes a static row-skip manifest: a contiguous active-trace prefix that the prover can use directly | ||
| // instead of scanning every row. Translator deliberately does not (its trace over-covered when expressed as a | ||
| // static manifest); it falls back to the dynamic skip_entire_row scan below. |
Contributor
There was a problem hiding this comment.
what does the phrase "overcovered" mean? Somewhere where you talk about this "property" of a flavor, might be worth a sentence of documentation about when/when not to use it.
notnotraju
reviewed
Jun 3, 2026
| * @details Some circuits have a circuit size much larger than the number of used rows (ECCVM, Translator). | ||
| * For relevant flavors, we have a `skip_entire_row` method that can be used to check whether to skip. | ||
| * This method iterates over the execution trace & computes blocks of contiguous unskippable rows. | ||
| * Static row-manifest flavors provide the unskippable ranges directly; row-skippable flavors expose a |
Contributor
There was a problem hiding this comment.
this is helpful commentary, thanks.
notnotraju
reviewed
Jun 3, 2026
| } else { | ||
| // If so, only compute the contribution if the relation is active | ||
| if (!Relation::skip(extended_edges)) { | ||
| const auto accumulate_relation = [&]() { |
Contributor
There was a problem hiding this comment.
clearer with the lambda, thanks!
notnotraju
approved these changes
Jun 3, 2026
notnotraju
left a comment
Contributor
There was a problem hiding this comment.
few tiny comments, but looks good -- Thanks!!
This was referenced Jun 4, 2026
AztecBot
added a commit
that referenced
this pull request
Jun 8, 2026
… --ci-refresh-chonk ## What Refreshes the pinned Chonk IVC inputs (`barretenberg/cpp/scripts/chonk-inputs.hash`) so the **Nightly Debug Build** goes green again. This PR carries the `ci-refresh-chonk` label **and** a `--ci-refresh-chonk` head-commit marker. PR CI's post-action (`ci_update_chonk_inputs.sh`) regenerates the pinned inputs, uploads the new tarball to S3, verifies the smallest flow through `ChonkPinnedIvcInputsTest.AllPinnedFlows`, and pushes a follow-up commit replacing the placeholder hash in this PR with the freshly-pinned value. **Do not merge until that follow-up commit lands** — the hash here is a `0000…` placeholder until then. Supersedes the earlier closed-unmerged refresh attempt #23744; the pin is still at the 2026-05-21 value (`209dde8e69a27c9f`), so the nightly has stayed red. ## Root cause Nightly debug build run [27085031299](https://github.com/AztecProtocol/aztec-packages/actions/runs/27085031299) failed in: ``` FAILED: barretenberg/cpp/scripts/run_test.sh bbapi_tests ChonkPinnedIvcInputsTest.AllPinnedFlows (code: 1) ``` The failure is on circuit 10/10 (`hiding_kernel`) of the `deploy_ecdsar1+sponsored_fpc` pinned flow: ``` Pub inputs offset mismatch: 669 vs 673 Commitment mismatch: Q_M, Q_C, Q_L, Q_R, Q_O, Q_4, Q_5, Q_ARITH, Q_SORT, ... C++ exception: Assertion failed: (kernel_return_data_match) Reason: kernel_return_data mismatch: proof contains { 0x183227397098d014..., 0x0 } but kernel_calldata commitment is { 0x..01, 0x..02 } ``` The `hiding_kernel` circuit's public-input layout changed (offset 669 → 673, plus selector-commitment changes), so the **precomputed VK and proof baked into the pinned `ivc-inputs.msgpack` are stale**. The reconstructed `kernel_return_data` from the stale public inputs reads a sentinel `{1, 2}` (the BN254 generator, i.e. an empty databus column) instead of the real return-data commitment, tripping the consistency check. That check is `BB_ASSERT_DEBUG(kernel_return_data_match, ...)` at `barretenberg/cpp/src/barretenberg/chonk/chonk.cpp:169` — a **debug-only** assertion compiled out of release/PR CI. Only the nightly *debug* build exercises it, which is why the stale pin slips past merge-queue CI. The pin was last bumped 2026-05-21. Circuit-affecting barretenberg changes have since landed on `next` without `ci-refresh-chonk`, most notably: - #23484 *fix: harden batch chonk verifier* — adds an independent batched-SRS MSM check in `IPA::batch_reduce_verify` (`commitment_schemes/ipa/ipa.hpp`); the IPA verifier lives inside the hiding kernel, which accounts for the new public inputs and changed selector commitments. - #23615 *feat: optimize sumcheck in ECCVM and Translator*. ## Fix Regenerate and re-pin the Chonk inputs via the standard `ci-refresh-chonk` flow (this PR). No source changes are needed — the pinned fixtures just need to track the current circuits. ## Follow-up (separate) Because the assertion is debug-only, circuit changes can stale the pin with no PR-CI signal, and refresh PRs have repeatedly been opened and closed without landing. Worth deciding whether `chonk_inputs.sh check` should exercise the pinned-flow IVC with debug asserts at PR time (or whether the nightly should hard-block), so this is caught before it reaches the nightly. Tracking separately. --- *Created by [claudebox](https://claudebox.work/v2/sessions/1bec730eb3623e82) · group: `slackbot`*
spypsy
pushed a commit
that referenced
this pull request
Jun 8, 2026
# ECCVM & Translator sumcheck prover optimizations Summary of the prover-side sumcheck optimizations introduced for the ECCVM and Translator Goblin VMs (PR #23615, `feat: optimize sumcheck in ECCVM and Translator`). ## Invariant: prover-only, soundness-safe Every optimization here changes **only the prover**. The native and recursive verifiers evaluate all relations unconditionally and consume a proof and verification key **identical** to the legacy `ECCVMFlavor` / `TranslatorFlavor`. Consequences: - A faulty skip or shortened length can only break **completeness** (the honest proof fails to verify), never **soundness**. - The prover runs sumcheck on dedicated `ECCVMShortMonomialFlavor` / `TranslatorShortMonomialFlavor` classes that inherit all entity/VK definitions from the legacy flavors. `ECCVMProver`, `TranslatorProver` and `TranslatorProvingKey` are bound to these short flavors. - The edge-by-edge equivalence tests (`ShortMonomialRelationsMatchFullEdgeRelations` for both VMs) assert each short relation reproduces its legacy counterpart's per-subrelation output exactly, guarding the completeness risk. `ShortMonomialProverVerifies` runs the full short-prover → legacy-verifier roundtrip. ## The six techniques ### 1. Coefficient-basis ("short monomial") accumulation — the foundation Relations accumulate in the monomial/coefficient basis (`CoefficientAccumulator`) instead of the evaluation (Lagrange) basis. A degree-1 edge is carried as its 2 coefficients `{c0, c1}` rather than evaluations at many points, so per-edge multiplies happen on short coefficient vectors and are extended to full `Univariate` length only at the end. This is what "short" refers to. ### 2. Per-subrelation partial-length tightening The legacy flavor over-provisions every subrelation to a single conservative `MAX_PARTIAL_RELATION_LENGTH`. Each short relation overrides `SUBRELATION_PARTIAL_LENGTHS` to its true `degree + 1`: - Independent "tail" subrelations (`INACTIVE_*`, `CONTINUITY_*`, `PHASE_SELECTOR_*`, degree-2 boundary/infinity checks) shrink to their real minimum (2–5). - Subrelations that share promoted intermediates (LAMBDA, ACCUMULATOR updates, SLOPE / COLLISION groups) are deliberately kept at length 8 to preserve reuse of those intermediates. - Flavor-level `MAX_PARTIAL_RELATION_LENGTH` is unchanged, so the proof and alpha batching are identical. ### 3. Region-skip predicates per relation Each short relation carries a `skip()` predicate that short-circuits the whole relation on edges where its contribution is identically zero. The predicate must remain sound on **boundary edges** (a zero row adjacent to an active row) and on the **randomized disabled (ZK-masking) rows**. | Relation | Skip condition | Subtlety handled | |---|---|---| | ECCVM transcript (outside transcript region) | all op selectors + `msm_count` + accumulator state + boundary Lagranges zero | accumulator-state wires keep the *finalize* row live; `lagrange_third` must be included (omitting it broke an earlier attempt) | | ECCVM wnaf (outside precompute region) | `precompute_select` **and** `precompute_select_shift` both zero | the shift keeps the region's first row live | | Translator delta-range (constant sorted runs) | all 5 deltas constant over edge **and** `lagrange_real_last` zero | sorted wires are constant across runs, so `δ(δ−1)(δ−2)(δ−3)` vanishes; max-value subrelations guarded behind `lagrange_real_last` | | Translator zero-constraints | `s = lagrange_odd + lagrange_even + lagrange_mini_masking` constant over edge | also elides the large zero-padding tail that previously dominated this relation's cost | ### 4. Splitting monolithic relations to enable finer skips A single relation spanning several subtables can only skip on the global tail (already excluded by the active-prefix manifest). Splitting lets each piece carry its own region skip: - **Bools** (23 booleanity checks) → `ECCVMBoolsTranscriptShortRelation` (13 transcript-family) + `ECCVMBoolsMsmShortRelation` (10 msm/precompute-family), each skipping when its group's summed wires are zero. `w·(w−1)` has no shift, so it vanishes exactly where the wire is constant 0/1 across the edge. - **Transcript** → main relation + `ECCVMTranscriptMsmTransitionShortRelation` holding the five degree-3–5 curve-arithmetic subrelations (offset-generator, MSM-infinity) gated by `msm_transition` (active on ≤1 row per MSM), skipped via `msm_transition.is_zero()`. Both splits reorder the legacy subrelation enum so the split groups are contiguous and the global subrelation order — hence alpha batching and the proof — is preserved. (This is the renumbering in `relations/ecc_vm/ecc_msm_relation.hpp`.) ### 5. Translator permutation boundary-subrelation skip The two grand-product boundary subrelations (`lagrange_last · z_perm_shift`, `lagrange_first · z_perm`) are nonzero only on the last/first row but were computed on every edge. The prover now skips the product where the selector is identically zero, while the verifier computes unconditionally. Guarded by the accumulator type so the in-circuit recursive verifier — where branching on a witness value is invalid — never branches: ```cpp if constexpr (std::is_same_v<Accumulator, FF>) { // verifier: single point std::get<1>(accumulators) += Accumulator(lagrange_last_scaled * z_perm_shift); } else if (!in.lagrange_last.is_zero()) { // prover: skip off-boundary edges std::get<1>(accumulators) += Accumulator(lagrange_last_scaled * z_perm_shift); } ``` Lives in `relations/translator_vm/translator_permutation_short_relation_impl.hpp`. > A more aggressive variant — computing the degree-4 permutation grand-product factors via a > subproduct tree at the minimal Lagrange length (3) before extending — was committed against the > **shared** `relations/permutation_relation.hpp` and then fully reverted (commits `5e8b9063` → > `fe19ea0`). The shared file is byte-for-byte identical to baseline; only the lightweight > per-edge boundary skip above remains. Also note `perf: fold translator short relation scaling` > and `perf: pair translator short relation products` restructure the permutation factor multiplies > to share work. ### 6. Sumcheck-level row-skip scan (`sumcheck/sumcheck_round.hpp`) Instead of running `skip_entire_row` over the whole padded trace every round: - **ECCVM** exposes a *static* active-prefix manifest (`row_skip_active_prefix_end`): the prover scans only `[head, active_prefix)` plus the final Lagrange-last edge-pair. The prefix is halved each round and threaded through `PartiallyEvaluatedMultivariates` / `partially_evaluate`. It is tight by construction. - **Translator** uses the *dynamic* `skip_entire_row` scan. A static manifest was tried but over-covered the fixed-size translator trace and regressed the Chonk joint sumcheck (~+50% on `execute_joint_sumcheck_rounds`, ~2–4% end-to-end), so it was removed along with the `RowSkipRange` / `fold_row_skip_ranges` / `compute_row_skip_ranges` machinery. --------- Co-authored-by: AztecBot <tech@aztec-labs.com>
wei3erHase
pushed a commit
to defi-wonderland/aztec-packages
that referenced
this pull request
Jun 8, 2026
BEGIN_COMMIT_OVERRIDE feat: optimize sumcheck in ECCVM and Translator (AztecProtocol#23615) END_COMMIT_OVERRIDE
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.
ECCVM & Translator sumcheck prover optimizations
Summary of the prover-side sumcheck optimizations introduced for the ECCVM and Translator
Goblin VMs (PR #23615,
feat: optimize sumcheck in ECCVM and Translator).Invariant: prover-only, soundness-safe
Every optimization here changes only the prover. The native and recursive verifiers evaluate
all relations unconditionally and consume a proof and verification key identical to the legacy
ECCVMFlavor/TranslatorFlavor. Consequences:verify), never soundness.
ECCVMShortMonomialFlavor/TranslatorShortMonomialFlavorclasses that inherit all entity/VK definitions from the legacy flavors.
ECCVMProver,TranslatorProverandTranslatorProvingKeyare bound to these short flavors.ShortMonomialRelationsMatchFullEdgeRelationsfor both VMs)assert each short relation reproduces its legacy counterpart's per-subrelation output exactly,
guarding the completeness risk.
ShortMonomialProverVerifiesruns the full short-prover →legacy-verifier roundtrip.
The six techniques
1. Coefficient-basis ("short monomial") accumulation — the foundation
Relations accumulate in the monomial/coefficient basis (
CoefficientAccumulator) instead of theevaluation (Lagrange) basis. A degree-1 edge is carried as its 2 coefficients
{c0, c1}rather thanevaluations at many points, so per-edge multiplies happen on short coefficient vectors and are
extended to full
Univariatelength only at the end. This is what "short" refers to.2. Per-subrelation partial-length tightening
The legacy flavor over-provisions every subrelation to a single conservative
MAX_PARTIAL_RELATION_LENGTH. Each short relation overridesSUBRELATION_PARTIAL_LENGTHSto itstrue
degree + 1:INACTIVE_*,CONTINUITY_*,PHASE_SELECTOR_*, degree-2boundary/infinity checks) shrink to their real minimum (2–5).
groups) are deliberately kept at length 8 to preserve reuse of those intermediates.
MAX_PARTIAL_RELATION_LENGTHis unchanged, so the proof and alpha batching areidentical.
3. Region-skip predicates per relation
Each short relation carries a
skip()predicate that short-circuits the whole relation on edgeswhere its contribution is identically zero. The predicate must remain sound on boundary edges
(a zero row adjacent to an active row) and on the randomized disabled (ZK-masking) rows.
msm_count+ accumulator state + boundary Lagranges zerolagrange_thirdmust be included (omitting it broke an earlier attempt)precompute_selectandprecompute_select_shiftboth zerolagrange_real_lastzeroδ(δ−1)(δ−2)(δ−3)vanishes; max-value subrelations guarded behindlagrange_real_lasts = lagrange_odd + lagrange_even + lagrange_mini_maskingconstant over edge4. Splitting monolithic relations to enable finer skips
A single relation spanning several subtables can only skip on the global tail (already excluded by
the active-prefix manifest). Splitting lets each piece carry its own region skip:
ECCVMBoolsTranscriptShortRelation(13 transcript-family) +ECCVMBoolsMsmShortRelation(10 msm/precompute-family), each skipping when its group's summedwires are zero.
w·(w−1)has no shift, so it vanishes exactly where the wire is constant 0/1across the edge.
ECCVMTranscriptMsmTransitionShortRelationholding the fivedegree-3–5 curve-arithmetic subrelations (offset-generator, MSM-infinity) gated by
msm_transition(active on ≤1 row per MSM), skipped viamsm_transition.is_zero().Both splits reorder the legacy subrelation enum so the split groups are contiguous and the global
subrelation order — hence alpha batching and the proof — is preserved. (This is the renumbering in
relations/ecc_vm/ecc_msm_relation.hpp.)5. Translator permutation boundary-subrelation skip
The two grand-product boundary subrelations (
lagrange_last · z_perm_shift,lagrange_first · z_perm) are nonzero only on the last/first row but were computed on every edge.The prover now skips the product where the selector is identically zero, while the verifier computes
unconditionally. Guarded by the accumulator type so the in-circuit recursive verifier — where
branching on a witness value is invalid — never branches:
Lives in
relations/translator_vm/translator_permutation_short_relation_impl.hpp.6. Sumcheck-level row-skip scan (
sumcheck/sumcheck_round.hpp)Instead of running
skip_entire_rowover the whole padded trace every round:row_skip_active_prefix_end): the proverscans only
[head, active_prefix)plus the final Lagrange-last edge-pair. The prefix is halvedeach round and threaded through
PartiallyEvaluatedMultivariates/partially_evaluate. It istight by construction.
skip_entire_rowscan. A static manifest was tried butover-covered the fixed-size translator trace and regressed the Chonk joint sumcheck
(~+50% on
execute_joint_sumcheck_rounds, ~2–4% end-to-end), so it was removed along with theRowSkipRange/fold_row_skip_ranges/compute_row_skip_rangesmachinery.