chore!: masking at the top of the trace#22334
Merged
notnotraju merged 58 commits intoApr 21, 2026
Merged
Conversation
…ay from RDP
With top-of-trace masking, the row-disabling polynomial 1 - ∏_{i≥2}(1-u_i)
is circuit-size independent. The verifier evaluates it over ALL D challenges
without needing log_circuit_size or padding_indicator_array.
Prover: ZK virtual rounds now use compute_virtual_contribution * (1-L) + libra
instead of sending zero univariates. Libra univariates cover all D rounds.
Verifier: apply_zk_corrections evaluates RDP from challenge vector size.
compute_padding_indicator_array returns all-1s (unified path).
…i/eccvm-lagrange-last-integer
…i/eccvm-lagrange-last-integer
notnotraju
reviewed
Apr 16, 2026
| MegaExecutionTraceBlocks() = default; | ||
|
|
||
| void compute_offsets() | ||
| void compute_offsets(size_t trace_offset = TRACE_OFFSET) |
Contributor
There was a problem hiding this comment.
at l. 305 in this file (meta_execution_trace.hpp), stale comment
notnotraju
reviewed
Apr 16, 2026
added 2 commits
April 17, 2026 12:00
- Add merge_constants.hpp with MERGE_FULL_SHIFT and MERGE_APPEND_OUTPUT_SHIFT; merge_prover and merge_verifier now reference the shared constants instead of duplicating the formulas. - Add static_assert in merge_prover.cpp that MERGE_APPEND_OUTPUT_SHIFT equals TranslatorFlavor::RANDOMNESS_START, since [M] is copy-constrained with the Translator's op queue wire commitments. - Rewrite stale doc comments in mega_execution_trace.hpp (ecc_op-first requirement, now explained via merge shift) and constants.hpp (masking row range).
…R_OP The reserved op-slot count at the start of the merged polynomial MUST be APPEND_OUTPUT_SHIFT / NUM_ROWS_PER_OP. The previous formula subtracted NUM_ZERO_ROWS, which was numerically equal by coincidence. Add a static_assert that APPEND_OUTPUT_SHIFT is a multiple of NUM_ROWS_PER_OP.
notnotraju
reviewed
Apr 17, 2026
| @@ -0,0 +1,25 @@ | |||
| // === AUDIT STATUS === | |||
Contributor
There was a problem hiding this comment.
Just added this for my own peace of mind.
notnotraju
reviewed
Apr 17, 2026
|
|
||
| namespace bb { | ||
|
|
||
| static_assert(MERGE_APPEND_OUTPUT_SHIFT == TranslatorFlavor::RANDOMNESS_START, |
Contributor
There was a problem hiding this comment.
More static asserts can't hurt. (I was trying to figure out how everything matched.)
notnotraju
reviewed
Apr 17, 2026
| static_assert(MERGE_APPEND_OUTPUT_SHIFT % UltraEccOpsTable::NUM_ROWS_PER_OP == 0, | ||
| "MERGE_APPEND_OUTPUT_SHIFT must be a multiple of NUM_ROWS_PER_OP so that ops land " | ||
| "on even row boundaries after the shift"); | ||
| constexpr size_t reserved_op_slots = MERGE_APPEND_OUTPUT_SHIFT / UltraEccOpsTable::NUM_ROWS_PER_OP; |
Contributor
There was a problem hiding this comment.
small change here, to make it clear what the synthetic meaning of the constants is.
Add a "Trace Layout Alignment" section covering the Mega circuit preamble, the Translator mini-circuit preamble, and MegaAvmFlavor, with row-by-row diagrams and the constants tying them together (MERGE_FULL_SHIFT, MERGE_APPEND_OUTPUT_SHIFT = RANDOMNESS_START).
notnotraju
reviewed
Apr 20, 2026
| - $R_j = t_j$ (current subtable) | ||
| - New operations are added at the end (with optional fixed offset) | ||
|
|
||
| ## Trace Layout Alignment |
Contributor
There was a problem hiding this comment.
@iakovenkos I added this section on what the trace physically looks like, can you give it a quick look?
…i/eccvm-lagrange-last-integer
iakovenkos
commented
Apr 21, 2026
| // masked; its read_counts column is. | ||
| auto& values_poly = entities[0]; | ||
| auto& read_counts_poly = entities[1]; | ||
| if constexpr (bus_idx != 0) { |
Contributor
Author
There was a problem hiding this comment.
@federicobarbacovi does it look reasonable to you?
Contributor
There was a problem hiding this comment.
Yes, it looks good 👍
dipkakwani
pushed a commit
to dipkakwani/aztec-packages
that referenced
this pull request
Apr 22, 2026
BEGIN_COMMIT_OVERRIDE chore!: masking at the top of the trace (AztecProtocol#22334) chore: Fix translator's static assert (AztecProtocol#22695) chore: bump mem for large circuit test (AztecProtocol#22690) END_COMMIT_OVERRIDE
This was referenced Apr 24, 2026
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.
Summary
Motivation
Previously, ZK masking used tail masking: random values were stored in separate
MaskingTailDatapolynomials at the end of the trace. This forced all PCS code to bedyadic_sizedependent — the batched polynomialA₀, Gemini folds, and Shplonk quotient all had to be allocated and operated atdyadic_sizebecause the masking tails extended to the last rows. The row-disabling polynomial was also circuit-size dependent (1 - L_{n-1} - ... - L_{n-4}), requiring apadding_indicator_arrayto handle padded sumcheck rounds.What Changed
Top-of-trace masking: Random masking values are written directly into witness polynomials at rows
{1, 2, 3}during allocation. The row-disabling polynomial disables the first 4 rows (0–3) instead of the last 4.lagrange_firstmoves from row0to rowTRACE_OFFSET (= 4).Key Benefits
dyadic_size: With masking at low indices, committed polynomials only extend tomax_end_index()(the actual trace extent), notdyadic_size. Gemini fold polynomials already trackactual_sizefromA_0.end_index(). This enables future non-dyadic PCS proving where sparse circuits avoid paying for the full power-of-2 padding.1 - ∏_{i≥2}(1-u_i)depends only on sumcheck challenges, not circuit size. Thepadding_indicator_arrayis eliminated.MaskingTailData(218 lines),padding_indicator_array(93+134 lines), and all tail-batching logic. Net-707lines across 103 files.padding_indicator_arrayparameters. This simplifies native, recursive, and AVM verifier flows alike.Merge Protocol and ECC Op Wire Changes
Moving
lagrange_firstfrom row0to rowTRACE_OFFSET (= 4)shifts the entire execution trace down by 4 rows. In Mega, theecc_opblock now starts attrace_offset() = TRACE_OFFSET + 1 = 5, andecc_op_wiredata sits one row before at rowTRACE_OFFSET = 4(to satisfy theecc_op_wire[row] == w_shift[row]constraint).The merge protocol must match this layout: it prepends
TRACE_OFFSETzeros to its table polynomials (L,R, andMin PREPEND mode) so that the prover's Shplonk quotient is consistent with theecc_op_wirecommitments held by the verifier. Previously, these polynomials started at row0; now they start at rowTRACE_OFFSETto align with the shifted circuit layout.The Translator receives its op queue data from Mega's
ecc_op_wires. Since the merge protocol handles the offset alignment in chonk, standard Mega → Translator flows work correctly. However, the two-layer AVM flow (AVM recursive verifier inside a Mega circuit) required addingTRACE_OFFSET = 0to the standalone AVM flavor. TheMegaAVMflavor inherits Mega'sTRACE_OFFSET = 4, soecc_op_wiresin the outer Mega circuit are offset. The inner AVM has no disabled region (TRACE_OFFSET = 0), but since it runs inside a Mega wrapper that handles the merge protocol, the op queue data alignment stays consistent across the boundary.Files Changed (103 files, +1484/-2191)
Deleted
sumcheck/masking_tail_data.hpp— tail masking infrastructurestdlib/primitives/padding_indicator_array/— virtual-round indicator for old row-disablingAdded
ultra_honk/zk_boundary.test.cpp— tests for masking layout,ecc_opalignment, row-disablingCore changes
prover_instance.cpp): Polynomials allocated withadd_masking()at rows{1,2,3};lagrange_firstatTRACE_OFFSET; trace blocks start atTRACE_OFFSET + 1oink_prover.cpp): Removed all tail references; commitments use base polynomials directlyultra_prover.cpp): CRS sized tomax_end_index()instead ofdyadic_size()for ZKeccvm_flavor.hpp): Polynomial allocation with trace offset; Lagrange polys shiftedeccvm_prover.cpp): Removed tail batching andextend_with_tailcopies for translation polyssumcheck.hpp): Unified ZK/non-ZK virtual round paths; removedpadding_indicator_arrayfrom verifierrow_disabling_polynomial.hpp): Simplified to1 - ∏_{i≥2}(1-u_i)gemini_impl.hpp): Fold polynomials trackactual_sizefromA_0.end_index()shplemini.hpp): Removedpadding_indicator_arrayfromcompute_batch_opening_claimvm2/constraining/): Removedpadding_indicator_arrayfrom native and recursive AVM verifiers; addedTRACE_OFFSET = 0to AVM flavormerge_prover.cpp/hpp,merge_verifier.cpp/hpp): PrependsTRACE_OFFSETzeros to table polynomials; verifier accounts for offset in commitment checksgp_start/start_indexparametersdatabus.hpp):DEFAULT_VALUE = 0(point-at-infinity commitment matches default)Known Issues / Follow-ups