This is implemented with reference to the lambdawokrs project.Just for learning.
An implementation of Baby SNARK protocol
BabySNARK is based on this NIZK proposed in 2014. It works with square span programs, which are similar to, yet simpler than, quadratic arithmetic programs (used in Pinocchio). The representation of the circuit is done with a matrix
We can express any boolean circuit using these types of constraints. Let us rewrite the equations in a different form that will be convenient for later purposes:
If the polynomial has multiple zeros, then it must be divisible by each
One way to show that the computation described by the system of equations is valid is by providing
A polynomial commitment scheme is given by four algorithms: setup
, commit
, open
, and evaluate
. The commitment allows us to bind ourselves to a given polynomial using short data and later be able to prove things about that polynomial. The commitment scheme must satisfy the following two properties:
- Hiding: the commitment does not reveal anything about the committed polynomial.
- Binding: given the commitment to
$p(x)$ ,$\mathrm{cm} (p)$ , it is infeasible to find another$q(x)$ , such that$\mathrm{cm} (p) = \mathrm{cm} (q)$
One way to build a PCS is by using a pairing-friendly elliptic curve, such as BN254 or BLS12-381. We will work here with type-3 pairings, which are functions
- Bilinearity:
$e(a g_1 , b g_2) = e(g_1 , g_2 )^{ab}$ . - Non-degeneracy: If
$e(P,Q) = 1$ , then either$P = \mathcal{O}$ or$Q = \mathcal{O}$ .
KZG commitment scheme works in this setting, which is the tool we will use. Why are pairings useful? Because they provide us with a way of multiplying things hidden inside an elliptic curve group.
We pick a random
We commit to the polynomial by computing
Using pairings, we could prove the relationship between the polynomial
With this construction, we do not need to supply the verifier with the coefficients of the polynomials, only their commitments. This solves part of the problem but not everything.
The program/circuit that we want to prove is defined by the matrix
We have the polynomial
We have one problem, though. How do we know that the prover used the same
We got another check. Finally, how do we know that the verifier computed
We could force the prover to provide the same linear combination, but with the points all shifted by some constant
The proof
- The commitment to
$V_w (x)$ using$g_1$ . - The commitment to
$V_w (x)$ using$g_2$ . - The commitment to the quotient polynomial
$q(x)$ using$g_1$ . - The commitment to
$B_w (x)$ using$g_1$
The verification involves six pairings (the pairing
To compute the commitments, we need parameters
Prover and verifier agree on a pairing-friendly elliptic curve and generators of the groups
-
$\{s^k g_1 \}$ for$k = 0, 1, 2 , ... m$ -
$\{U_j (s) g_1 \}$ for$j = l , l + 1 , ... m$ ($l$ being the number of public inputs). -
$\{U_j (s) g_2 \}$ for$j = l , l + 1 , ... m$ -
$\{\beta U_j (s) g_1 \}$ for$j = l , l + 1 , ... m$
The verifying key consists of the following:
-
$\{U_j (s) g_1 \}$ for$j = 0 , 1 , ... l - 1$ -
$\{U_j (s) g_2 \}$ for$j = 0 , 1 , ... l - 1$ -
$[Z^\prime ] = (s^m - 1)g_2$ (commitment to the vanishing polynomial) $e(g_1 , g_2)^{ - 1}$ $\beta \gamma g_1$ $\gamma g_2$
The steps for the prover are as follows:
- Compute
$[V_w ] = V_w (s) g_1$ ,$[V_w^\prime ] = V_w (s) g_2$ , and$[B_w ] = B_w (s) g_1$ using the proving key. - Compute the polynomial quotient polynomial
$q(x)$ from the zerofier$Z(x)$ , the vector of witness and instance, and the polynomials describing the circuit$U_j (x)$ . - Compute
$[q ] = q(s) g_1$ using the proving key. - Produce the proof
$\pi = ( [q] , [V_w ] , [V_w^\prime ] , [B_w ])$
The verifier has the following steps:
- Parse the proof
$\pi$ as$[q] , [V_w ] , [V_w^\prime ] , [B_w ]$ . - Check
$e( [V_w ] , g_2 ) = e( g_1 , [V_w^\prime ])$ - Check
$e( [B_w] , \gamma g_2) = e( \beta \gamma g_1 , [V_w^\prime ])$ - Compute
$[V_u ] = V_u (s) g_1$ , and$[V_u^\prime ] = V_u (s) g_2$ using the verifying key. - Check
$e([V_u ] + [V_w ] , [V_u^\prime ] + [V_w^\prime ])e(g_1 , g_2)^{ - 1} = e( [q] , [Z^\prime])$
If all checks pass, the proof is valid.
- Interpolation is done using the Fast Fourier Transform (FFT). This is possible because BLS12-381's scalar field has
$2^{32}$ as one of its factors. - The quotient is calculated in evaluation form, using the FFT. We need to evaluate the polynomials at
$\mu \omega^k$ , where$\mu$ is the offset (we want to evaluate on cosets because if we evaluate directly over$D_i$ , we get$0/0$ ). - The evaluation of the vanishing polynomial is straightforward:
$Z(\mu \omega^k ) = (\mu \omega^k )^m - 1 = \mu^m - 1$ , because$\omega$ has order$m$ . - Compute multiscalar multiplications using Pippenger's algorithm.
The protocol above is not zero-knowledge since
- The polynomial
$p(x) = \left(\sum_k z_j U_j(x) + \delta Z(x) \right)^2 - 1$ . Note that adding$Z(x)$ does not change the main condition, which is that the constraints are satisfied if and only if$p(x)$ is divisible by$Z(x)$ . - Compute
$[V_w ] = (V_w (s) + \delta Z(s)) g_1$ ,$[V_w^\prime ] = (V_w (s) + \delta Z(s)) g_2$ , and$[B_w ] = (B_w (s) + \beta \delta Z(s)) g_1$ .
The verifier's steps are unchanged.