Skip to content

fix(bb): pad gemini_masking_poly size to even to avoid sumcheck OOB#22789

Closed
AztecBot wants to merge 1 commit intonextfrom
claudebox/fix-bb-nightly-debug-build
Closed

fix(bb): pad gemini_masking_poly size to even to avoid sumcheck OOB#22789
AztecBot wants to merge 1 commit intonextfrom
claudebox/fix-bb-nightly-debug-build

Conversation

@AztecBot
Copy link
Copy Markdown
Collaborator

Summary

Fixes the nightly barretenberg debug build (https://github.com/AztecProtocol/aztec-packages/actions/workflows/barretenberg-nightly-debug-build.yml), which has been failing since 2026-04-22 with:

Assertion failed: (index < virtual_size_ + virtual_padding)

in HonkRecursionConstraintTestWithoutPredicate/1.GenerateVKFromConstraints (UltraZK).

Root cause

OinkProver::commit_to_masking_poly sized gemini_masking_poly to exactly polynomials.max_end_index(). When that value is odd, the polynomial's virtual_size ends up odd as well.

SumcheckProverRound::compute_effective_round_size rounds max_end_index up to the next even number so sumcheck can iterate edge pairs (0, 1), (2, 3), …. extend_edges then accesses multivariate[edge_idx + 1] for every polynomial in multivariates.get_all(), including gemini_masking_poly. With the masking poly's virtual_size one short of the rounded-up effective size, that final read goes one past the end and trips the debug assertion.

Witness/precomputed polynomials are sized to dyadic_size() and stay in bounds; only gemini_masking_poly was off because it intentionally tracks the active extent rather than the full dyadic size.

In release builds the assertion is a no-op and get(...) falls through to the static-zero branch (since the index sits exactly at end_), so the bug silently returned 0 — gemini_masking_poly is not referenced by any sumcheck relation, so the spurious read had no effect on proof correctness. The debug-only failure surfaced via the nightly debug build.

Fix

Round polynomial_size up to the next even value so the masking polynomial's virtual_size is at least compute_effective_round_size(...) — at most one extra random field element when max_end_index is odd.

const size_t max_end_index = prover_instance->polynomials.max_end_index();
const size_t polynomial_size = max_end_index + (max_end_index % 2);
prover_instance->polynomials.gemini_masking_poly = Polynomial<FF>::random(polynomial_size);

The verifier's view is unchanged: the masking polynomial is opaque, consumed only via its commitment and sumcheck evaluation. The other gemini_masking_poly = Polynomial::random(circuit_size) callers (eccvm_prover.cpp, translator_prover.cpp) pass a power-of-two circuit_size and don't need the change.

Detailed analysis (stack trace, regression window, debugging steps): https://gist.github.com/AztecBot/08bcebe7902e7201ad193c8e6acad491

Test plan

  • Reproduce on next HEAD a4ac021356: HonkRecursionConstraintTestWithoutPredicate/1.GenerateVKFromConstraints aborts in extend_edges with index=4135 == virtual_size_=4135.
  • After fix, debug-build local run of dsl_tests:
    • HonkRecursionConstraintTestWithoutPredicate/0.GenerateVKFromConstraints — PASSED
    • HonkRecursionConstraintTestWithoutPredicate/1.GenerateVKFromConstraints — PASSED (was failing)
  • Full nightly debug build (ci-barretenberg-debug) green via CI.

ClaudeBox log: https://claudebox.work/s/94d26399d9c5dec5?run=1

@AztecBot AztecBot added ci-draft Run CI on draft PRs. claudebox Owned by claudebox. it can push to this PR. labels Apr 25, 2026
@AztecBot
Copy link
Copy Markdown
Collaborator Author

Automatically closing this stale claudebox draft PR (no updates for 5+ days). Re-open if still needed.

@AztecBot AztecBot closed this Apr 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-draft Run CI on draft PRs. claudebox Owned by claudebox. it can push to this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant