Skip to content

fix: handle partial-live frontload phase2 mles#53

Merged
kunxian-xia merged 3 commits into
mainfrom
feat/frontload
May 9, 2026
Merged

fix: handle partial-live frontload phase2 mles#53
kunxian-xia merged 3 commits into
mainfrom
feat/frontload

Conversation

@hero78119
Copy link
Copy Markdown
Collaborator

@hero78119 hero78119 commented May 8, 2026

Problem

Frontload two-phase sumcheck still missed one valid Normal MLE shape:

N = global num vars
w = log2(num_workers)
L = N - w
k = MLE canonical num vars

The previous implementation handled:

Case Condition Phase-2 shape
Exhausted in phase 1 k <= L compact constant
Fully live in phase 2 k == N full worker-index MLE

It did not handle the middle case:

L < k < N

Example from the regression:

N = 6, w = 2, L = 4, k = 5
phase 1 vars: x0..x3
phase 2 vars: x4,x5
local chunk vars: x0..x2
worker-bit canonical vars: x3,x4
true tail vars: x5

Here one worker-bit canonical variable is already bound in phase 1 (x3), while one remains live in phase 2 (x4). Treating this as either fully exhausted or fully live produces incorrect phase-2 polynomial construction.

A related API issue was that frontload two-phase final evaluations could expose proof-internal tail factors. Consumers such as Ceno expect raw canonical MLE openings:

mle(r0..r{k-1})

not:

mle(r0..r{k-1}) * product(r{k}..r{phase1_end-1})

Approach

Keep the full 2^w worker split, and encapsulate the partial-live logic only in build_phase2_poly.

At the phase boundary each worker has a folded scalar:

s_b = e_b(bound local vars) * bound_eq_for_phase1_worker_bits * phase1_tail

build_phase2_poly now handles three canonical cases:

Case Condition Construction
Exhausted k <= L phase2_mle[0] = sum_b s_b
Partial-live L < k < N aggregate workers with the same live phase-2 suffix
Fully live k == N phase2_mle[b] = s_b

For the partial-live case:

remaining = k - L          // live canonical phase-2 worker bits
bound = w - remaining      // worker bits already bound in phase 1
worker_id = (bound_prefix, live_suffix)

phase2_mle[live_suffix] = sum_bound_prefix s_{bound_prefix, live_suffix}

Then normal frontload phase 2 evaluates:

phase2_mle(x_L..x{k-1}) * product_{i=k}^{N-1} x_i

So the verifier remains canonical:

e(x0..x{k-1}) * product_{i=k}^{N-1} x_i

No verifier-side knowledge of worker layout is introduced.

Side Note: Raw Final-Eval Contract

get_mle_flatten_final_evaluations() now exposes raw canonical MLE openings for frontload:

mle(r0..r{k-1})

It excludes all true frontload tail factors. This lets consumers reconstruct the sumcheck subclaim with the same canonical frontload tail rule used by the verifier.

Implementation details:

  • Proof construction remains unchanged.
  • After phase 2, frontload normalizes final evaluations by dividing out baked phase-1 true tail factors for k < L.
  • This intentionally assumes Fiat-Shamir challenges are nonzero, matching the protocol assumption used elsewhere in this codebase.
  • The old frontload::evaluate(poly, point) helper was removed to avoid hiding raw-vs-tail behavior.
  • frontload::evaluate(poly, point, raw_mle_evals) now explicitly reconstructs the full canonical frontload polynomial from raw MLE openings plus tail factors.

Testing

Command Result
cargo fmt --check Pass
cargo test -p sumcheck Pass: 12 passed; 0 failed
cargo test -p sumcheck --lib -- test_frontload_2phase_mle_category_combinations --nocapture Pass

Regression coverage:

  • Adds normal_live_in_phase2_with_tail (k=5 when N=6) to test_frontload_2phase_mle_category_combinations.
  • Runs category combinations across log_num_workers = 0..=3, i.e. num_threads = 1,2,4,8.
  • Keeps direct proof-round equality checks against single-worker canonical frontload.
  • Verifies frontload final evals equal raw canonical MLE openings.
  • Verifies frontload::evaluate(poly, point, raw_mle_evals) reconstructs subclaim.expected_evaluation from those raw openings.

Benchmark / Performance Impact

Command:

cargo bench -p sumcheck --bench devirgo_sumcheck -- 'mixed_sum_nv_22_16_2/(frontload_compact_a_plus_b_plus_c|suffix_phase2_a_plus_b_plus_c)|mixed_product_sum_nv_22_16_2/(frontload_compact_product_sum|suffix_phase2_product_sum)'

Before = previous local refactor commit 6c74b7d.
After = partial-live fix commit 83d0108 / current PR branch state with the same proof-generation path.

Benchmark Before After Delta
mixed_sum_nv_22_16_2/frontload 20.102 ms 18.529 ms 1.08x faster
mixed_product_sum_nv_22_16_2/frontload 49.139 ms 58.403 ms 1.19x slower

Current frontload vs suffix:

Benchmark Suffix mean Frontload mean Frontload speedup
mixed_sum_nv_22_16_2 72.132 ms 18.529 ms 3.89x
mixed_product_sum_nv_22_16_2 223.23 ms 58.403 ms 3.82x

The final-eval normalization/API change is postprocessing and does not alter proof round construction. Frontload remains faster than suffix in the measured mixed sum/product cases.

Risk / Rollout

Risk Mitigation
Partial-live Normal soundness New normal_live_in_phase2_with_tail regression covers L < k < N.
Worker-count edge cases Category combinations now run for num_threads = 1,2,4,8.
Canonical verifier relation Tests compare two-phase proof rounds and final evaluation against canonical single-worker frontload.
Raw final-eval contract Tests verify final evals are raw MLE openings and reconstruct subclaim.expected_evaluation only after applying canonical tails.
Performance regression Benchmarks reported above; frontload remains faster than suffix in measured mixed sum/product cases.
Compatibility Suffix prover remains available through prove_suffix.

Rollback is to route affected callers back to prove_suffix or revert this PR.

Copilot Reviewer Directive (keep this section)

When Copilot reviews this PR, apply .github/copilot-instructions.md strictly.

  • Perform review only; do not commit/push/propose code changes.
  • Prefer inline comments on changed lines for each actionable finding.
  • If inline comments are unavailable, use [severity] path:line (symbol) format.
  • Prioritize soundness, performance, and architecture risks over style.
  • Output order: findings by severity, then open questions, then brief summary.
  • If PR description is empty or missing key context, report PR metadata: description as a finding.

Comment thread crates/sumcheck/src/test.rs Outdated
@kunxian-xia kunxian-xia merged commit eda8eab into main May 9, 2026
2 checks passed
@kunxian-xia kunxian-xia deleted the feat/frontload branch May 9, 2026 01:13
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.

2 participants