Gravitational plate of three masses and a slashed discABC0Static engraved plate. Three-dimensional view is unavailable or reduced motion is requested.

← back to fieldarticle

articleAug 5, 2025

Groth16

From arithmetic circuits through R1CS and QAP to Groth16's three-element proof, trusted setup toxic waste, and the single pairing verification equation.

Groth16

1. R1CS and QAP: turning computation into a checkable math problem

1.1. Step 1: Break every computation into adds and multiplies (Arithmetic Circuit)

First convert the program you want to prove into an Arithmetic Circuit: a graph of simple gates. Logic, branches, and loops still bottom out as many additions and multiplications.

Take proving x3+x+5==35x^3 + x + 5 == 35. The prover knows the secret x=3x=3. That computation splits into gates like:

gate1:sym1=xxgate 1: sym1 = x * x gate2:y=sym1xgate 2: y = sym1 * x gate3:sym2=y+xgate 3: sym2 = y + x gate4:out=sym2+5gate 4: out = sym2 + 5 gate5:out==35gate 5: out == 35 (constraint)

That flow of simple ops is the arithmetic circuit. The prover must show each gate computed correctly.

1.2. Step 2: Constraint matrices (A, B, C) and the vector equation (R1CS)

R1CS folds every gate constraint into one vector equation shape: ((as)(bs)(cs)=0)((a · s) * (b · s) - (c · s) = 0). Gates stay separate steps; some multiply, some add.

1. Solution vector (ss)

Pack every variable into one long vector. It is the full computation state, and the prover knows every entry.

s=[1,x,out,sym1,y,sym2]s = [1, x, out, sym1, y, sym2] (the leading 11 is a dummy for constants, xx is the private witness, outout is the public output). With x=3x=3, a correct solution is s=[1,3,35,9,27,30]s = [1, 3, 35, 9, 27, 30].

2. Turn each gate into a vector equation

For each gate, build three vectors aa, bb, cc that pick variables out of ss so the multiply/add relation holds. That produces constraint matrices A, B, C. For gate1:sym1=xxgate 1: sym1 = x * x:

a=[0,1,0,0,0,0]a = [0, 1, 0, 0, 0, 0] (pick xx) b=[0,1,0,0,0,0]b = [0, 1, 0, 0, 0, 0] (pick xx) c=[0,0,0,1,0,0]c = [0, 0, 0, 1, 0, 0] (pick sym1sym1)

Do this for every gate and you get one (ai,bi,ci)(a_i, b_i, c_i) triple per gate. That collection is R1CS.

(as)(bs)=(cs)(a · s) * (b · s) = (c · s) holds ((x)(x)=(sym1)(x) * (x) = (sym1)). Stack those rows into matrices AA, BB, CC. R1CS then asks for an ss such that (As)(Bs)(Cs)=0(A · s) ◦ (B · s) - (C · s) = 0 (element-wise product).

You still have to check one equation per gate, so this form alone is expensive.

1.3. Step 3: Compress many constraints into one polynomial (QAP)

QAP compresses R1CS into a single polynomial-divisibility check.

Idea: if two degree-dd polynomials agree at nn distinct points and n>dn > d, they are the same polynomial.

Process

  1. Assign coordinates: give each R1CS constraint an x-coordinate (gate 1 at x=1x=1, gate 2 at x=2x=2, …).
  2. Matrices to polynomials: Lagrange-interpolate each column of A,B,CA, B, C into a polynomial (column jj of AA becomes Aj(x)A_j(x), with Aj(k)=AkjA_j(k) = A_{kj}).
  3. Define the combined polynomials with solution entries sjs_j as coefficients:

A(X)=ΣsjAj(X)A(X) = Σ s_j·A_j(X) B(X)=ΣsjBj(X)B(X) = Σ s_j·B_j(X) C(X)=ΣsjCj(X)C(X) = Σ s_j·C_j(X)

Evaluating at X=kX=k recovers the k-th R1CS inner products: A(k)=aksA(k) = a_k · s, and likewise for B and C.

  1. Target polynomial T(X)T(X): roots at every constraint coordinate:

