Properties that any zero knowledge based proving system needs to entertain:

- Completeness: Any honest prover can convince verifier of the statement and witness.
- Soundness: Any malicious prover can never convince a verifier of the statement that it’s trying to prove. In other words, if a prover doesn’t know witness, it can never convince the verifier.

Any proving system defines an n-variate polynomial with an evaluation recipe. Two parties involved in the process are **Prover** and **Verifier**.

SNARKS are succinct argument of knowledge: Mostly used interchangeably but in proofs the soundness holds against a computationally unbounded adversary while in argument of knowledge soundness only holds against polynomially unbounded adversary. Arguments are thus called

computationally sound proofs.

## SNARK

Argument system that generate **succinct** and **fast** proofs for public statement $x$ in $F_{n}$ and secret witness $w$ in $F_{m}$. The statement and witness need to be encoded in an arithmetic circuit $C$.

Arithmetic circuits: $C(x,w)→F$

Requirements:

- Completeness: $∀x,w:C(x,w)=0→Pr[V(S_{v},x,P(S_{p},x,w))]=1$
- Knowledge Sound: P doesn’t know $w→Pr[V(S_{v},x,π)]=$ negligible

why are finite fields important for SNARKs?

Because of hard DLP, group operations, roots of unity.

More formal definition:

### Soundness

For dummies like me: for every polynomial time adversary, there exists an extractor that uses adversary to find out about

`w`

, even though adversary doesn't know about`w`

, because if it would, then adversary can generate arbitrary proofs.

(S,P,V) is **knowledge sound** for a circuit if for every * poly. time adversary A* = (A_0, A_1) such that:

there is an efficient * extractor* $E$, that uses $A_{1}$ s.t.

### Zero Knowledge

For any normal proof, there exists a simulator which can generate proofs without knowledge of

`w`

.

(S,P,V) is zero knowledge for circuit C if there is an efficient **Sim** s.t. $∀x∈F_{n}→∃w:C(x,w)=0$, the distribution:

$(C,S_{p},S_{v},x,π):where(S_{p},S_{v}):S(C),π:P(S_{p},x,w)$

is indistinguishable from the distribution:

$(C,S_{p},S_{v},x,π):where(S_{p},S_{v},π)←Sim(C,x)$

### Proofs

Two ways to prove statement:

- Interactive: prover and verifier goes back and forth to agree on some random values and parameters which verifier can then verify.
- Non-interactive: Pre-processing done to generate a proof $π$ that allows verifier to verify circuit.

Preprocess argument system: prover preprocesses $C$ to generate public parameters $S_{p},S_{v}$.

Consists of $(S,P,V)$:

- $S(C)$: generate $S_{p},S_{v}$
- $P(S_{p},x,w)$: generate proof $π$
- $V(S_{v},x,π)$: verify proof

How does

`S_{p},S_{v}`

gets generated? Is it done for every circuit or some other method? Wouldn't it be very bad UX if we have to run`S`

every time?: Each circuit needs some summary that can be used to verify the proof as no verifier will run the whole computation again, otherwise there's no benefits of these systems.

There has to be some randomisation involved that prover can’t forge by itself to generate these parameters.

- First method is to generate random $r$ for every circuit outside prover.
- Second is to generate a random value once $S_{init}(λ,r)→pp$, create some public parameters based on that, use those parameters to generate $S_{index}(pp,C)→S_{p},S_{v}$
- Totally transparent: no random secrets needed to generate circuit parameters.

Pipeline followed by any ZKP system:

```
flowchart LR
A["computation"]
B["circuit"]
C["prover"]
D["IOP"]
E["verifier"]
A-- arithmetisation --> B
B-->C
C-->D
D-->E
```

Any circuit need to be proven to verifier, so we need to encode and evaluate our polynomial. Thus, most SNARK system consist of two components:

#### PLONK: poly-IOP for General Circuit

Plonk IOP can be used with different PCS to generate different proving systems. For example:

- Aztec’s proving system: KZG+Plonk
- Halo2: Bulletproofs + Plonk, used by zcash
- Plonky2: FRI + Plonk, used by polygon zkevm
- Scroll: (halo2) plonk + kzg

##### Step 1: Compile Circuit for a Computation Trace

Suppose you have a circuit with inputs $I:I_{x},I_{w}$, and gates C where $x$ is the statement inputs and $w$ is the witness input. Our goal is to prove to verifier that $C(w)=0$.

We put inputs $x_{1}=5,x_{2}=6,w_{1}=1$, and compute the computation trace through the circuit. The **computation trace** comes out to be:

inputs: | 5 | 6 | 1 |
---|---|---|---|

Gate 0: | 5 | 6 | 11 |

Gate 1: | 6 | 1 | 7 |

Gate 2: | 11 | 7 | 77 ← Output |

##### Step 2: Encode Trace in Polynomial $P$

- Calculate $d$ of $P$ = $3∣C∣+∣I∣$ where |C|: no. of gates and |I|: no. of inputs
- Aim: encode in a polynomial of form: $F_{p}(X)$
- Encode inputs: $P(w_{−i})=I_{i}∀i∈I$
- Encode gate $l∈C$ wirings:
- $P(w_{3l})=$ left input to gate l
- $P(w_{3l+1})=$ right input to gate l
- $P(w_{3l+2})=$ output of gate l

- Prover has $d$ evaluations of $P$, can use FFT to interpolate coefficients in $O(log_{2}d)$

##### Step 3: Prove Validity of P

What does prover needs to prove to verifier in order to convince it?

- correct output: to prove that output of computation was according to the statements and witness committed.
- correct inputs: proves
- correct intermediate gate evaluations:
- wiring between gates is according to the statement specified by prover

#### Proof Gadgets for IOP

**equality test**→ to test if polynomial $f$ and $g$ are equal and note that verifier only has the commitment, verifier queries the polynomial at point $r$ or opens the commitment and test if values providied by prover are equal. But this generates soundness error.- soundness error → two polynomials in $F_{p}$ can be zero at at most d roots, if $f(r)−g(r)=0=>f−g=0=>f=gv.h.p$
- this assumption has error d/p such that if suppose g is not same as f, then g can have at most d different roots. thus, error → $d/p$
- this is derived from Schwartz-Zippel Lemma

let $\Upomega$ be some subset of $F_{p}$ of size $k$. Let $f∈F_{p}[X]$ be the polynomial that prover wants to prove. Verifier has commitment to this polynomial $Com(f)$.

We can construct efficient poly-IOPs for the following tasks:

- Zero Test: Prove that $f$ is identically zero on $\Upomega$
- Sumcheck: Prove that $∑_{a∈\Upomega}f(a)=0$
- Product check: Prove that $∏_{a∈\Upomega}f(a)=1$
- Permutation check: Prove that $f(a)=g(W(a))$ where $W$ is a permutation polynomial.

Question

- Why do we do these checks only? What is the significance of these checks? What other checks can be done? Can we remove some checks or combine some checks?
- How does the permutation polynomial is calculated?
- Find the reasons behind these checks? Could you have come up with these yourselves?

Vanishing Polynomial of $\Upomega$ is $Z_{\Upomega}(X):=∏_{a∈\Upomega}(X−a)$. $Deg(Z_{\Upomega})=k$ If $\Upomega$ becomes the multiplicative subgroup formed using primitive $k_{th}$ root of unity, then VP becomes $X_{k}−1$. Thus, VP can be calculated in logarithmic time.

##### Zero Check

Let $\Upomega=1,ω,⋯,ω_{k−1}$. Calculate $q(X)=f(X)/X_{k}−1$.

Send $Com_{q}$ to verifier, and verifier opens commitment at point $r$, and check $f(r)=q(r)(r_{k}−1)$. This proves that f(x) is divisible by X^k-1, hence, f has roots in $\Upomega$.

##### Sum Check

Read Sumcheck

##### Product Check on $\Upomega$

We want to prove $∏_{a∈\Upomega}f(a)=1$. Naively, we can send all evaluations of $f$ in $\Upomega$ but that will be quadratic in degree d. Instead, we can create a polynomial $t∈F_{p}(X)$ that evaluates to 1 at $ω_{k}−1$.

Let’s try a toy example in sage taken from here:

So, we can define polynomial $t$ s.t. $t(1)=1,t(ω_{s})=∏_{i=0}f(ω_{i})$ for s=1,…,k-1. Now in order to prove product check, we’ll prove:

- $t(ω_{k−1})=1$
- $t(ω.x)=t(x).f(ω.x)$ for all $x∈\Upomega$. This will be used to a zero test on t(X) so that verifier can get convinced that prover actually computed $t(x)$. This is proven using: $t(ωr)−t(ω)f(ωr)=q(r)(r_{k}−1)$.

The same product check holds for rational function as well, i.e.

`f/g`

. Prove this using:`t(\omega x)g(\omega x)=t(x)f(\omega x)`

##### Permutation Check

It is used to check that two polynomials $f,g$ are permutation of each other. Mainly, prover wants to prove that: $(f(1),f(ω),⋯,f(ω_{k−1}))∈F_{p}$ is a permutation of $(g(1),g(ω),⋯,g(ω_{k−1}))∈F_{p}$.

Can be done by creating two polynomials $F^=∏_{a∈\Upomega}(X−f(a))$ and $G^=∏_{a∈\Upomega}(X−g(a))$ and doing product check on these two polynomials. How will the product check work? It’s simply testing that $g^ (r)f^ (r) =∏_{a∈\Upomega}(r−g(a)r−f(a) )=1$.

Why can't we do zero test to check that these polynomials are equal? ::

##### Prescribed Permutation Check

Instead of just proving the permutation, prover wants to prove that $f(x)=g(σ(x))$, where $σ:\Upomega→\Upomega$ is a permutation if $∀i∈[k]:W(ω_{i})=ω_{j}$ is a bijection.

Why can't you use zero check here to check the two polynomials are equal? :: because g(W(y)) where y in

`\Upomega`

will become O(d^2) in prover time. We don't want quadratic time prover.

Observation: If $(σ(a),f(a))_{a∈\Upomega}$ is a permutation of $(a,g(a))$ then $f(y)=g(σ(y))$. We prove this by defining bivariate polynomial:

$f^ (X,Y)g^ (X,Y) =a∈\Upomega∏ (X−Y.σ(a)−f(a))=a∈\Upomega∏ (X−Y.a−g(a)) $We do product check on these two polynomials such that $∏_{a∈\Upomega}(r−s.a−g(a)r−s.σ(a)−f(a) )=1$, where $r,s$ is the input queried by verifier.

##### Proving Validity of T(x).

T(x) is the polynomial that encodes the computation trace of the circuit.

##### Prove Inputs Were Correct.

Create polynomial v(y) on $\Upomega_{inp}:={ω_{−1},ω_{−2},⋯,ω_{−∣Ix∣}}⊆\Upomega$ and do zero test on:

$T(y)−v(y)=0∀y∈\Upomega_{inp}$##### Prove Gate Evaluations Are Correct

Define a selector polynomial S(X) which is:

Then, you define the polynomial:

$S(y)[T(y)+T(wy)]+(1−S(y))[T(y).T(wy)]=T(w_{2}y)$

then it’s just the zero check.

##### Combining Gate Constraints into One Equation

You can very easily combine gate constraints into one equation:

$Q_{L}(x)a(x)+Q_{R}(x)b(x)+Q_{O}(x)c(x)+Q_{M}(x)(a(x).b(x))+Q_{C}(x)=0\labeleqa (1) $where,

- $Q_{L},Q_{R}$: selector polynomial created for evaluation for left, right of a gate respectively.
- $Q_{O}$: selector polynomial for addition gate.
- $Q_{M}$: selector polynomial for multiplication gate.
- $Q_{C}$: polynomial for constant in a gate, ex: public inputs of the circuit.
- $a(x),b(x),c(x)$: polynomial for left, input and output values of the gates.

We can rewrite $\eqrefeqa$ in terms of linear factors in $ω_{i}$,

$Q_{L}(x)a(x)+Q_{R}(x)b(x)+Q_{O}(x)c(x)+Q_{M}(x)(a(x).b(x))+Q_{C}(x)=(x−ω)…(x−ω_{n})h(X) $Term $(x−ω)…(x−ω_{n})$ is **Vanishing Polynomial:**$H(X)$. Since, $ω$ is a primitive nth root of unity, $ω_{i}$ forms a cyclic group, and $H(X)=X_{n}−1$ . Plonk says that, constraint system is satisfied, when the constraint equation is completely divided by Vanishing polynomial.

##### Prove Gate Wirings Are Correct.

encode the wires as permutation polynomial and prove through permutation check that wiring along the circuit is correct.

$T(y)=T(σ(y))∀y∈\Upomega$

But we have three different n-degree poly, namely $a(X),b(X),c(X)$, thus we join these three polys into one polynomial of degree-3n:

