iden3.io
github.com/iden3
twitter.com/identhree
I'm not a mathematician, this talk is not for mathematicians
In free time, have been studying zkSNARKS & implementing it in Go
Talk about a technical explaination from an engineer point of view
The idea is to try to transmit the learnings from long night study hours during last winter
Also at the end will briefly overview how we use zkSNARKs in iden3
This slides will be combined with
Don't use your own crypto. But it's fun to implement it (only for learning purposes)
Generating a proof:
Verifying a proof:
mod
, %
5 mod 12 = 5
14 mod 12 = 2
83 mod 10 = 3
5 + 3 mod 6 = 8 mod 6 = 2
$(x_1, y_1) + (x_2, y_2) = (\dfrac{ x_1 y_2 + x_2 y_1 }{ 1 + d x_1 x_2 y_1 y_2 }, \dfrac{ y_1 y_2 - x_1 x_2 }{ 1-dx_1 x_2 y_1 y_2 })$
(whiteboard explanation)
S1
and S2
into another set S3
21888242871839275222246405745257275088696311157297823662689037894645226208583
21888242871839275222246405745257275088548364400416034343698204186575808495617
$e(P_1 + P_2, Q_1) == e(P_1, Q_1) \cdot e(P_2, Q_1)$
$e(P_1, Q_1 + Q_2) == e(P_1, Q_1) \cdot e(P_1, Q_2)$
$e(aP, bQ) == e(P, Q)^{ab} == e(bP, aQ)$
$e(g_1, g_2)^6 == e(g_1, 6 \cdot g_2)$
$e(g_1, g_2)^6 == e(6 \cdot g_1, g_2)$
$e(g_1, g_2)^6 == e(3 \cdot g_1, 2 g_2)$
$e(g_1, g_2)^6 == e(2 \cdot g_1, 3 g_2)$
(small overview, is offtopic here, but is interesting)
$e(G,S) == e(P, H(m))$
$e(G, s0+s1+s2...) == e(p0, H(m)) \cdot e(p1, H(m)) \cdot e(p2, H(m)) ...$
More info: https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html
not a software compiler -> a constraint prover
constraint concept
value0
== value1
<operation>
value2
want to proof that a certain computation has been done correctly
graphic of circuit with gates (whiteboard)
about high level programing languages for zkSNARKS, by Harry Roberts: https://www.youtube.com/watch?v=nKrBJo3E3FY
Circuit code example: $f(x) = x^5 + 2\cdot x + 6$
func exp5(private a):
b = a * a
c = a * b
d = a * c
e = a * d
return e
func main(private s0, public s1):
s2 = exp5(s0)
s3 = s0 * 2
s4 = s3 + s2
s5 = s4 + 6
equals(s1, s5)
out = 1 * 1
For a certain circuit, with the inputs that we calculate the Witness for the circuit signals
[8]
[32790]
[one s1 s0 b0 c0 d0 s2 s3 s4 s5 out]
[1 32790 8 64 512 4096 32768 16 32784 32790 1]
$(a_{11}s_1 + a_{12}s_2 + ... + a_{1n}s_n) \cdot (b_{11}s_1 + b_{12}s_2 + ... + b_{1n}s_n) - (c_{11}s_1 + c_{12}s_2 + ... + c_{1n}s_n) = 0$
$(a_{21}s_1 + a_{22}s_2 + ... + a_{2n}s_n) \cdot (b_{21}s_1 + b_{22}s_2 + ... + b_{2n}s_n) - (c_{21}s_1 + c_{22}s_2 + ... + c_{2n}s_n) = 0$ $(a_{31}s_1 + a_{32}s_2 + ... + a_{3n}s_n) \cdot (b_{31}s_1 + b_{32}s_2 + ... + b_{3n}s_n) - (c_{31}s_1 + c_{32}s_2 + ... + c_{3n}s_n) = 0$ [...] $(a_{m1}s_1 + a_{m2}s_2 + ... + a_{mn}s_n) \cdot (b_{m1}s_1 + b_{m2}s_2 + ... + b_{mn}s_n) - (c_{m1}s_1 + c_{m2}s_2 + ... + c_{mn}s_n) = 0$
*where $s$ are the signals of the circuit, and we need to find $a, b, c$ that satisfies the equations
R1CS constraint example:
[one s1 s0 b0 c0 d0 s2 s3 s4 s5 out]
[1 32790 8 64 512 4096 32768 16 32784 32790 1]
b0 == s0 * s0
R1CS example:
$A$ | $B$ | $C$: |
---|---|---|
$[0 0 1 0 0 0 0 0 0 0 0]$ $[0 0 1 0 0 0 0 0 0 0 0]$ $[0 0 1 0 0 0 0 0 0 0 0]$ $[0 0 1 0 0 0 0 0 0 0 0]$ $[0 0 1 0 0 0 0 0 0 0 0]$ $[0 0 0 0 0 0 1 1 0 0 0]$ $[6 0 0 0 0 0 0 0 1 0 0]$ $[0 0 0 0 0 0 0 0 0 1 0]$ $[0 1 0 0 0 0 0 0 0 0 0]$ $[1 0 0 0 0 0 0 0 0 0 0]$ |
$[0 0 1 0 0 0 0 0 0 0 0]$ $[0 0 0 1 0 0 0 0 0 0 0]$ $[0 0 0 0 1 0 0 0 0 0 0]$ $[0 0 0 0 0 1 0 0 0 0 0]$ $[2 0 0 0 0 0 0 0 0 0 0]$ $[1 0 0 0 0 0 0 0 0 0 0]$ $[1 0 0 0 0 0 0 0 0 0 0]$ $[1 0 0 0 0 0 0 0 0 0 0]$ $[1 0 0 0 0 0 0 0 0 0 0]$ $[1 0 0 0 0 0 0 0 0 0 0]$ |
$[0 0 0 1 0 0 0 0 0 0 0]$ $[0 0 0 0 1 0 0 0 0 0 0]$ $[0 0 0 0 0 1 0 0 0 0 0]$ $[0 0 0 0 0 0 1 0 0 0 0]$ $[0 0 0 0 0 0 0 1 0 0 0]$ $[0 0 0 0 0 0 0 0 1 0 0]$ $[0 0 0 0 0 0 0 0 0 1 0]$ $[0 1 0 0 0 0 0 0 0 0 0]$ $[0 0 0 0 0 0 0 0 0 1 0]$ $[0 0 0 0 0 0 0 0 0 0 1]$ |
(Polynomial Interpolation)
$L(x) = \sum_{j=0}^{n} y_j l_j(x)$
(small overview, is offtopic here, but is interesting)
$f(x) = \alpha_0 + \alpha_1 x + \alpha_2 x^2 + \alpha_3 x^3 + ... + + \alpha_{n-1} x^{n-1}$
$(\alpha_1(x)s_1 + \alpha_2(x)s_2 + ... + \alpha_n(x)s_n) \cdot (\beta_1(x)s_1 + \beta_2(x)s_2 + ... + \beta_n(x)s_n) - (\gamma_1(x)s_1 + \gamma_2(x)s_2 + ... + \gamma_n(x)s_n) = P(x)$
|----------------------- $A(x)$ -----------------------|------------------------ $B(x)$ -----------------------|------------------------ $C(x)$ ------------------------|
The following explanation is for the Pinocchio protocol, all the examples will be for this protocol. The Groth16 is explained also in the end of this slides.
$g_1 t^0, g_1 t^1, g_1 t^2, g_1 t^3, g_1 t^4, ...$ $g_2 t^0, g_2 t^1, g_2 t^2, g_2 t^3, g_2 t^4, ...$
Proving Key: $pk = (C, pk_A, pk_A', pk_B, pk_B', pk_C, pk_C', pk_H)$ where:
where:
Verification Key: $vk = (vk_A, vk_B, vk_C, vk_\gamma, vk^1_{\beta\gamma}, vk^2_{\beta\gamma}, vk_Z, vk_{IC})$
type Pk struct { // Proving Key pk:=(pkA, pkB, pkC, pkH)
G1T [][3]*big.Int // t encrypted in G1 curve, G1T == Pk.H
A [][3]*big.Int
B [][3][2]*big.Int
C [][3]*big.Int
Kp [][3]*big.Int
Ap [][3]*big.Int
Bp [][3]*big.Int
Cp [][3]*big.Int
Z []*big.Int
}
type Vk struct {
Vka [3][2]*big.Int
Vkb [3]*big.Int
Vkc [3][2]*big.Int
IC [][3]*big.Int
G1Kbg [3]*big.Int // g1 * Kbeta * Kgamma
G2Kbg [3][2]*big.Int // g2 * Kbeta * Kgamma
G2Kg [3][2]*big.Int // g2 * Kgamma
Vkz [3][2]*big.Int
}
// Setup is the data structure holding the Trusted Setup data. The Setup.Toxic sub struct must be destroyed after the GenerateTrustedSetup function is completed
type Setup struct {
Toxic struct {
T *big.Int // trusted setup secret
Ka *big.Int
Kb *big.Int
Kc *big.Int
Kbeta *big.Int
Kgamma *big.Int
RhoA *big.Int
RhoB *big.Int
RhoC *big.Int
}
Pk Pk
Vk Vk
}
for i := 0; i < circuit.NVars; i++ {
proof.PiB = Utils.Bn.G2.Add(proof.PiB, Utils.Bn.G2.MulScalar(pk.B[i], w[i]))
proof.PiBp = Utils.Bn.G1.Add(proof.PiBp, Utils.Bn.G1.MulScalar(pk.Bp[i], w[i]))
}
($c=1+witness+\delta_1+\delta_2+\delta_3$
Verification:
$\dfrac{
e(\pi_A, \pi_B)
}{
e(\pi_C, g_2)
}
= e(g_1 h(t), g_2 z(t))
$
$\dfrac{
e(A_1 + A_2 + ... + A_n, B_1 + B_2 + ... + B_n)
}{
e(C_1 + C_2 + ... + C_n, g_2)
}
= e(g_1 h(t), g_2 z(t))
$
$\dfrac{
e(g_1 \alpha_1(t) s_1 + g_1 \alpha_2(t) s_2 + ... + g_1 \alpha_n(t) s_n, g_2 \beta_1(t)s_1 + g_2 \beta_2(t) s_2 + ... + g_2 \beta_n(t) s_n)
}{
e(g_1 \gamma_1(t) s_1 + g_1 \gamma_2(t) s_2 + ... + g_1 \gamma_n(t) s_n, g_2)
}
= e(g_1 h(t), g_2 z(t))
$
$
e(g_1 \alpha_1(t) s_1 + g_1 \alpha_2(t) s_2 + ... + g_1 \alpha_n(t) s_n, g_2 \beta_1(t)s_1 + g_2 \beta_2(t) s_2 + ... + g_2 \beta_n(t) s_n)$
$= e(g_1 h(t), g_2 z(t)) \cdot e(g_1 \gamma_1(t) s_1 + g_1 \gamma_2(t) s_2 + ... + g_1 \gamma_n(t) s_n, g_2)
$
$\tau = \alpha, \beta, \gamma, \delta, x$
$\sigma_1 =$
$\alpha, \beta, \delta, { x^i}_{i=0}^{n-1}$
${ \dfrac{ \beta u_i(x) + \alpha v_i(x) + w_i(x) }{ \gamma } }_{i=0}^l$
${ \dfrac{ \beta u_i(x) + \alpha v_i(x) + w_i(x) }{ \delta } }_{i=l+1}^m$
${ \dfrac{x^i t(x)}{\delta} }_{i=0}^{n-2}$
$\sigma_2 = (\beta, \gamma, \delta, { x^i }_{i=0}^{n-1})$
(where $u_i(x), v_i(x), w_i(x)$ are the $QAP$)
type Pk struct { // Proving Key
BACDelta [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m
Z []*big.Int
G1 struct {
Alpha [3]*big.Int
Beta [3]*big.Int
Delta [3]*big.Int
At [][3]*big.Int // {a(τ)} from 0 to m
BACGamma [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to m
}
G2 struct {
Beta [3][2]*big.Int
Gamma [3][2]*big.Int
Delta [3][2]*big.Int
BACGamma [][3][2]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to m
}
PowersTauDelta [][3]*big.Int // powers of τ encrypted in G1 curve, divided by δ
}
type Vk struct {
IC [][3]*big.Int
G1 struct {
Alpha [3]*big.Int
}
G2 struct {
Beta [3][2]*big.Int
Gamma [3][2]*big.Int
Delta [3][2]*big.Int
}
}
// Setup is the data structure holding the Trusted Setup data. The Setup.Toxic sub struct must be destroyed after the GenerateTrustedSetup function is completed
type Setup struct {
Toxic struct {
T *big.Int // trusted setup secret
Kalpha *big.Int
Kbeta *big.Int
Kgamma *big.Int
Kdelta *big.Int
}
Pk Pk
Vk Vk
}
$\pi_A=\alpha + \sum_{i=0}^m \alpha_i u_i(x) + r \delta$ $\pi_B=\beta + \sum_{i=0}^m \alpha_i v_i(x) + s \delta$
$\pi_C = \dfrac{ \sum_{i=l+1}^m a_i(\beta u_i(x) + \alpha v_i(x) + w_i(x)) + h(x)t(x) }{ \delta } + \pi_As + \pi_Br -rs\delta$
$\pi=\pi_A^1, \pi_B^1, \pi_C^2$
$[\pi_A]_1 \cdot [\pi_B]_2 = [\alpha]_1 \cdot [\beta]2 + \sum{i=0}^l a_i [ \dfrac{ \beta u_i(x) + \alpha v_i(x) + w_i(x) }{ \gamma } ]_1 \cdot [\gamma]_2 + [\pi_C]_1 \cdot [\delta]_2 $
$e(\pi_A, \pi_B) = e(\alpha, \beta) \cdot e(pub, \gamma) \cdot e(\pi_C, \delta)$
language | snark library with which plugs in |
---|---|
Zokrates | libsnark, bellman |
Snarky | libsnark |
circom | snarkjs, websnark, bellman |
go-snark-circuit | go-snark |
we work over $F_r$, where $r=$21888242871839275222246405745257275088548364400416034343698204186575808495617
BabyJubJub
Mimc
Poseidon
Succinct Non-Interactive Zero Knowledge for a von Neumann Architecture
, Eli Ben-Sasson, Alessandro Chiesa, Eran Tromer, Madars Virza https://eprint.iacr.org/2013/879.pdfPinocchio: Nearly practical verifiable computation
, Bryan Parno, Craig Gentry, Jon Howell, Mariana Raykova https://eprint.iacr.org/2013/279.pdfOn the Size of Pairing-based Non-interactive Arguments
, Jens Groth https://eprint.iacr.org/2016/260.pdf