T(X)=(X1)(X2)...(Xn)T(X) = (X-1)(X-2)...(X-n)

  1. QAP form: all R1CS constraints hold iff P(X)=A(X)B(X)C(X)P(X) = A(X)·B(X) - C(X) vanishes on {1,,n}\{1,…,n\}, iff T(X)T(X) divides P(X)P(X): A(X)B(X)C(X)=H(X)T(X)A(X)·B(X) - C(X) = H(X) · T(X).

The prover now only needs to show: “I know an ss that builds A,B,CA, B, C such that a quotient H(X)H(X) exists.” Many constraints became one division check.

2. NIZK (Non-Interactive Zero-Knowledge)

You still have to prove the QAP without revealing ss and without chatting with the verifier. NIZK does that with a CRS (Common Reference String) from a Trusted Setup.

After the reduction, the prover must convince a verifier that A(X)B(X)C(X)=H(X)T(X)A(X)·B(X) - C(X) = H(X)·T(X) holds for polynomials they know.

Trusted Setup

CRS generation has to be honest. A malicious setup can break the whole system. That ceremony is the Trusted Setup.

Groth16 uses secret scalars such as:

ττ (tau): secret evaluation point for the polynomials αα (alpha), ββ (beta): consistency / zero-knowledge δδ (delta), γγ (gamma): randomization and finishing the verification equation

They are sampled from a strong RNG.

After key material is derived, those secrets must be destroyed forever — the toxic waste. Leak them and anyone can forge proofs.

Role of the CRS

With a CRS, the prover can send one proof and the verifier decides alone. The CRS holds encrypted evaluations at the secret ττ. The proving key includes values like [τ0]1,[τ1]1,...,[τn]1[τ⁰]₁, [τ¹]₁, ..., [τⁿ]₁ (points in elliptic-curve group G₁).

So the prover never learns ττ, yet can form [P(τ)]1[P(τ)]₁ for any degree-n1≤n-1 polynomial PP by linear combination of those powers. Proving key plus verification key together are the CRS.

The prover holds the proving key; the verifier holds the verification key. The prover must prove the QAP at secret ττ while hiding witness w.

  1. Prover computation

    • Build A,B,C,HA, B, C, H from the private witness ww.
    • Using encrypted powers in pkpk, compute [A(τ)]1[A(τ)]₁, [B(τ)]2[B(τ)]₂, [C(τ)]1[C(τ)]₁, [H(τ)]1[H(τ)]₁.
    • Homomorphism of the curve group lets [P(τ)]1=p0[τ0]1+p1[τ1]1+[P(τ)]₁ = p₀[τ⁰]₁ + p₁[τ¹]₁ + … without knowing ττ.
    • Package those into the final proof ππ.
  2. Verifier

    • Check one pairing equation with ππ and vkvk.
    • That equation tests A(τ)B(τ)C(τ)=H(τ)T(τ)A(τ)·B(τ) - C(τ) = H(τ)·T(τ) in the encrypted domain.

Toxic waste

Once the CRS exists, destroy τ,α,β,δ,γτ, α, β, δ, γ permanently. Anyone who keeps them can forge H(X)H(X) and mint fake proofs.

Production systems use Multi-Party Computation (MPC) — Zcash-style ceremonies. Each participant contributes a secret share, updates the CRS, and deletes their share. If at least one participant is honest and destroys their share, the full secret is unknown to everyone.

3. Groth16 proof shape: three group elements

The goal is to show the QAP holds at secret ττ. Submitting the polynomials in the clear is not an option.

Groth16 compresses that information into three curve points π=([A]1,[C]1,[B]2)π = ([A]₁, [C]₁, [B]₂). They are cryptographic commitments that only become meaningful inside the verification equation.

3.1. [A]₁ and [B]₂

These commit to A(X)A(X) and B(X)B(X), which carry most of the private witness.

[A]₁ (G₁): commitment to A(X)A(X)

Built as a linear combination of proving-key material:

A1=α+A(τ)+rδA₁ = α + A(τ) + r·δ

  • A(τ)A(τ): evaluation of the prover’s A(X)A(X) at ττ — the core claim.
  • αα: blocks knowledge-of-coefficient style forgeries and forces consistency.
  • rδr·δ: fresh prover randomness rr times setup secret δδ, so identical statements produce different [A]1[A]₁ (zero knowledge).

[B]₂ (G₂): commitment to B(X)B(X)

Same structure, but in G₂:

B2=β+B(τ)+sδB₂ = β + B(τ) + s·δ

  • ββ, ss play the roles of αα, rr on G₂.
  • Why two groups? Pairing e(G1,G2)e(G₁, G₂) needs one element from each. Splitting [A]1[A]₁ and [B]2[B]₂ lets verification multiply A(τ)B(τ)A(τ)·B(τ) in the exponent via pairing.

3.2. [C]₁

[C]1[C]₁ ties [A]1[A]₁ and [B]2[B]₂ to an honest QAP. Without it, a prover could pick unrelated AA and BB and still hope to pass.

Its job is to cancel garbage terms in the verification equation and leave the QAP identity.

Conceptually:

C1=sA(τ)+rB(τ)+rsδ+L(x,τ)+H(τ)T(τ)C₁ = s·A(τ) + r·B(τ) + r·s·δ + L(x, τ) + H(τ)·T(τ) (real formulas also scale by setup secrets γγ, δδ).

  • sA(τ)s·A(τ) and rB(τ)r·B(τ) cancel cross terms from e([A]1,[B]2)e([A]₁, [B]₂).
  • rsδr·s·δ cancels the product of the randomization limbs.
  • L(x,τ)L(x, τ) covers the public-input slice of C(X)C(X).
  • H(τ)T(τ)H(τ)·T(τ) is the QAP quotient claim.

In short:

  • [A]₁: encrypted A(τ)A(τ) with ZK randomness
  • [B]₂: encrypted B(τ)B(τ) with ZK randomness, in the other group for pairing
  • [C]₁: auxiliary proof that those commitments are consistent with a real quotient HH

4. Verification: one equation, three pairings

Goal

Check that π=([A]1,[C]1,[B]2)π = ([A]₁, [C]₁, [B]₂) really witnesses A(X)B(X)C(X)=H(X)T(X)A(X)·B(X) - C(X) = H(X)·T(X) at ττ.

4.1. Pairing

e:G1×G2Ge: G₁ × G₂ → Gᴛ

Bilinearity:

e([a]1,[b]2)=e(aG1,bG2)=e(G1,G2)(ab)e([a]₁, [b]₂) = e(a·G₁, b·G₂) = e(G₁, G₂)^{(a·b)} e([a]1+[c]1,[b]2)=e([a]1,[b]2)e([c]1,[b]2)e([a]₁ + [c]₁, [b]₂) = e([a]₁, [b]₂) · e([c]₁, [b]₂)

You never open aa or bb, yet pairing recovers the product in the target-group exponent — enough to check A(τ)B(τ)A(τ)·B(τ).

4.2. Verification equation

e(A,B)=e(α,β)e(L(x),γ)e(C,δ)e(A, B) = e(α, β) · e(L(x), γ) · e(C, δ)

1. LHS: the prover’s claim

With A=α+A(τ)+rδA = α + A(τ) + r·δ and B=β+B(τ)+sδB = β + B(τ) + s·δ, bilinearity expands e(A,B)e(A, B) into many exponent terms, including the desired A(τ)B(τ)A(τ)B(τ) plus auxiliary junk.

2. RHS: rebuild QAP pieces and cancel junk

  • e(α,β)e(α, β) matches the αβαβ term; vkvk ships [α]1[α]₁, [β]2[β]₂.
  • e(L(x),γ)e(L(x), γ) handles public inputs; the verifier builds [L(x,τ)]1[L(x, τ)]₁ from vkvk and xx.
  • e(C,δ)e(C, δ) uses the prover’s CC, which was built to cancel the LHS auxiliaries and supply H(τ)T(τ)H(τ)T(τ).

After cancellation, the surviving relation is equivalent to:

A(τ)B(τ)C(τ)=H(τ)T(τ)A(τ)B(τ) - C(τ) = H(τ)T(τ)

One pairing equation is enough to conclude the prover knows a witness whose derived polynomials satisfy QAP.

4.3. Cost

  • Constant-time verification: three pairings, independent of circuit size nn or mm. That is the “succinct” part.
  • Public inputs (MSM): time grows with public-input length ll when forming L(x,τ)L(x, τ), but Multi-Scalar Multiplication keeps that cheaper than ll naive curve adds.

related

  1. Jul 23, 2025/articleExploring KZG polynomial commitments
  2. Jul 6, 2025/articleExploring PlonK

graphfeed