Zinc+ II: Zip+, IPRS Codes, and the Compiled SNARK

May 27, 2026

Where Part 1 left us

Part 1 ended with an API, not a SNARK. The three-step PIOR reduced UCS satisfiability to an Fq~\mathbb F_{\tilde q} equation that a standard sumcheck-shaped PIOP can handle, but the verifier’s hooks into the witness — the projected polynomial oracles [[f~]][[\tilde f]] — were left as a contract:

Given a commitment to a multilinear f~\tilde f with coefficients in Q<d,B[X]\mathbb Q^{<d,B}[X], a verifier-sampled random prime q0q_0, and a random aFq0a \in \mathbb F_{q_0}, the oracle returns ψq0,a(f)~(β)\widetilde{\psi_{q_0, a}(f)}(\beta) for any query point βFq0ν\beta \in \mathbb F_{q_0}^\nu — or \bot when the partial projection isn’t defined.

A commitment scheme has to deliver that interface. And not loosely — the contract has three teeth:

  • Proximity. The committed object has to be (close to) the encoding of an honest witness, in some Brakedown-style sense.
  • Bit-size enforcement. The extracted coefficients must have bit-size poly(B)\text{poly}(B), or Lemma 2.1’s random-prime soundness from Zinc Part 1 doesn’t bite. A generic Q\mathbb Q-PCS gives unbounded extraction; that kills soundness.
  • Well-definedness. The committed witness must have ψq0,a\psi_{q_0, a} defined everywhere — no entry of ff whose denominator is divisible by the sampled q0q_0.

The scheme that delivers all three is Zip+. It’s the successor to Zinc Part 2’s Zip, and the paper highlights exactly three changes:

  1. List-decoding regime via MCA. Zip lived in unique decoding; Zip+ pushes the proximity radius up to the Mutual Correlated Agreement bound. Smaller proofs, lower verifier work.
  2. Merged test and evaluation phases. Zip had two distinct random-linear-combination rounds — one for codeword-proximity, one for the tensor-identity eval. MCA’s structure lets a single combo carry both.
  3. IPRS codes instead of JEA. A new linear code over Q\mathbb Q with MDS-optimal distance, O(nlogn)O(n \log n) FFT-style encoding, and bounded norm growth — three properties JEA could not give simultaneously.

End-to-end, the paper reports proving 7 SHA-256 compressions followed by the multi-scalar-multiplication portion of ECDSA verification in 40.6 ms prover time, 7.0 ms verifier time, 198 KB proof on a MacBook Air M4, at 100 bits of security (same numbers as Part 1 — the headline benchmark for the full stack).

This Part 2 covers Zip+ and IPRS. We restate the contract precisely, walk the three deltas, build IPRS from “lift the FFT not the polynomial,” sketch MCA operationally, layer the Zip+ IOPP construction, and close with the BCS-style compilation that turns the PIOR + PCS stack into a hash-only succinct argument.

Prerequisites. Zinc+ Part 1 — UCS, the three-step PIOR, the projected-oracle interface, Lemma 2.10. Zinc Part 2 — Brakedown skeleton, the tensor identity, commit/test/eval phases over Q\mathbb Q, the IOPP-to-Z\mathbb Z idea, the bit-size lemma chain. Comfort with multilinear extensions, Reed–Solomon codes, the FFT structure of RS encoders, and the localization Z(p)Fp\mathbb Z_{(p)} \to \mathbb F_p.

What we won’t cover. The full round-by-round knowledge soundness reduction (paper §3.2 + Appendix A.2). The general-radix IPRS encoder and full distance proof (§7). All of the batching wrappers around the core Zip+ IOPP (§6). These are load-bearing for the soundness argument but not the conceptual story.

A glossary for the rest of the article

A few symbols recur — worth pinning down up front.

  • CKnC \subseteq K^n — a linear code over a field KK, dimension kk, blocklength nn, relative distance δ\delta.
  • CJC^J — the JJ-wise interleaving of CC. A codeword in CJC^J is a tuple (v1,,vJ)(v_1, \ldots, v_J) of JJ codewords from CC, arranged as rows of a J×nJ \times n matrix.
  • k1,k2k_1, k_2 with k1k2=tk_1 k_2 = t — the matrix dimensions Zip+ uses internally. Witness WW of length tt gets reshaped to k2×k1k_2 \times k_1.
  • VK<d[X]k2×nV \in K^{<d}[X]^{k_2 \times n} — the purported interleaved encoding of WW that the verifier holds an oracle on.
  • u1Kk1,u2Kk2u_1 \in K^{k_1}, u_2 \in K^{k_2} — the equality vectors built from the query point z=(z2,z1)z = (z_2, z_1) for the tensor reformulation of the MLE eval claim.
  • δ\delta, β\beta — relative minimum distance of the code; proximity parameter the IOPP runs at. Zip+ pushes β\beta up to (close to) δ\delta, vs. Zip’s β<δ/2\beta < \delta / 2.
  • MCA — Mutual Correlated Agreement, the property of the code that lets soundness survive past unique decoding.
  • IPRS[Fq,L,k]\text{IPRS}[\mathbb F_q, L, k] — the new code over Q\mathbb Q, parameterized by a base field Fq\mathbb F_q, evaluation domain LFqL \subseteq \mathbb F_q, and dimension kk. Lives in Qn\mathbb Q^n where n=Ln = |L|.
  • ψm,ξ\psi_{m, \xi} — a second-prime projection Z(m)[X]Fm\mathbb Z_{(m)}[X] \to \mathbb F_m, ff(ξ)modmf \mapsto f(\xi) \bmod m, used inside Zip+‘s Layer-3 reduction when the target is a high-extension finite field.
  • B0B_0 vs BB — the completeness-vs-soundness bit-size gap. Honest provers use entries of bit-size B0\leq B_0; soundness only guarantees rejection at bit-size B>B0\geq B > B_0. The slack is fine — the PIOR’s soundness analysis tolerates a poly(B)\text{poly}(B) bound (Remark 2.17 of the paper).

