Notes on STIR-style proximity testing, where each round cuts the degree by k but only halves the domain: the construction, how to handle repeated queries, and round-by-round soundness.
· 9 min read · Proximity Testing, Reed–Solomon
Symbol
Meaning
RS[F,L,d]
{f:L→F∣∃f^∈F<d[X],f=f^∣L}
ρ
rate of the code, ρ:=d/∣L∣
f^
hat = polynomial object (as opposed to the function f)
Lk
{xk:x∈L}
smooth
L is a multiplicative coset of F∗ whose order is a power of 2
List(f,d,δ)
codewords of RS[F,L,d] within distance δ of f
(δ,ℓ)-list decodable
∣List(f,d,δ)∣≤ℓ for every f
V^S
vanishing polynomial of S, ∏a∈S(X−a)
Fact — The Johnson Bound: The code RS[F,L,d] is (1−ρ−η,2ηρ1)-list decodable for every η∈(0,1−ρ).
1. The Idea
One STIR iteration reduces proximity testing of C=RS[F,L,d] to proximity testing to C′=RS[F,L′,d/k], where the degree drops by a factor k but the domain only drops by a factor 2:
ρ′=∣L∣/2d/k=k2⋅ρ.
Testing proximity to C′ is easier than testing proximity to C for two reasons:
C′ is “smaller” than C in the sense that the degree is reduced from d to d/k and the evaluation domain size is reduced from n to n/2.
The rate of the code is reduced by a factor of 2/k.
Intuitively, testing proximity to a code with a smaller rate is easier because the code has more “redundancy”. Indeed, rate reduction in STIR is the key feature that facilitates smaller query complexity: the smaller the rate, the fewer queries are needed to achieve a target soundness error.
2. Tools
STIR rests on the following tools.
2.1 Out-of-Domain Sampling
Lemma 4.5 shows that the probability that there exist two distinct codewords in the list-decoding set of a function that both agree on a random point is small.
Lemma 4.5
If RS[F,L,d] is (δ,ℓ)-list decodable, then
STIR relies on k-wise folding of functions and polynomials. Lemma 4.9 shows that folding a function preserves its proximity from the Reed–Solomon code with high probability
Folding Polynomials: Given a polynomial f^∈F<d[X], a folding parameter k∈N and r∈F, we define a polynomial PolyFold(f^,k,r)∈F<d/k[X] as follows. Let Q^∈F[X,Y] be the bivariate polynomial derived from f^ with degX(Q^)<d/k and degY(Q^)<k such that f^(Z)=Q^(Zk,Z). Then PolyFold(f^,k,r)(X):=Q^(X,r).
Folding Functions: Let f:L→F be a function, k∈N a folding parameter and α∈F. For every x∈Lk let p^x∈F<k[X] be the polynomial interpolating {f(y):y∈L,yk=x}. We define Fold(f,k,α):Lk→F by Fold(f,k,α)(x):=p^x(α).
2.3 Quotienting
STIR also needs the quotient of functions and polynomials.
Quotienting Functions: Let f:L→F be a function, S⊆F a set disjoint with L, and Ans:S→F be a function. Let Ans∈F<∣S∣[X] be the polynomial interpolating {Ans(x):x∈S}. The quotient functionQuotient(f,S,Ans):L→F is defined by:
Quotient(f,S,Ans)(x):=V^S(x)f(x)−Ans(x)
Quotienting Polynomials: Let f^∈F<d[X] be a polynomial and S⊆F. The polynomial quotientPolyQuotient(f^,S)∈F<d−∣S∣[X] is defined by:
PolyQuotient(f^,S)(X):=V^S(X)f^(X)−Ans(X),
where Ans∈F<∣S∣[X] is the polynomial interpolating {f^(x):x∈S}.
Lemma 4.4 shows that if a function is “quotiented by the wrong value”, then its quotient is far from low-degree.
Note that S must be a set: if a point appeared twice, V^S would have a double root there while f^−Ans only vanishes to first order, and the honest quotient would not be a polynomial. Section 4 discusses what this means once the points of S are sampled at random.
2.4 Degree Correction
Finally, STIR also shows how to properly perform a degree correction.
Given target degree d∈N, shifting parameter r, function f:L→F, and degree 0≤d≤d∗, we define DegCor(d∗,r,f,d):L→F by:
The closed form of the geometric sum is the efficiency contribution: O(log(d∗−d)) operations and a single query to f, instead of O(d∗−d).
2.5 Checking the Interpolant: the Shake Polynomial
Quotienting makes the verifier evaluate Ans, the interpolant of ∣S∣ points. Interpolating costs O(∣S∣2) field operations, and so does the obvious alternative: let the prover send Ans and check it at every point of S, ∣S∣ evaluations of a degree-∣S∣ polynomial. Both are the dominant verifier cost of an iteration when ∣S∣ is in the hundreds.
The fix is to let the prover send Ans together with a witness that it interpolates, and check the witness at one random point. Define the shake polynomial
Sh(X):=a∈S∑X−aAns(X)−Ans(a).
The check. V samples ρ←F∖Safter receiving Ans and Sh, and accepts iff
Sh(ρ)=a∈S∑ρ−aAns(ρ)−Ans(a).
Cost: two polynomial evaluations and one batched inversion: O(∣S∣).
Two degree bounds must be enforced for this argument: deg(Ans)<∣S∣ (a longer polynomial through the same points is not the interpolant) and deg(Sh)<∣S∣−1.
3. Construction
3.1 Ingredients
A field F.
An iteration count M∈N.
An initial degree d∈N that is a power of 2.
Folding parameters k0,…,kM−1∈N, powers of two, with d≥∏iki.
Evaluation domains L0,…,LM−1⊆F, each Li a smooth coset of F∗ with ∣Li∣>d/∏j<ikj (i.e. ρi<1), and Li−1ki−1∩Li=∅ for every i∈[M−1].
Repetition parameters t0,…,tM−1∈N with ti+1<d/∏j≤ikj for i<M−1.
Per-round degrees, for i=0,…,M: di:=∏j<ikjd (so d0=d), and ρi:=di/∣Li∣.
3.2 Interaction phase
Initial function: f0:L0→F, an oracle. Honest case: f0∈RS[F,L0,d0] and the prover holds f^0∈F<d0[X].
Initial folding: V sends r0fold←F.
Loop, for i=1,…,M−1:
Send folded function. P sends gi:Li→F. Honest: gi is the evaluation over Li of
g^i:=PolyFold(f^i−1,ki−1,ri−1fold)∈F<di[X].(Note the domain jump: the fold naturally lives on Li−1ki−1, of size ∣Li−1∣/ki−1, but the prover re-evaluates it over Li, of size ∣Li−1∣/2. That is the “shift to improve rate”.)
Out-of-domain sample. V sends riout←F∖Li.
Out-of-domain reply. P sends βi∈F. Honest: βi:=g^i(riout).
STIR message. V sends rifold,ricomb←F and ri,1shift,…,ri,ti−1shift←Li−1ki−1.
Quotient set and answers (both parties, no message). View Gi:={riout}∪{ri,1shift,…,ri,ti−1shift} as a set (repeated shift points counted once, see Section 4), and Ansi:Gi→F,
Ansi(riout)=βi,Ansi(ri,jshift)=Fold(fi−1,ki−1,ri−1fold)(ri,jshift).
Interpolant and shake polynomial. P sends Ansi∈F<∣Gi∣[X] and Shi∈F<∣Gi∣−1[X] as coefficients. Honest: Ansi interpolates Ansi on Gi and
Shi(X):=a∈Gi∑X−aAnsi(X)−Ansi(a).
Shake challenge. V sends ρi←F.
Define next polynomial (prover-local, no message). With g^i′:=PolyQuotient(g^i,Gi), the prover defines the degree-corrected polynomial
f^i:=DegCor(di,ricomb,g^i′,di−∣Gi∣)∈F<di[X],
and the protocol proceeds to the next iteration with f^i.
Final round: P sends dM coefficients of a polynomial p^∈F<dM[X]; honest p^:=PolyFold(f^M−1,kM−1,rM−1fold).
The disjointness Li−1ki−1∩Li=∅ is what makes Gi∩Li=∅ automatic (the out-of-domain sample is drawn outside Li, the shift points live in Li−1ki−1), so the quotient’s denominator never vanishes on Li and the paper’s Fill polynomial is never needed.
3.3 Verifier decision phase
1. Main loop, for i=1,…,M−1:
(a) For every j∈[ti−1], query Fold(fi−1,ki−1,ri−1fold) at ri,jshift. This involves querying fi−1 at all ki−1 points x∈Li−1 with xki−1=ri,jshift. (For i≥2, fi−1 is the virtual oracle of (c) below, so each of those is one query to gi−1 plus the quotient/degree-correction arithmetic.)
(b) Build Gi and Ansi as in step 5 of the interaction, and check the shake identity
Shi(ρi)=a∈Gi∑ρi−aAnsi(ρi)−Ansi(a),
rejecting if ρi∈Gi.Then, (virtually) set, for every x∈Li,
gi′(x):=V^Gi(x)gi(x)−Ansi(x)
(c) Define the virtual oracle fi:Li→F as follows:fi:=DegCor(di,ricomb,gi′,di−∣Gi∣) Notice that every query x to fi translates into a single query to gi.
2. Consistency with the final polynomial: sample r1fin,…,rtM−1fin←LM−1kM−1 and check
p^(rjfin)=Fold(fM−1,kM−1,rM−1fold)(rjfin)∀j∈[tM−1].
This is the only explicit equality check of the protocol. Everything before it binds the prover through quotients: a gi that disagrees with Ansi on Gi makes fi far from low degree (Lemma 4.4), and that is what the next iteration’s queries detect.
4. Repeated Queries
The ti−1 shift points are sampled i.i.d. from Li−1ki−1 so they are sampled with replacement. Two of them coincide with probability about (2ti−1)/∣Li−1ki−1∣. For concreteness, a schedule with t0=200 queries into a folded domain of 220 points collides in around 2.5% of executions, and summing over the quotient rounds of a realistic schedule gives a few percent per proof. This is not a negligible event.
4.1 Why it Matters
Gi enters the protocol as a set: in V^Gi, in the interpolant Ansi and in the degree correction through ∣Gi∣. If a repeated point were kept as a multiset, V^ would acquire a double root at it while g^i−Ansi only vanishes there to first order, so the honestf^i would not be a polynomial and the honest prover would fail. If, instead, one party deduplicates and the other does not, they disagree on ∣Gi∣, on Ansi and on V^Gi, and every honest proof fails. So both parties must apply the same rule, and the rule must produce a set.
4.2 Solution A: Deduplicate
Drop every shift point that already occurred. Natively this is a sorted set and costs nothing. Its consequence is that ∣Gi∣ is data-dependent: it is only known once the queries are, which is harmless natively but shapes a circuit verifier substantially:
∣Gi∣ becomes only known at proving time, so the exponent of the degree correction ∑ℓ≤∣Gi∣(rcombx)ℓ is data-dependent.
Ansi and Shi are sent zero-padded to ti−1+1 coefficients and the tail beyond ∣Gi∣ must be pinned to zero, to keep the degree bounds of Section 2.5.
The freshness flags themselves cost O(ti−12) comparisons: all quereies are diferent iff ∏i=j(rishift−rjshift)=0.
V^Gi cannot be built as a product over a set of unknown size. One builds instead U(X):=∏q(X−freshq⋅rqshift)=V^fresh(X)⋅Xδ, where a dropped repeat contributes the factor X and δ is the number of drops; U is monic of degree exactly ti−1, and the spurious xδ is divided out at evaluation time.
Deduplication is therefore correct and simple, but it is where most of the STIR-specific circuit cost lives.
4.4 Solution B: Hinted Freshness
Keep i.i.d. sampling, but let the prover supply the freshness flags and have the verifier check them in O(tlogt) through a sorted permutation argument instead of recomputing them in O(t2). This keeps everything in Section 4.2 except the quadratic term, and is only worth it if the sampling cannot be changed.
5. Round-by-Round Soundness
Under the hypotheses: f∈/RS[F,L0,d0],
δ0∈(0,Δ(f,RS[F,L0,d0])]∩(0,1−B⋆(ρ0)),
δi∈(0,min{1−ρi−1/∣Li∣,1−B⋆(ρi)}) for 0<i<M−1,
RS[F,Li,di] is (δi,ℓi)-list decodable,
STIR has rbr soundness error (εfold,ε1out,ε1shift,…,εM−1out,εM−1shift,εfin) with
The state function is essentially “the current fold is within δi of the code”∧“every consistency-with-Ans check so far holds”. The four errors correspond to the four ways the state can flip from 0 to 1:
εfold. The initial folding brings f close to the code by chance.
εiout. Two distinct codewords of List(gi,di,δi) agree on the out-of-domain point. If this does not happen, there is at most oneu with u^(riout)=βi.
εishift. Three summands, one per tool:
(1−δi−1)ti−1: if that unique u exists, u^ disagrees with the fold of fi−1 on ≥δi−1 of the domain, so the ti−1 shift queries catch it except with that probability.
err⋆(di,ρi,δi,ti−1+s): DegCor with ricomb failing to preserve distance.
err⋆(di/ki,ρi,δi,ki): the next fold with rifold failing to preserve distance.
εfin. The final fold agrees with p^ on all tM−1 points despite being δM−1-far.
References
STIR: Reed–Solomon Proximity Testing with Fewer Queries - Arnon, Chiesa, Fenzi and Yogev [2024/390].