Our efficient prover implementation of our univariate skip variant
Here, we explain our optimized prover implementation of our univariate skip variant. Essentially, the problem is to combine Gruen [Gru24, § 5.1] and both Dao–Thaler works [DT24a, DT24b] in a way that lets the prover do as much work as possible in the small Rijndael field. We also use a lookup-based NTT like Hu et al. [Hu+25]'s.
As we've already seen, we use deterministic Rijndael elements as the verifier's first three challenges. These "saturate" the Rijndael field. We further use an "uneven" variant of [DT24b], in which the inner loop—of size just 8—operates entirely over the Rijndael field. Every 8 cube points, the prover embeds into F2128 and accumulates.
The Problem
We recall that the prover's goal is to evaluate the polynomial
In this page, we describe a highly optimized implementation, which strategically uses the Rijndael field "where possible". We call our algorithm the Rijndael zerocheck.
The Underlying Arrays
Our prover algorithm below makes use of the constraint arraysa, b and c. As we have seen, there is a straightforward way that the prover can compute these, on input his witness w and the constraint system.
Efficient Lookup-Based Extrapolation
Thus far, we have let D⊂F2128 be an arbitrary 6-dimensional subspace. Now, we enforce that D⊂F28⊂F2128. We write D′⊂F2128 for a further linear subspace, now of dimension 7 over F2. We require that D′⊂F28 too, so we have a chain of inclusions
D⊂D′⊂F28⊂F2128.
This condition is not hard to set up (we can construct both subspaces in K, and embed them).
Finally, we prepare one more step. Below, we will need the mapping
Extrap:F264→F2864
that extrapolates a bitstring from D to D′∖D. On the other hand, we want to work in the Rijndael field K, so we need to inverse-embed each element of the result.
On input a 64-bit word (p0,…,p63), Extrap interprets that word as the values that some univariate polynomial P(I), of degree less than 64, takes on D⊂F2128. (I.e., this P(I) happens to take F2-valued values on D.) This data specifies P(I) uniquely, as a polynomial in F2128[I]≺64. Finally, Extrap maps:
Extrap:(p0,…,p63)↦(ι−1(P(i)))i∈D′∖D.
Since D′⊂F28⊂F2128 and P(I) is bit-valued on D, P(I)'s values on D′ themselves live in F28⊂F2128. I.e., the evaluations P(i) for i∈D′∖D live in the image of ι, and ι−1(P(i)) is well-defined. This means that each output Extrap(p0,…,p63) is an element of K64≅F2864.
By the way, it would have been equivalent if we had defined Extrap as the function that extrapolates a bit-vector (p0,…,p63) from ι−1(D) to ι−1(D′∖D) in K. Showing the equivalence of that definition with ours is a short exercise. The way we did it turns out to be easier to work with below.
Since Extrap is F2-linear, we can implement it in the following efficient way, using precomputation. We break the input (p0,…,p63) into 8 length-8 chunks. For each chunk, we precompute a length-256 table containing all 256 evaluations of Extrap on input strings that are nonzero just on that chunk. The total data size is thus 8⋅256⋅64⋅8 bits, or 128 KiB. To evaluate Extrap on some input (p0,…,p63), we must do 8 lookups and 7 length-64 bytewise XORs.
The Algorithm
We have already seen that the prover must evaluate g(I) on 2k−1 points outside of D. Thus it's enough for the prover to evaluate g(I) on D′∖D.
We proceed with the prover's algorithm. The prover's inputs are the constraint arrays a, b and c and the verifier's partially-deterministic challenge rx=(σ0,σ1,σ2,rx,0,…,rx,ℓand−4), as well as the fixed Rijndael field elementsρ0, ρ1, ρ2, and the precomputed mapping Extrap above.
initialize an empty accumulator array of 64F2128-elements, say g.
tensor-expand rx; i.e., compute the array (eq(rx,v))v∈Bℓand−3.
for each v∈Bℓand−3do:
initialize an all-zero accumulator of 64 K-elements (i.e. bytes), say temp.
for each u∈B3do:
let x:=u∥v.
define a:=Extrap(a[x]), b:=Extrap(b[x]) and c:=Extrap(c[x]).
for each i∈{0,…,63}, update temp[i]+=(a[i]⋅b[i]−c[i])⋅eq(ρ,u).
for each i∈{0,…,63}, update g+=ι(temp[i])⋅eq(rx,v).
return g.
We claim that the array g returned by this algorithm contains exactly the values of g(i) for i∈D′∖D, which is what we want.
The above protocol is very efficient. Every 8th iteration, we have to do 64 K→F2128embeddings and 64 multiplications in F2128. "Between" iterations, we work entirely in K. The breakup of our sum into outer and inner loops above can be viewed as a variant of an idea of Dao and Thaler [DT24b] (i.e., separate from the use of deterministic challenges).
Correctness
The correctness of the above algorithm is not completely obvious. It relies on the following nested sum expression (recall also the analysis done here). For each i∈D′∖D,
For each pair of outer and inner loop indices v∈Bℓand−3 and u∈B3, the arrays a, b and c contain the isomorphic inverses under ι of a(i,x), b(i,x) and c(i,x), respectively, for i∈D′∖D, by definition of Extrap. As of the end of the inner loop, then, the accumulator temp will contain:
Here, we use the fact that ι−1:F28→K is a ring homomorphism. Upon applying ι (in the forward direction) componentwise to this vector and then multiplying eq(rx,v) componentwise, we get:
which is exactly the vth summand of the sum expression above.
The Univariate Specialization
As we already saw, after the prover sends g(I), the verifier will sample a single scalar ri←F2128 and send it to the prover. The parties' "cubular" sumcheck will be run on
To prepare this sumcheck, the prover needs to prepare the tables of values of the partially specialized ℓand-variate multilinears a(ri,X), b(ri,X) and c(ri,X) on Bℓand. As we saw above, the tables of values of these latter oblong-multilinears are just the constraint arrays a, b and c. How do the tables of values of a(ri′,X), b(ri′,X) and c(ri′,X) on Bℓand relate to a, b and c?
We have already answered this question in the general context of oblong-multilinearization. In our context, we have k=6. Moreover, for each x∈Bℓand, the three bit-arrays
are stored as a[x], b[x] and c[x]. To run the specialization algorithm on a, b and c, the prover just needs to do, for each x∈{0,…,nand−1} (in parallel), three size-64 subset sums of (δD(ri′,i))i∈B6, where the respective bit-coefficients come from a[x], b[x] and c[x].