$u=x_{l}∣∣x_{r}∣∣x_{o}=(x_{l},…,x_{l},x_{r},…,x_{r},x_{o},…,x_{o})$and create a permutation $σ∈S_{3n}$ on $u$ which gives $v$. $σ$ is chosen such that subset of array $u$ forms cycles.

### Recap

### Formal Protocol

#### Prover’s Algorithm

##### Round 1:

Compute $a(x),b(x),c(x)$ and send commitments $[a]_{1},[b]_{1},[c]_{1}$ to verifier.

##### Round 2:

- Compute permutation challenge $β,γ$.
- Compute permutation polynomial $z(x)$ and send commitment $[z]_{1}$ to verifier.

##### Round 3:

- Compute quotient polynomial $t(x)$ and send commitment $[t_{low}(x)]_{1},[t_{mid}(x)]_{1},[t_{hi}(x)]_{1}$ to verifier.
- It uses
**quotient challenge**: $α$ to distinguish the three conditions.

It contains all three conditions that is to be proven to the verifier, i.e.

- equality constraint involving $a(x),b(x),c(x)$
- permutation constraint:
- $z(x)f_{′}(x)=g_{′}(x)z(xω)$
- $L_{1}(z(x)−1)=0∀x∈\Upomega$

##### Round 4:

Evaluation of $a,b,c,S_{σ1},S_{σ2},t$ at $z$ and **evaluation challenge**: $z$ at $zω$. Namely, $aˉ,bˉ,cˉ,sˉ_{σ1},sˉ_{σ2},zˉ$.

##### Round 5:

Linearisation polynomial $r(x)$ can be interpreted as $t(x)=t_{low}(X)+X_{n}t_{mid}(X)+X_{2n}t_{hi}(X)=l(X)/Z_{H}(X)$. Thus, prover proves $r(x)=l(X)−Z_{H}(z)(t_{low}(X)+z_{n}t_{mid}(X)+z_{2n}t_{hi}(X))=0$, evaluated at $z$.

Proof polynomial: $W_{z}(x)=X−zM(X) $, and $W_{zω}(x)=X−zωN(X) $. It contains separate terms for each polynomial, separated using **opening challenge**: $v_{i}$. Send $[W_{z}]_{1}$ and $[W_{zω}]_{1}$.

##### Overall Proof:

Proof consists of:

- 9 $G_{1}$ points: $[a]_{1},[b]_{1},[c]_{1},[t_{low}]_{1},[t_{mid}]_{1},[t_{hi}]_{1},[z]_{1},[W_{z}]_{1},[W_{zω}]_{1}$
- 6 $F$ evaluations: $aˉ,bˉ,cˉ,sˉ_{σ1},sˉ_{σ2},zˉ$
- multipoint evaluation challenge: $u$
- $54(n+a)g(n+a)Fmul$ operations

#### Verifier Algorithm

Explained intuition behind the steps really well here. Just reiterating those here:

$W_{z}(X)$ can be written as $M(X)/(X−z)$, and $W_{zω}(x)=N(x)/(X−zω)$. Combining these two identities with multipoint evaluation challenge $u$, we get:

$X(W(X)+uW_{zω}(X))=zW(X)+zωuW_{zω}(X)+M(X)+uN(X)$### Plonk Extensions

- Turboplonk: Custom gates
- Ultraplonk: Turboplonk+ Plookup
- Hyperplonk
- UniPlonk
- Fflonk
- Goblinplonk

### TurboPlonk

Plonk’s arithmetization allows to efficiently add gates other than addition/multiplication. These gates are necessary to reduce constraints in a repetitive computation like hash function computation which involves bitwise arithmetic like XOR.

This article from Kobi explains really well, the design considerations for a custom gate model of MiMc hash.

### Plonkup

Explanation of prover and verifier’s algorithm with reasoning of each step can be found in a beautiful explanation in a blog post by Joshua and by Hector.

### References

- ZK Whiteboard sessions
- Why and How ZK-SNARKS work?
- PLONK whitepaper
- Awesome PLONK
- ZKP MOOC L5
- Vitalik’s Understanding PLONK
- David Wong’s Understand PLONK
- Plonk by hand
- Plonk toy implementation
- ZK Proving systems by Jonathan Wang
- Plonk Arithmetization
- Gnark’s Plonk
- Zac: Adding zk to PLONK
- The Pantheon of Zero Knowledge Proof Development Frameworks
- zkHarness
- zkalc
- Jump: A primer on proof systems