Skip to content

test: natural frontload eval diverges from verifier expectation#52

Closed
kunxian-xia wants to merge 2 commits into
feat/frontloadfrom
test/frontload-natural-eval-check
Closed

test: natural frontload eval diverges from verifier expectation#52
kunxian-xia wants to merge 2 commits into
feat/frontloadfrom
test/frontload-natural-eval-check

Conversation

@kunxian-xia

Copy link
Copy Markdown
Collaborator

Summary

These tests demonstrate that the fix in #51 does not resolve the underlying frontload medium-MLE bug (#50). The core issue: for Normal MLEs with num_vars > log2(workers) but num_vars < max_num_variables, the prover produces worker-count-dependent round polynomials instead of the correct worker-count-independent ones.

Two failing tests added:

  • test_frontload_2phase_sum_keeps_small_mle_compact: adds a 5-var medium MLE alongside the existing 8-var large and 2-var small. The round polynomial diverges at round 3 because mle_round_endpoints uses tail factors (s_w * x) instead of eq-weighted contributions (s_w * eq(x, worker_bit)) for rounds past the local chunk size.

  • test_random_monimials_use_frontload_sum: adds a natural frontload::evaluate check (worker-count-independent) alongside the existing worker_aware_frontload_evaluate. The natural evaluation disagrees with the verifier's expected evaluation, showing the protocol result depends on num_threads — an implementation detail that should not affect soundness.

Why worker_aware_frontload_evaluate masks the bug

worker_aware_frontload_evaluate reorders MLE variables to match the worker-aware split, making the evaluation oracle agree with the (wrong) prover output. This makes the verifier check pass, but the polynomial being sumchecked is no longer f(x_0,...,x_{k-1}) * ∏_{i≥k} x_i — it's a different, worker-layout-dependent polynomial. The correct fix must be in the prover's round polynomial computation, not in the evaluation oracle.

Test plan

  • Run cargo test -p sumcheck --lib -- test_random_monimials_use_frontload_sum — expected FAIL
  • Run cargo test -p sumcheck --lib -- test_frontload_2phase_sum_keeps_small_mle_compact — expected FAIL
  • Both tests should pass once the prover is correctly fixed

🤖 Generated with Claude Code

Two test changes that expose the medium-MLE round polynomial bug:

1. test_frontload_2phase_sum_keeps_small_mle_compact: add a 5-var medium
   MLE alongside the 8-var large and 2-var small. This triggers round
   polynomial divergence at round 3 where the prover uses tail factors
   instead of eq-weighted contributions for Normal MLEs.

2. test_random_monimials_use_frontload_sum: add a natural
   frontload::evaluate check (worker-count-independent) alongside the
   existing worker_aware_frontload_evaluate. The natural evaluation
   disagrees with the verifier's expected_evaluation, showing the
   protocol produces worker-count-dependent results.

Both tests fail, demonstrating that worker_aware_frontload_evaluate
masks the underlying bug by matching the wrong prover behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kunxian-xia

Copy link
Copy Markdown
Collaborator Author

@copilot come up with a plan to fix the bugs. you have to think with max effort, you have to understand the root cause, and then still follow the ideal prover workflow by splitting MLEs into chunks and dispatch them to each worker thread. The key idea is to think when the local chunk has halved into one scalar (e.g. local_chunk has 2 vars, but the phase 1 has 4 variables), how to derive the round polynomial contribution by merging each worker's local round polynomial together.

Copilot AI commented May 8, 2026

Copy link
Copy Markdown
Contributor

@copilot come up with a plan to fix the bugs. you have to think with max effort, you have to understand the root cause, and then still follow the ideal prover workflow by splitting MLEs into chunks an...

Plan (based on 9f5a120): root cause is that after a Normal MLE’s local chunk is exhausted, phase-1 treats remaining rounds as pure tail s_w * z (as if worker bit were always 1). This drops the worker-bit interpolation and makes round polys depend on worker layout. Fix plan:

  1. Separate “worker-bit rounds” from “true frontload-tail rounds” using global MLE arity (global_mle_num_vars), not local chunk arity.
  2. In mle_round_endpoints, for local_num_vars <= round < global_mle_num_vars, emit endpoints from worker bit b at that round: b=0 -> (s_w, 0), b=1 -> (0, s_w) (i.e. s_w * eq(z,b)), not (0, s_w).
  3. Keep (0, s_w) only for rounds round >= global_mle_num_vars (actual frontload tail).
  4. Update frontload-mask logic (required_future_frontload_mask / frontload_tail_start) so only variables at/after global tail start are forced to 1; worker-bit rounds must not be forced as tail.
  5. Keep the current chunked-per-worker workflow: workers still fold local chunks independently; merge happens algebraically by summing worker round contributions that now carry correct worker-bit basis factors.
  6. Validate with the two new failing tests + existing frontload combination tests; then run sumcheck crate tests/lints to ensure no regressions.

@kunxian-xia

Copy link
Copy Markdown
Collaborator Author

@copilot come up with a plan to fix the bugs. you have to think with max effort, you have to understand the root cause, and then still follow the ideal prover workflow by splitting MLEs into chunks an...

Plan (based on 9f5a120): root cause is that after a Normal MLE’s local chunk is exhausted, phase-1 treats remaining rounds as pure tail s_w * z (as if worker bit were always 1). This drops the worker-bit interpolation and makes round polys depend on worker layout. Fix plan:

  1. Separate “worker-bit rounds” from “true frontload-tail rounds” using global MLE arity (global_mle_num_vars), not local chunk arity.
  2. In mle_round_endpoints, for local_num_vars <= round < global_mle_num_vars, emit endpoints from worker bit b at that round: b=0 -> (s_w, 0), b=1 -> (0, s_w) (i.e. s_w * eq(z,b)), not (0, s_w).
  3. Keep (0, s_w) only for rounds round >= global_mle_num_vars (actual frontload tail).
  4. Update frontload-mask logic (required_future_frontload_mask / frontload_tail_start) so only variables at/after global tail start are forced to 1; worker-bit rounds must not be forced as tail.
  5. Keep the current chunked-per-worker workflow: workers still fold local chunks independently; merge happens algebraically by summing worker round contributions that now carry correct worker-bit basis factors.
  6. Validate with the two new failing tests + existing frontload combination tests; then run sumcheck crate tests/lints to ensure no regressions.

implement the fix please.

…e merge semantics

Agent-Logs-Url: https://github.com/scroll-tech/gkr-backend/sessions/bcd95224-91d9-4367-b959-6d2af6044f70

Co-authored-by: kunxian-xia <1082586+kunxian-xia@users.noreply.github.com>
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