Skip to content

Quotient matrix - #67

Merged
gabriel-barrett merged 2 commits into
mainfrom
quotient-matrix
Jul 24, 2026
Merged

Quotient matrix#67
gabriel-barrett merged 2 commits into
mainfrom
quotient-matrix

Conversation

@gabriel-barrett

Copy link
Copy Markdown
Member

Commit quotient slices as one matrix per circuit

Changes how the quotient polynomial is committed: instead of one matrix per
degree-n chunk on the split sub-cosets, each circuit's quotient is sliced by
coefficientsQ(X) = Σᵢ X^{i·n}·cᵢ(X), each cᵢ of degree < n — and
all q slices are committed as a single q·D-column matrix on the trace
domain
, opened once at ζ.

Motivation

The opening phase's dominant costs are per-matrix and width-independent:
barycentric evaluation, the (p(x) − y)/(x − ζ) reduction that feeds FRI, and
per-query row extraction each walk the full LDE height once per matrix,
regardless of how many columns the matrix has. Under the old layout a circuit
contributed q quotient matrices, so raising the quotient degree multiplied
exactly the work these passes do. Profiling an Aiur-scale system (~500
circuits, quotient degree 4) showed the per-matrix passes were ~80% of
fri_open, scaling linearly with quotient matrix count — while the committed
area barely changed.

The same disease affected the commit side (one LDE/Merkle pipeline invocation
per tiny D-column chunk) and even the proof size: every matrix in a query's
batch opening carries its own length-prefixed vector, ~8 bytes × matrices ×
queries of pure framing.

The change

Prover (prove_multiple_claims): after the constraint sweep produces the
quotient's evaluations on the size-q·n coset, interpolate once (coset iDFT),
slice the coefficient vector into q degree-< n polynomials, and evaluate
the sliced n × q·D matrix back onto the trace domain (one size-n DFT).
The evaluation sweep itself — the expensive part — is untouched; the added
transform work is on q·D columns and is negligible. Requires a
TwoAdicField bound on the prover's Val, which every FRI-based
configuration satisfies.

Opening round: the quotient round now has exactly one entry per active
circuit (same shape as stages 1 and 2), instead of q chunk entries per
circuit.

Verifier: the sub-domain Lagrange recombination — the zps products of
vanishing polynomials over the split cosets — collapses to a power series:

Q(ζ) = Σᵢ ζ^{i·n} · cᵢ(ζ)

with each cᵢ(ζ) read from column-slices of the one wide matrix. This is
both cheaper natively and substantially simpler to port to a recursive
verifier. Shape checks change accordingly (one opened row of q·D values per
circuit at the single point ζ).

Soundness is unchanged: each slice is individually degree-bound < n by FRI
(same bound as before), the recombination identity is exact, and the layout
is bound into the transcript through the commitment.

Breaking changes

  • Commitment layout, transcript, and proof shape change: proofs from earlier
    versions no longer verify. The quotient round of Proof::quotient_opened_values
    now carries one entry per active circuit (a q·D-value row at ζ).
  • Downstream verifiers (including recursive ones) must switch the quotient
    recombination from the sub-domain zps formula to the ζ^{i·n} power
    series.

Testing

The full test suite passes on top of the change (lookup systems, sparse
activation, high-degree circuits, adversarial/tamper tests, serialization
round-trip), and it is exercised end to end downstream by the Ix/Aiur proving
suites (70 prove/verify cases plus BLAKE3/SHA-256 circuits and IxVM kernel
checks).

Slice the quotient by COEFFICIENTS — Q(X) = sum_i X^(i*n) * c_i(X) with
each c_i of degree < n — and commit all q slices of a circuit as a
single q*D-column matrix on the trace domain, instead of one matrix per
slice on the split sub-cosets.

The opening phase pays several per-matrix, per-row costs that are
independent of matrix width (barycentric evaluation, the (p(x) - y)/(x - z)
FRI-input reduction, row extraction per query), so q matrices per
circuit multiplied the dominant fri_open work by q. Measured on an
IxVM-scale system, the per-matrix passes accounted for ~80% of fri_open
and scaled directly with quotient matrix count. One matrix per circuit
makes that cost independent of the quotient degree.

The verifier gets simpler too: the sub-domain Lagrange recombination
(the zps product over vanishing polynomials) becomes a plain power
series, Q(zeta) = sum_i zeta^(i*n) * c_i(zeta) — also cheaper to port to
the recursive verifier.

Prover-side, slicing coefficients requires interpolating the quotient
once (coset iDFT of the q*n evaluations, then a size-n DFT of the sliced
matrix onto the trace domain) — transform work on q*D columns, negligible
against the constraint-evaluation sweep. This adds a TwoAdicField bound
on the prover's Val, which every FRI-based configuration satisfies.

Breaking change: commitment layout, transcript, and proof shape (the
quotient round carries one wide matrix per active circuit).
The repo is sometimes checked out inside another cargo workspace (e.g. the
ix monorepo), whose manifest would otherwise absorb this package and break
standalone builds. An empty [workspace] table keeps the package
self-contained.
@gabriel-barrett

Copy link
Copy Markdown
Member Author

!benchmark

@gabriel-barrett
gabriel-barrett merged commit 40092c1 into main Jul 24, 2026
6 checks passed
@gabriel-barrett
gabriel-barrett deleted the quotient-matrix branch July 24, 2026 15:34
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