Similarities: proofs systems, use polynomial commitment schemes, same constraint system (constraint polynomial, BG12 permutations, lookup tables, custom gates)
Differences: PLONK requires a trusted-setup, PLONK uses pairings, Halo has proof recursion (2-cycle of elliptic curve groups), PLONK uses a Kate-like PCS, Halo uses a Hyrax-like PCS
Timeline:
[Standard] PLONK (Aug-2019) - proof system via polynomial commitments using a single updateable trusted-setup. Uses pairings, a non-R1CS constraint-system, BG12 permutation proofs, and Kate-like polynomial commitments.
Halo (Sep-2019) - proof recursion via elliptic curve cycles, no pairings, no trusted setup, Hyrax-like PCS.
TurboPLONK (late-2019/early-2020) - PLONK with custom gates/constraints.
plookup (Nov-2020) - extends PLONK with lookup tables (replace expensive computations with key-value maps to lookup a computation's output on an input, currently lookup tables focus on replacing bitwise operations such as bitwise AND and XOR).
UltraPLONK (late-2020) - PLONK with custom gates and lookup tables, i.e. combines TurboPLONK and plookup (makes many algorithms that are SNARK unfriendly, more friendly). Side note: using lookup tables and custom gates allows for efficient modular arithmetic in a field smaller than the PLONK field, which could allow for recursive proofs without cycles of elliptic curves (i.e. multiple base and scalar fields). Side note #2: Pedersen hashing within UltraPLONK is roughly as efficient as Poseidon.
Halo2 (late-2020) - combines UltraPLONK, a PCS that does not require a trusted-setup, and cycles of elliptic curves for recursion.
Question: Verification time is constant in PLONK, but is not in Halo/Halo2 because Halo's proof size varies with computation size? Zcash will rely on batch transaction verification to achieve something close to succinctness.
Arithmetization - breaks a general computation into a sequence of steps.
Example: :
Arithmetization converts a general computation into a system of polynomials (a set of interdependent polynomials) where each is constrained to a value. A general computation's set of polynomials is its constraint system. Every polynomial is of the same form.
Standard PLONK uses the constraint polynomial:
which can encode addition, multiplication, and constant assignment.
Constraint | ||
---|---|---|
Addition | ||
Multiplication | ||
Assign Constant (Public Input) |
|
|
Exponentiation |
Note: a constraint may reference a value from another constraint, e.g. exponentiation. This is enforced via a permutation argument, not using constraint.
TODO: The values define a computation. The values are filled in by someone who knows how the computation proceeds (the inputs and outputs at each gate).
We can think of a computation's constraint system as a matrix:
where the prover fills in the columns , , and with values (the witnesses) such that every constraint is satisfied.
Example: (cont.)
The 's and equality constraints define a computation, the 's give an instance of the computation; the prover fills in values to show that they know how a computation proceeds.
We would like to replace constraint checks (i.e. is the constraint satisfied?) with a single check of some form. We do this by transforming the constraint system into a polynomial expression that is true if and only if the constraint system is satisfied.
Lagrange interpolation converts a function's evaluation form into a passing through each point.
Lagrange interpolation is used to represent each column as a polynomial: , where each column's polynomial on the input outputs the column's value in row .
We associate each matrix row with a unique value where the set of values associated with all rows is . Zipping this set of inputs with a column gives the evaluation form for a polynomial that outputs the column value on row 's input . Performing Lagrange interpolation on each column's evaluation form produces the polynomial that maps each row's input to the value in the column at that row . For example, to interpolate column as we use the evaluation form .
Given the set of interpolating polynomials, we use the constraint equation to write an expression that holds for every input :
moving the right hand side to the left, we rewrite the above as:
We can write the left hand side of the above equation as a polynomial:
which that outputs on every input , i.e. has roots . We know some of the polynomial's roots, therefore we know part of its linear factorization contains the degree-1 terms :
We call the vanishing polynomial which outputs on every input :
which in a cyclic multiplicative group of order simplifies to:
and its cofactor polynomial. Thus, we can write the constraint system polynomial as as equality:
The constraint system is satisfied if its polynomial representation is divisible by without remainder.
Thus we can perform constraint checks using a single polynomial division check.
A permutation that shuffles an array of elements can be written:
where means that .
The polynomial division check ensures that the prover knows satisfying inputs and outputs for each gate, but does not ensure a correct wiring, e.g. the output of one gate is the input to another.
Example: I know such that .
Applying the division check on the two gates proves that I know satisfying inputs and outputs for each gate in isolation, i.e. I know such that and :
adding copy constraints proves that the left inputs are equal, the right inputs are equal and the outputs are equal, i.e. I know such that :
To prove equality of wires we apply a permutation check across the constraint system values . We join each of the three columns into a single array of length :
and create a permutation that acts on to produce an array . We choose such that each subset of copied values forms a cycle, i.e. copied values are permuted with only their copies.
Given a permutation where:
we can write in cycle notation: or simply . An -cycle is a subset of elements that repeat after applications of , e.g. the -cycle maps then .
Given a constraint system of constraints:
and wiring:
we create a permutation , which operates on a set containing elements, such that each set of copied constraint system values forms a cycle:
written in a less cumbersome way using indices in as:
The permuted vector is:
The unpermuted array is encoded into the polynomial:
and the permuted array is encoded into the polynomial:
where is the index in that permutes into , i.e. and . Also let and denote the terms of and respectively:
Notice that for each term in there is an identical term in , thus the polynomials and are the same, despite their terms possibly being different:
thus the following relation holds:
This relation between a polynomial representing an array and a polynomial representing a permutation of the array can be tested using Schwartz-Zippel: given a random input the probability the , or , is negligible.
PLONK actually defines and where the verifier chooses a random and sends it to the prover (which are equivalent via the right-shift Schwartz-Zippel lemma), thus in reality the above expression is:
The trace of a running product is an array whose first element is an contains the value of the product after each multiplicand, e.g.
The verifier chooses a random for the prover to evaluate and the prover constructs a grand product array that represents , i.e. is the trace of the product :
is recursive in that its element is equal to the previous element times :
Notice that the can be computed from by multiplying its last element by the last product term in :
The prover creates a polynomial using Lagrange interpolation on a publicly known set of inputs and image such that:
Notice that the following relation holds for a pair of neighboring inputs and :
Given , the verifier wants to check that is a permutation of according to . The verifier checks that the permutation identity holds at the last element in :
and that is a correctly constructed running product :
If at the random challenge then , which implies .
Note: "ordered multiset" == "array"
Note: "subarray" == "order preserving subset of an array"
PLONK defines an ordered multiset's set difference as the difference between adjacent elements of :
Given arrays and , if is a subarray of , then the set difference of contains number of zeros because each is inserted next to an having the same value:
However, this alone does not prove that an array is a subarray of because we can find an array where the set difference of contains number of zeros:
However, given a random value , we can test (w.h.p.) that an array is subarray of an array by shifting all elements by :
Given two arrays and of equal length , if both and contain the same elements, regardless of their ordering, then the products of the arrays' elements will be equal:
However, the products of two [equally lengthed] arrays' elements being equal does not guarantee that and contain the same elements, e.g.
We can use a product equality check on the elements of two arrays to guarantee that the arrays contain the same elements by right-shifting every element of each array by a random value :
A univariate polynomial having roots can be written uniquely as degree- polynomials:
where is a constant. If we don't care about the sign of the roots we can write:
A polynomial that has a linear factor has a root at :
We can encode a set of values into a unique polynomial:
We can encode an array into a unique polynomial where each root encodes an array element and its position:
Side Note: if an array is a permutation of another, e.g. and where is a permutation, then the following equality holds:
e.g. and :
Given two univariate polynomials:
Schwartz-Zippel says that for a random input the probability that different polynomials evaluate to the same value is very low.
This allows us to test polynomial equivalency, i.e. is the same polynomial as .
Schwartz-Zippel holds if every root of and is shifted by the a randomly chosen constant :
because shifting two polynomials by the same value along the x-axis does not affect their equality.
We can encode the elements of a set into a polynomial and the set into a polynomial and use Schwartz-Zippel to test set equality (i.e. do sets and contain the same elements).
We can encode an array as a polynomial whose roots contains the array elements and their positions:
thus, we can use Schwartz-Zippel to test array equality (i.e. ).
PLONK uses Schwartz-Zippel (on random input ) with a random right-shift to check array equality:
The Schwartz-Zippel probability is the same for an -variate polynomial and a randomly selected evaluation point
Given a random evaluation point such that , the probability that is the zero-polynomial (always a zero-function) is the converse of the Schwartz-Zippel probability
Given an array and a subset , then the low-degree extension of is the interpolation polynomial of degree that passes through the points :
We associate each value in the constraint system with a unique value in :
where are disjoint subgroups and , . We then join the labels into an array of length :