What Zip+ has to deliver

Before construction, the contract. The witness W(K<d[X])tW \in (K^{<d}[X])^t is reshaped as a k2×k1k_2 \times k_1 matrix with entries in K<d[X]K^{<d}[X], where k1k2=tk_1 k_2 = t are both powers of 22. Let MKk1×nM \in K^{k_1 \times n} be a generator matrix for a linear code over KK with relative distance δ\delta. The honest commitment is the interleaved encoding VK<d[X]k2×nV \in K^{<d}[X]^{k_2 \times n} obtained by encoding each row of WW independently under MM.

The verifier holds oracle access to VV. The claim to be checked: ψ(W)~(z)=ζ\widetilde{\psi(W)}(z) = \zeta for some query point z(K)μz \in (K')^\mu, μ=log(k1k2)\mu = \log(k_1 k_2), target ζK\zeta \in K', and finite field KK' obtained from K[X]K[X] via the projection ψ\psi.

Completeness. If VV is the honest interleaved encoding of some WW satisfying ψ(W)~(z)=ζ\widetilde{\psi(W)}(z) = \zeta — and, when K=QK = \mathbb Q, the projection ψ(W)\psi(W) is well-defined — the verifier accepts with probability 11.

Soundness. The verifier rejects with high probability if any of:

  • VV is β\beta-far from every interleaved encoding of a WW with ψ(W)~(z)=ζ\widetilde{\psi(W)}(z) = \zeta, for proximity parameter β\beta up to the MCA bound; or
  • K=QK = \mathbb Q and VV has an entry of bit-size above poly(B)\text{poly}(B); or
  • K=QK = \mathbb Q and VV has an entry whose ψ\psi-projection is not well-defined.

The bit-size gap. Honest provers use witnesses with entries in Q<d,B0[X]\mathbb Q^{<d, B_0}[X]. Soundness only catches cheaters at bit-size B\geq B for some B>B0B > B_0. This gap is real and fine — paper §2.4 footnote 8 makes the call explicitly: “it is enough for our compilation purposes to guarantee bit-size bound below poly(B)\text{poly}(B), not exactly below BB.” The slack gets absorbed by the PIOR’s downstream Lemma-2.1-style counting argument, which already runs on poly(λ)\text{poly}(\lambda)-bit bounds.

That’s the contract Zip+ implements.

Three changes vs. Zip

Zip+ is Zip with three surgical changes. Pin them down before the construction.

Delta 1 — list-decoding regime, MCA-bounded. Zip’s soundness analysis (Zinc Part 2’s §Testing Phase) ran in the unique decoding regime: the proximity parameter β\beta stayed strictly below δ/2\delta / 2, so that ”VV is within distance β\beta of some codeword” identified that codeword uniquely. Zip+ pushes β\beta all the way up to the Mutual Correlated Agreement (MCA) bound of the code — for any linear code over Q\mathbb Q or any finite field, β>(1δ+ε)1/3\beta > (1 - \delta + \varepsilon)^{1/3}, the so-called 1.5 Johnson bound [Zei24, [BCFW25]]. Larger β\beta means fewer column opens needed to hit λ\lambda bits of soundness, which means smaller proofs and faster verification.

The cost is the soundness analysis. Past unique decoding, ”VV is close to a unique codeword” is no longer true — there’s a list of nearby codewords, and the analysis has to argue that none of them is a successful cheat. That’s where round-by-round knowledge soundness from [BCFW25] enters — we’ll come back to it in the BCS section below.

Delta 2 — merged test and evaluation phases. Zip’s IOPP had two distinct phases. The testing phase asked “are these rows really codewords?” via one random linear combination across rows; the evaluation phase asked “and does that combination give the claimed evaluation?” via a second random linear combination. Two rounds, two batches of column opens. Zip+ does it in one: the same random combination used to check codeword proximity also implements the u2Vu_2 \cdot V row-combine that drives the tensor identity. MCA is what makes this safe — the merged combo’s soundness is exactly the MCA condition on the code.

Delta 3 — IPRS instead of JEA. Zip was instantiated with JEA (Juxtaposed Expand-Accumulate) codes — small entries and linear-time encoding, but suboptimal minimum distance, which dominated the proof-size term. IPRS is a new code with MDS-optimal distance (δ=1k/n+1/n\delta = 1 - k/n + 1/n), O(nlogn)O(n \log n) FFT-style encoding, and bounded norm growth (relative norm increase of 40\sim 406060 bits in target configurations, comparable to what 64-bit-field schemes achieve). Three properties simultaneously. JEA could not.

The next three sections take these deltas in order: IPRS first (the new linear-code primitive), then MCA (the soundness primitive that supports Deltas 1 and 2), then the layered IOPP construction.

IPRS: lift the FFT, not the polynomial

Every code-based PCS over Q\mathbb Q runs into a trilemma. The code needs good minimum distance (so the IOPP needs few queries per soundness bit), efficient encoding (so the prover’s commit step doesn’t blow up), and bounded codeword norm growth (so committing rationals doesn’t produce kilobit-per-entry codewords). Naive constructions get two of the three. IPRS gets all three.

Walk through the naive attempts first — they make the trick clear.

Naive attempt 1: RS over Q\mathbb Q. Define the code as evaluations of rational-coefficient polynomials on a fixed integer subset SZS \subseteq \mathbb Z:

RSnaive[S,k]={(f(α))αSfQ<k[Y]}Qn.\text{RS}_{\text{naive}}[S, k] = \{(f(\alpha))_{\alpha \in S} \mid f \in \mathbb Q^{<k}[Y]\} \subseteq \mathbb Q^n.

Minimum distance is fine — it’s the standard RS bound. Encoding is fine — same FFT-shaped algorithm as RS, just executed over Q\mathbb Q instead of Fq\mathbb F_q. Norm is catastrophic. A degree-(k1)(k-1) polynomial evaluated at αS\alpha \in S gives entries of order xSk1\|x\|_\infty \cdot \|S\|_\infty^{k-1}. For practical kk (say 2102^{10}) and any S2\|S\|_\infty \geq 2, codeword entries blow up to hundreds of thousands or millions of bits. The committer has to Merkle-hash all of it. Dead.

Naive attempt 2: lift the Vandermonde matrix. Take a standard RS code RS[Fq,L,k]\text{RS}[\mathbb F_q, L, k] over a small finite field. It has a Vandermonde generator matrix VqV_q with entries in {0,,q1}\{0, \ldots, q-1\}. View VqV_q as an integer matrix, then define the lift:

CQ[V^q]={V^qxxQk}Qn.C_{\mathbb Q}[\hat V_q] = \{\hat V_q \cdot x \mid x \in \mathbb Q^k\} \subseteq \mathbb Q^n.

Norm growth is now fine — entries are bounded by xqk\|x\|_\infty \cdot q \cdot k, so O(logq+logk)O(\log q + \log k) bits per entry. Lemma 2.12 in the paper shows that lifted codes preserve both dimension and minimum distance, so the MDS property of RS survives. But encoding has no FFT structure. The radix-22 butterfly that gives RS its O(nlogn)O(n \log n) encoding relies on the fact that squaring an nn-th root of unity gives an (n/2)(n/2)-th root of unity — an identity that holds in Fq\mathbb F_q but is destroyed when you lift the twiddle factors to Z\mathbb Z and stop reducing modulo qq. Encoding collapses to O(nk)O(nk) naive matrix-vector multiplication. For n=216,k=212n = 2^{16}, k = 2^{12}, that’s 228\sim 2^{28} rational multiplications per commit. Dead.

The IPRS trick: lift the algorithm, not the algebra. Pick an FFT encoder for the finite-field RS code RS[Fq,L,k]\text{RS}[\mathbb F_q, L, k] — fix the radix (say 22), the twiddle factors ωj\omega^j for the chosen primitive nn-th root of unity ωFq\omega \in \mathbb F_q, the recursion depth. Now identify each Fq\mathbb F_q element with its centered integer representative via ι:Fq{(q1)/2,,(q1)/2}Z\iota: \mathbb F_q \to \{-(q-1)/2, \ldots, (q-1)/2\} \subseteq \mathbb Z. Execute the same FFT recursion — same butterfly equation f(ωj)=f0(ω2j)+ωjf1(ω2j)f(\omega^j) = f_0(\omega^{2j}) + \omega^j \cdot f_1(\omega^{2j}) — but with every twiddle factor replaced by ι(ωj)\iota(\omega^j) and every operation performed over Z\mathbb Z (or Q\mathbb Q, for rational messages) with no modular reduction.

Side-by-side comparison of the standard RS-FFT over F_q and the IPRS-FFT lifted to Z. Both share the same butterfly structure, FFT shape, and minimum distance δ = 1 - k/n + 1/n. The lift swaps F_q twiddles ω^j for their centered integer representatives ι(ω^j) and drops modular reduction, which destroys polynomial-evaluation semantics but preserves linearity, dimension, and distance while bounding entries at ‖x‖∞ · (q/2)^(depth+1) · k.

The output is no longer the evaluation vector of any polynomial. Squaring ι(ωj)\iota(\omega^j) over Z\mathbb Z does not give ι(ω2j)\iota(\omega^{2j}). The “evaluations” of the recursive subproblems aren’t really evaluations of anything. And that’s fine. The IOPP doesn’t need the polynomial-evaluation semantics — it needs a linear code with good distance, fast encoding, and bounded entries. The semantics was scaffolding.

Definition (paper Definition 2.13). Given a prime qq, a multiplicative subgroup L=(1,ω,,ωn1)FqL = (1, \omega, \ldots, \omega^{n-1}) \subseteq \mathbb F_q, a dimension k<nk < n, and a fixed FFT algorithm for RS[Fq,L,k]\text{RS}[\mathbb F_q, L, k]:

IPRS[Fq,L,k]:={EncIPRS(x)xQk}Qn.\text{IPRS}[\mathbb F_q, L, k] := \{\text{Enc}_{\text{IPRS}}(x) \mid x \in \mathbb Q^k\} \subseteq \mathbb Q^n.

Properties (paper Theorem 2.14). IPRS[Fq,L,k]\text{IPRS}[\mathbb F_q, L, k] is a linear code over Q\mathbb Q of dimension kk, blocklength nn, and minimum relative distance δ=1k/n+1/n\delta = 1 - k/n + 1/nMDS-optimal, same as RS. The norm bound:

EncIPRS(x)x(q/2)depth+1k.\|\text{Enc}_{\text{IPRS}}(x)\|_\infty \leq \|x\|_\infty \cdot (q/2)^{\text{depth}+1} \cdot k.

In the paper’s target configurations (k29k \approx 2^9 to 2102^{10}, q216q \approx 2^{16}, depth 1122, radix 88), this works out to a relative norm increase of roughly 40–60 bits. Comparable to what field-native schemes achieve over 6464-bit fields when encoding small-norm messages. Far below the thousands of bits naive RS over Q\mathbb Q would produce. The proof (paper §7.2) is a corollary of Lemma 2.12: IPRS is a lift of an RS code under a specific generator matrix (not Vandermonde), so it inherits both dimension and minimum distance.

The trilemma resolved:

ConstructionRelative norm growthFFT structure
Naive RS over Q\mathbb QkSk1\leq k \cdot \|S\|_\infty^{k-1}yes (but moot)
Lifted Vandermonde CQ[V^q]C_\mathbb Q[\hat V_q]kq\leq k qno
IPRS[Fq,L,k][\mathbb F_q, L, k](q/2)depth+1k\leq (q/2)^{\text{depth}+1} \cdot kyes

Concrete encoding cost: encoding a vector of length 2162^{16} with entries in {0,1}<32[X]\{0,1\}^{<32}[X] takes 31.84\sim 31.84 ms multithreaded on M4 with the paper’s radix-88 IPRS implementation (Table 2 of the paper). Vectors of 3232-bit integers at the same length: 2.83\sim 2.83 ms. These are the costs upstream of the IOPP — the per-commit hash work and the per-row Merkle structure run on top.

One open question (paper §2.3.4). Whether IPRS codes have MCA up to the standard Johnson bound (better than the 1.5 Johnson bound that is known to hold for all linear codes), as RS codes do. The paper proves the 1.5 Johnson bound for IPRS via the general result on Q\mathbb Q-codes; the Johnson-bound version would directly tighten Zinc+‘s proof sizes. Open at time of writing.

MCA: living past unique decoding

Brakedown’s classical soundness needed proximity within unique decoding — β<δ/2\beta < \delta / 2 — because the analysis turned on “if VV is β\beta-close to a codeword cc, then cc is unique.” Zip+ pushes proximity up to the 1.5 Johnson bound β>(1δ+ε)1/3\beta > (1 - \delta + \varepsilon)^{1/3}, well past unique decoding. The fix is MCA.

Mutual Correlated Agreement, operationally. For two vectors v1,v2Knv_1, v_2 \in K^n, consider the random linear combination r1v1+r2v2r_1 v_1 + r_2 v_2 for random r1,r2Kr_1, r_2 \in K. Each viv_i has an agreement domain ADCC,β(vi)[n]\text{ADC}_{C, \beta}(v_i) \subseteq [n] — the set of coordinate subsets SS of relative size >1β> 1 - \beta on which viv_i matches some codeword. The MCA property of CC at distance β\beta says: with high probability over (r1,r2)(r_1, r_2), every agreement domain of the combination r1v1+r2v2r_1 v_1 + r_2 v_2 is contained in the intersection of the agreement domains of the individual viv_i‘s. (This is the "J=2J=2" version; the paper states a JJ-fold generalization.)

Operationally: if you take a random linear combination of JJ purported codewords and it lands close to a codeword on some subset SS, then every individual purported codeword had to be close to a codeword on the same subset SS. The combination doesn’t gain agreement that wasn’t already there.

Theorem 3.4 (paper, paraphrased). Any linear code over any field — including Q\mathbb Q — satisfies MCA up to the 1.5 Johnson bound β>(1δ+ε)1/3\beta > (1 - \delta + \varepsilon)^{1/3}, with error n/(εR)n / (\varepsilon |R|) over the choice of random coefficients drawn from a finite subset RKR \subseteq K. The proof for the finite-field case is from [Zei24]; the paper adapts it to linear codes over Q\mathbb Q (Remark 2.16). We won’t reproduce the proof — see Zei24 for the original and paper §3.2 for the Q\mathbb Q adaptation.

Why this matters operationally. In the Brakedown / Zip family, the IOPP’s per-query soundness error scales as βt\beta^t, where tt is the number of columns the verifier opens. To hit λ\lambda bits of soundness, you need tλ/log(1/β)t \approx \lambda / \log(1/\beta) opens. Pushing β\beta from δ/2\delta/2 (unique decoding) up to (1δ)1/3\sim (1-\delta)^{1/3} (1.5 Johnson) directly reduces tt — fewer columns, smaller proofs, less verifier work. This is the “list-decoding regime” win.

The merging of test and evaluation phases is a downstream consequence: MCA’s “agreement doesn’t leak from combinations” property is exactly what lets a single random-combo step do both proximity testing and tensor-identity evaluation safely.

A caveat on what the implementation actually does. The paper is slightly self-contradictory on the benchmark parameters: §2.5 says the Table 4 numbers use rate 1/81/8 at the 1.5 Johnson bound, while Remark 2.16 footnote 9 says “in our experiments we use a rate of 1/41/4 and the Unique Decoding Radius, since in this parameter regime the UDR leads to better performance than the 1.5 Johnson bound.” Take the §2.5 statement as the headline (it’s the paragraph attached to Table 4) and the footnote as evidence that the MCA-bound vs UDR choice is workload-dependent — the implementation picks whichever wins for the configuration in front of it.

The Zip+ IOPP, in three layers

The Zip+ construction is layered: a non-projected scalar core, a polynomial-witness wrapper, and a projected-evaluation outer layer. We follow the paper’s §2.4 layering — it’s also how the implementation is organized.

Three-layer reduction tower of the Zip+ IOPP. Layer 3 starts with the projected constraint ψ̃(W)(z) = ζ over K' and reduces to a non-projected tensor constraint. Layer 2 carries a polynomial witness W̃(z) = a over K[X] with a ∈ K^<d[X] and splits W by X-degree into d parallel scalar IOPPs batched together. Layer 1 carries the scalar witness W̃(z) = ζ over K, dispatched Brakedown-style via a row-combine plus column opens against the underlying linear code (IPRS over Q, or any code over F_q).

Layer 1 — non-projected, scalar witness

Same shape as Zinc Part 2’s eval phase. The witness WKk2×k1W \in K^{k_2 \times k_1}, the interleaved encoding VKk2×nV \in K^{k_2 \times n}, the constraint W~(z)=ζ\widetilde W(z) = \zeta for z=(z2,z1)Klogk2+logk1z = (z_2, z_1) \in K^{\log k_2 + \log k_1} and ζK\zeta \in K. Build the equality vectors

u2=(eq~(z2,b))b{0,1}logk2Kk2,u1=(eq~(z1,b))b{0,1}logk1Kk1.u_2 = (\widetilde{\mathrm{eq}}(z_2, b))_{b \in \{0,1\}^{\log k_2}} \in K^{k_2}, \qquad u_1 = (\widetilde{\mathrm{eq}}(z_1, b))_{b \in \{0,1\}^{\log k_1}} \in K^{k_1}.

The MLE-evaluation constraint rewrites as the tensor constraint

W~(z)=u2TWu1=ζover K.\widetilde W(z) = u_2^T W u_1 = \zeta \quad \text{over } K.

Protocol: the prover sends aKk2a \in K^{k_2} claimed to equal Wu1W u_1. The verifier checks u2Ta=ζu_2^T a = \zeta. If that passes, prover and verifier reduce the remaining claim (”VV is close to an encoding of some WW with Wu1=aW u_1 = a”) to a single proximity claim via the merged random-combo step — the same combination that tests codeword proximity also computes Wu1W u_1.

The K=QK = \mathbb Q adaptations. When K=QK = \mathbb Q, two things change.

(a) Projected check at the scalar level. The constraint form becomes ϕm(W)~(z)=ζ\widetilde{\phi_m(W)}(z) = \zeta in Fm\mathbb F_m for a large random prime mm — exactly the Zinc-Part-1 random-prime trick, here at the inner-IOPP layer. The prover sends aFmk2a \in \mathbb F_m^{k_2}; the check u2Ta=ζu_2^T a = \zeta runs modm\bmod\, m. The final proximity claim is still taken over Q\mathbb Q — the random linear combination is analyzed over Q\mathbb Q, which is what requires the MCA-for-Q\mathbb Q result from Remark 2.16.

(b) Bit-size enforcement. Per Remark 2.17, the final move in any Brakedown-style IOPP over Q\mathbb Q is the prover sending the random linear combination of witness rows, ww^\star. If the honest prover’s witness has bit-size B0\leq B_0, then ww^\star (a combination with λ\lambda-bit random coefficients) has bit-size B0+O(λ+logk2)\leq B_0 + O(\lambda + \log k_2), all polynomial in B0B_0 and λ\lambda. The verifier rejects if ww^\star‘s bit-size exceeds the poly(B)\text{poly}(B) threshold. Soundness against bit-size cheats then reduces to the Zinc-Part-2 lemma chain (Lemmas 2.4, 2.5 of that paper) on random linear combinations of large rationals — random combos of large entries stay large, random combos of fractions rarely collapse to integers.

Layer 2 — non-projected, polynomial witnesses

Now WW and VV have entries in K<d[X]K^{<d}[X], and the target aa also lives there. Split everything by XX-degree:

W=i=0d1XiW(i),V=i=0d1XiV(i),a=i=0d1Xiζ(i).W = \sum_{i=0}^{d-1} X^i \cdot W^{(i)}, \qquad V = \sum_{i=0}^{d-1} X^i \cdot V^{(i)}, \qquad a = \sum_{i=0}^{d-1} X^i \cdot \zeta^{(i)}.

The polynomial constraint W~(z)=a\widetilde W(z) = a decomposes into dd independent scalar constraints W(i)~(z)=ζ(i)\widetilde{W^{(i)}}(z) = \zeta^{(i)} over KK. Each fires a Layer-1 IOPP on (V(i),W(i),ζ(i))(V^{(i)}, W^{(i)}, \zeta^{(i)}). Standard random-linear-combination batching collapses the dd parallel proximity claims into one.

For commits, this is exactly the interleaved commitment from Part 1’s add-on path: a polynomial-witness commit is just dd scalar-witness commits, batched. When K=FqK = \mathbb F_q, this is the entire PCS story — any existing Fq\mathbb F_q multilinear PCS, wrapped with the dd-layer interleaving, handles the Zinc+ add-on regime. No new code, no new lemmas.

Layer 3 — projected constraints

This is where Zip+ does new work. The PIOR delivers a claim of the form ψ(W)~(z)=ζ\widetilde{\psi(W)}(z) = \zeta over a finite field KK', where ψ\psi is one of the projections from Part 1’s §2.2.1 — either ϕq0\phi_{q_0} (when K=QK = \mathbb Q) or ιq~\iota_{\tilde q} \circ eval-at-α\alpha (when K=FqK = \mathbb F_q). Reduce to a Layer-2 non-projected claim.

Easy case: K=FqK = \mathbb F_q, ψ\psi evaluates at αK\alpha \in K. The tensor reformulation lifts straight up: ψ(W)~(z)=u2Tψ(W)u1=ζ\widetilde{\psi(W)}(z) = u_2^T \psi(W) u_1 = \zeta. The prover sends aK<d[X]a \in K^{<d}[X] claimed equal to u2TWu1u_2^T W u_1 over K[X]K[X], the verifier checks ψ(a)=ζ\psi(a) = \zeta, and the remaining proximity-plus-tensor-constraint claim hands off to Layer 2. One non-projected polynomial IOPP, done.

Hard case: K=QK = \mathbb Q, K=FpκK' = \mathbb F_{p^\kappa} with κ\kappa large. This case arises when the inner PIOP runs over a high-extension finite field — e.g., F2128\mathbb F_{2^{128}} for arithmetizations that start over F2[X]\mathbb F_2[X]. The naive lift “evaluate W~\widetilde W at the lifted query point zlift({0,,p1}<κ[X])μz_{\text{lift}} \in (\{0, \ldots, p-1\}^{<\kappa}[X])^\mu” produces a result whose XX-degree is κμ\kappa \mu — prohibitive when κ\kappa is, say, 128128 and μ\mu is 2020.

The fix: lift only the equality vectors u1,u2u_1, u_2, not the witness. Reduce first to the tensor constraint u2Tψ(W)u1=ζu_2^T \psi(W) u_1 = \zeta over Fq\mathbb F_q. Then take a fixed lift of ψ\psi — a section {0,,p1}<κ[X]Fq\{0, \ldots, p-1\}^{<\kappa}[X] \hookleftarrow \mathbb F_q — and apply it coefficient-wise to u1,u2u_1, u_2 to get u1,lift,u2,liftu_{1, \text{lift}}, u_{2, \text{lift}} with polynomial entries of XX-degree <κ< \kappa. The lifted tensor product u2,liftTWu1,liftu_{2, \text{lift}}^T W u_{1, \text{lift}} over Q[X]\mathbb Q[X] now has XX-degree <d+2κ2< d + 2\kappa - 2 — manageable for any reasonable dd and κ\kappa, not blown up by μ\mu.

The prover then sends aQ<d+2κ2[X]a \in \mathbb Q^{<d + 2\kappa - 2}[X] claimed equal to that lifted tensor product. The verifier checks ψ(a)=ζ\psi(a) = \zeta over Fq\mathbb F_q. If that passes, the residual claim is ”VV is close to an encoding of some WW with u2,liftTWu1,lift=au_{2, \text{lift}}^T W u_{1, \text{lift}} = a over Q[X]\mathbb Q[X]” — almost a Layer-2 claim, except the constraint vectors have polynomial entries of degree <κ< \kappa.

The second-prime detour. To avoid running O(κ)O(\kappa) scalar IOPPs to handle the polynomial constraint vectors, Zip+ projects once more. The verifier samples a fresh large random prime mm and a fresh random ξFm\xi \in \mathbb F_m. The map ψm,ξ:Z(m)[X]Fm\psi_{m, \xi}: \mathbb Z_{(m)}[X] \to \mathbb F_m first localizes coefficients to Fm\mathbb F_m, then evaluates at X=ξX = \xi. Replace the strict constraint

u2,liftTWu1,lift=aover Q[X]u_{2, \text{lift}}^T W u_{1, \text{lift}} = a \qquad \text{over } \mathbb Q[X]

with its ψm,ξ\psi_{m, \xi}-image:

ψm,ξ(u2,lift)Tϕm(W)ψm,ξ(u1,lift)=ψm,ξ(a)over Fm.\psi_{m, \xi}(u_{2, \text{lift}})^T \phi_m(W) \psi_{m, \xi}(u_{1, \text{lift}}) = \psi_{m, \xi}(a) \qquad \text{over } \mathbb F_m.

If the original held strictly, the projected version holds too. If the original failed, Schwartz–Zippel-plus-random-prime gives the standard O(d/m)+O(μ/m)O(d / m) + O(\mu / m) soundness bound — negligible for m2λm \approx 2^\lambda. The honest prover’s witness has no entry whose denominator is divisible by mm by the same bit-size counting from Part 1, so well-definedness holds for free.

The residual claim ”VV is close to encoding of some WW with ψm,ξ(u2,lift)Tϕm(W)ψm,ξ(u1,lift)=ψm,ξ(a)\psi_{m, \xi}(u_{2, \text{lift}})^T \phi_m(W) \psi_{m, \xi}(u_{1, \text{lift}}) = \psi_{m, \xi}(a)” is now a Layer-2 polynomial-witness tensor constraint over Fm[X]\mathbb F_m[X] (since ϕm(W)\phi_m(W) still has polynomial entries in XX, of degree <d< d) — handed off to the batched scalar IOPPs of Layer 2.

What the layers buy

The cleanest way to read the layering is degree on the constraint, not on the witness. Layer 1 handles scalar constraints with the merged Brakedown core. Layer 2 lifts to polynomial witnesses by paying a factor dd in scalar IOPPs (batched). Layer 3 absorbs the projection — easy when K=KK' = K, requiring the ψm,ξ\psi_{m, \xi} second-prime trick when KK' is a high-extension of a different characteristic.

The whole thing composes with the IPRS code as the underlying Q\mathbb Q-linear code (or with any Fq\mathbb F_q-linear code in the Fq\mathbb F_q-only regime).

Soft range checks: bit-size at the commitment layer

Part 1’s PIOR assumed bit-size-bounded witnesses. Lemma 2.1’s random-prime soundness analysis required it. The PCS is what makes that assumption a guarantee.

Where the check lives. Per Remark 2.17 of the paper, every Brakedown-style IOPP over Q\mathbb Q ends with the prover sending the random linear combination of witness rows, wQk1w^\star \in \mathbb Q^{k_1}, which the verifier then encodes and checks against the committed VV via column opens. The bit-size check piggy-backs on ww^\star:

  • Honest case. Witness entries have bit-size B0\leq B_0. The combination uses λ\lambda-bit random coefficients across k2k_2 rows. Standard arithmetic: wWk22λ\|w^\star\|_\infty \leq \|W\|_\infty \cdot k_2 \cdot 2^\lambda, so ww^\star‘s entries have bit-size B0+logk2+λ=poly(B0,λ)\leq B_0 + \log k_2 + \lambda = \text{poly}(B_0, \lambda). Verifier checks against this bound.
  • Cheating case. If WW has entries of bit-size B\geq B for some B>B0B > B_0, the Zinc-Part-2 Lemmas 2.4–2.5 chain (random combinations of large rationals stay large with overwhelming probability) forces ww^\star above the threshold too. Verifier rejects.

The completeness-soundness gap. Honest provers are guaranteed B0\leq B_0; soundness only catches at B>B0\geq B > B_0. The slack is real — there’s a band in [B0,B][B_0, B] where the verifier can’t distinguish — but it’s harmless: the PIOR’s Lemma-2.1-style analysis only needed a poly(B)\text{poly}(B) bound, not a tight BB. Paper §2.4 footnote 8 makes this call explicitly: “it is enough for our compilation purposes to guarantee bit-size bound below poly(B)\text{poly}(B), and not exactly below BB.” The constants get absorbed downstream.

Well-definedness. Runs the same way as Zinc Part 2’s bad-denominator branch. Honest prover’s witness has no entry whose denominator is divisible by the random prime q0q_0 — bit-size counting (Lemma 2.1) gives this with overwhelming probability. The oracle returns \bot on ill-defined queries; the verifier rejects on any \bot.

The upshot: the commitment scheme enforces Q<d,poly(B)[X]\mathbb Q^{<d, \text{poly}(B)}[X] typing. The narrower types — Z<d[X]\mathbb Z^{<d}[X], {0,1}<w[X]\{0,1\}^{<w}[X], [0,2w)[0, 2^w) — are enforced by lookup constraints at the PIOP layer, exactly as in Part 1.

From IOPP to hash-only SNARK: BCS compilation

Stack so far: UCS arithmetization → three-step PIOR (Part 1) → Zip+ IOPP with IPRS codes (this article). Final arrow: from the interactive IOP to a hash-only non-interactive succinct argument. That’s done via the standard BCS-style compilation [BCS16] — Merkle-commit each oracle, answer queries via Merkle paths, Fiat–Shamir the verifier randomness from a transcript hash.

Zinc Part 2 stopped one step earlier. Its analog scheme iCOS delivered an interactive succinct argument because Zip’s soundness analysis was not round-by-round — proving the standard “this scheme survives Fiat-Shamir” lemma required a state-restoration soundness argument that the unique-decoding-regime analysis didn’t yield.

Zip+ proves round-by-round knowledge soundness. From paper §1.1: “We prove round-by-round knowledge soundness, allowing for Fiat-Shamir compilation.” The proof uses a recent definition from [BCFW25] that handles soundness in the list-decoding regime — the same regime that gives the smaller proofs. Past unique decoding, the standard knowledge-soundness extractor (find the unique nearby codeword, decode it) doesn’t apply; the BCFW25 framework provides the list-aware extractor.

The result: the Fiat-Shamir transform applies cleanly. The final SNARK is hash-only — no hidden-order groups, no trusted setup, plausibly post-quantum (modulo the standard ROM-vs-QROM caveats for hash-based schemes). Proof size and verifier time match what the IOPP reports, plus Merkle-path overhead.

We won’t reproduce the BCS construction here — see BCS16 for the canonical version, and Zinc Part 2’s §Compilation for the iCOS predecessor and the gap that Zip+‘s RBR-KS analysis closes.

What this buys: the benchmark

End-to-end on MacBook Air M4, 100 bits of security, 7 SHA-256 compressions followed by the multi-scalar-multiplication portion of ECDSA verification:

ComponentProverVerifierProof size
Zip+ IOPP — commit8.4 ms
Zip+ IOPP — open4.7 ms4.2 ms0.06 KB
Zip+ IOPP subtotal13.1 ms4.2 ms162 KB
Zinc+ PIOR (ring proj, ideal batch, eval proj)5.5 ms0.2 ms9 KB
Finite-field PIOP (HyperPlonk-like)21.4 ms2.0 ms27 KB
zstd-3 compression0.6 ms0.6 ms
Total40.6 ms7.0 ms198 KB

A few things worth pulling out:

  • The PIOR is cheap. Steps 1–3 from Part 1 take 5.55.5 ms — about 14%14\% of prover time. Most of the work is the inner finite-field PIOP (21.421.4 ms) and the Zip+ commit/open (13.113.1 ms).
  • Proof size is dominated by Zip+ (162162 KB out of 198198 KB total). The paper notes this is inherent to Brakedown/Ligero-style PCSs; ongoing work on a WHIR-based [ACFY25b] replacement is expected to compress this substantially.
  • The implementation is suboptimal on purpose. Paper line 1766: it arithmetizes entirely over Z[X]\mathbb Z[X], not the optimal Z[X]/F2[X]/Fq\mathbb Z[X] / \mathbb F_2[X] / \mathbb F_q mix from §8. So these numbers are pessimistic — multi-domain support is on the roadmap.
  • Parameters. IPRS code with rate 1/81/8, radix 88, base field of size 216+12^{16} + 1. Random prime q0q_0 is 192\sim 192 bits. Proximity parameter set to the 1.5 Johnson bound. (Paper Remark 2.16 footnote 9 notes that at the alternative rate 1/41/4, the UDR empirically outperforms the 1.5 Johnson bound — workload-dependent.)

What we didn’t cover

A few load-bearing pieces deferred for length:

  • Full MCA-to-RBR-KS reduction (paper §3.2 + Appendix A.2). The list-aware knowledge extractor that BCFW25 provides, and its instantiation for the Zip+ IOPP.
  • General-radix IPRS encoder and full distance proof (paper §7). Above we fixed radix-22 for the explanation; the implementation uses radix-88 for performance.
  • Full Zip+ IOPP construction with all batching wrappers (paper §6). The §2.4 sketch we followed gives the conceptual structure; the implementation layers in column batching, query batching, and merged Merkle-path verification.
  • Qāren [SSPP26]. Concurrent work compiling any Fp\mathbb F_p multilinear PCS to a relaxed mod-PCS over Q\mathbb Q. The paper flags it as a possibly-better fit for committing {0,1}<32[X]\{0,1\}^{<32}[X] vectors (the SHA-256 use case), but defers the integration.
  • The Fq\mathbb F_q-only “Zinc+ add-on” PCS path. Covered in Part 1 — any existing Fq\mathbb F_q multilinear PCS wrapped with interleaved commits handles it. No new PCS needed.

Conclusion

The core ideas, in order:

  1. Zip+ implements the projected-oracle interface that Part 1’s PIOR left as a contract — proximity, bit-size enforcement, and well-definedness under ψ\psi, all at the commitment layer.
  2. Three deltas vs. Zip: list-decoding regime via MCA (smaller proofs), merged test + evaluation phase (one round less), IPRS codes instead of JEA (MDS distance + FFT encoding + bounded norms simultaneously).
  3. IPRS — lift the FFT, not the polynomial. Throwing away the polynomial-evaluation semantics of RS while keeping the FFT algorithmic structure resolves the distance/encoding/norm trilemma that has blocked code-based PCSs over Q\mathbb Q.
  4. MCA + round-by-round knowledge soundness unblocks Fiat-Shamir. Zinc Part 2’s iCOS stopped at interactive succinctness because the unique-decoding analysis didn’t survive state-restoration; Zip+‘s RBR-KS proof in the list-decoding regime is what makes BCS compilation kosher.
  5. Soft range checks fold into the existing random-linear-combo step. Bit-size enforcement piggy-backs on the prover’s final ww^\star message; the B0B_0-vs-BB completeness-soundness gap is real but absorbed downstream.

The result is the first hash-only SNARK with native integer + bitwise arithmetization, no hidden-order groups, plausibly post-quantum, delivering 7 SHA-256 compressions + ECDSA MSM at 40\sim 40 ms prover / 77 ms verifier / 198198 KB proof on a laptop. End-to-end, with measured benchmarks.

What’s next: IPRS-MCA at the standard Johnson bound (open in the paper, would directly tighten proofs); a WHIR-based replacement for the Brakedown-flavored proof-size term; integration with Qāren for {0,1}<32[X]\{0,1\}^{<32}[X] commits.

References

  • Zinc+: SNARKs for Polynomial Rings. Alexander Abdugafarov, Albert Garreta, Amit Kumar, Michał Osadnik, Psi Vesely, Ilia Vlasov, Kai Zhe Zheng. Nethermind Research et al., May 2026. PDF
  • Zinc+ Part 1. Walkthrough on this blog.
  • Zinc Part 1, Part 2. Walkthroughs on this blog.
  • Brakedown. Golovnev, Lee, Setty, Thaler, Wahby. CRYPTO 2023.
  • Field-Agnostic SNARKs from Expand-Accumulate Codes ([BFKTWZ24], the source of JEA-style constructions). Block, Fang, Katz, Thaler, Waldner, Zhang. CRYPTO 2024.
  • Khatam: Reducing the Communication Complexity of Code-Based SNARKs ([Zei24]). Zeilberger 2024 — MCA / 1.5 Johnson bound for linear codes; generalized to Q\mathbb Q-codes in this paper’s §3.2. ePrint 2024/1843
  • Linear-Time Accumulation Schemes ([BCFW25]). Bünz, Chiesa, Fenzi, Wang. TCC 2025 — provides the round-by-round knowledge soundness framework Zip+ uses in the list-decoding regime.
  • Interactive Oracle Proofs ([BCS16]). Ben-Sasson, Chiesa, Spooner. TCC 2016-B — the BCS-style compilation from IOPs to hash-only succinct arguments.
  • WHIR ([ACFY25b]). Arnon, Chiesa, Fenzi, Yogev 2025 — the proof-size successor that ongoing Zinc+ work is targeting.
  • Relaxed Modular PCS ([SSPP26]). Shirzad, Sridhar, Papadopoulos, Papamanthou 2026 — concurrent work compiling any Fp\mathbb F_p multilinear PCS to a relaxed mod-PCS over Q\mathbb Q. ePrint 2026/347
  • Binius. Diamond, Posen. 2024–2025 — binary-field SNARKs, the comparison point for bitwise arithmetization.