small update, fix trusted setup ops over Field R
arnaucube arnaucube@gmail.com
Sun, 05 May 2019 22:59:53 +0200
4 files changed,
41 insertions(+),
25 deletions(-)
M
README.md
→
README.md
@@ -7,7 +7,7 @@ - `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.pdf
- `Pinocchio: Nearly practical verifiable computation`, Bryan Parno, Craig Gentry, Jon Howell, Mariana Raykova https://eprint.iacr.org/2013/279.pdf ## Caution -Implementation from scratch in Go to understand the concepts. Do not use in production. +Implementation of the zkSNARK [Pinocchio protocol](https://eprint.iacr.org/2013/279.pdf) from scratch in Go to understand the concepts. Do not use in production. Not finished, implementing this in my free time to understand it better, so I don't have much time.@@ -15,17 +15,18 @@ Current implementation status:
- [x] Finite Fields (1, 2, 6, 12) operations - [x] G1 and G2 curve operations - [x] BN128 Pairing -- [x] circuit code compiler +- [ ] circuit code compiler - [ ] code to flat code (improve circuit compiler) - [x] flat code compiler + - [ ] private & public inputs. fix circuit compiler - [x] circuit to R1CS - [x] polynomial operations - [x] R1CS to QAP - [x] generate trusted setup - [x] generate proofs - [x] verify proofs with BN128 pairing - - [ ] fix 4th pairing proofs generation & verification: ê(Vkx+piA, piB) == ê(piH, Vkz) * ê(piC, g2) -- [ ] WASM implementation to run on browsers + - [ ] fix 4th pairing proofs generation & verification: ê(Vkx+piA, piB) == ê(piH, Vkz) * ê(piC, G2) +- [ ] move witness calculation outside the setup phase ## Usage
M
r1csqap/r1csqap.go
→
r1csqap/r1csqap.go
@@ -189,24 +189,24 @@ }
// CombinePolynomials combine the given polynomials arrays into one, also returns the P(x) func (pf PolynomialField) CombinePolynomials(r []*big.Int, ap, bp, cp [][]*big.Int) ([]*big.Int, []*big.Int, []*big.Int, []*big.Int) { - var alpha []*big.Int + var ax []*big.Int for i := 0; i < len(r); i++ { m := pf.Mul([]*big.Int{r[i]}, ap[i]) - alpha = pf.Add(alpha, m) + ax = pf.Add(ax, m) } - var beta []*big.Int + var bx []*big.Int for i := 0; i < len(r); i++ { m := pf.Mul([]*big.Int{r[i]}, bp[i]) - beta = pf.Add(beta, m) + bx = pf.Add(bx, m) } - var gamma []*big.Int + var cx []*big.Int for i := 0; i < len(r); i++ { m := pf.Mul([]*big.Int{r[i]}, cp[i]) - gamma = pf.Add(gamma, m) + cx = pf.Add(cx, m) } - px := pf.Sub(pf.Mul(alpha, beta), gamma) - return alpha, beta, gamma, px + px := pf.Sub(pf.Mul(ax, bx), cx) + return ax, bx, cx, px } // DivisorPolynomial returns the divisor polynomial given two polynomials
M
snark.go
→
snark.go
@@ -99,12 +99,14 @@ // input soundness
for i := 0; i < len(alphas); i++ { for j := 0; j < len(alphas[i]); j++ { if j <= circuit.NPublic { - if bytes.Equal(alphas[i][j].Bytes(), Utils.Bn.Fq1.Zero().Bytes()) { - alphas[i][j] = Utils.Bn.Fq1.One() + if bytes.Equal(alphas[i][j].Bytes(), Utils.FqR.Zero().Bytes()) { + alphas[i][j] = Utils.FqR.One() } } } } + + fmt.Println("alphas[1]", alphas[1]) // generate random t value setup.Toxic.T, err = Utils.FqR.Rand()@@ -176,7 +178,8 @@
// for i := 0; i < circuit.NVars; i++ { for i := 0; i < len(circuit.Signals); i++ { at := Utils.PF.Eval(alphas[i], setup.Toxic.T) - rhoAat := Utils.Bn.Fq1.Mul(setup.Toxic.RhoA, at) + // rhoAat := Utils.Bn.Fq1.Mul(setup.Toxic.RhoA, at) + rhoAat := Utils.FqR.Mul(setup.Toxic.RhoA, at) a := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoAat) setup.Pk.A = append(setup.Pk.A, a) if i <= circuit.NPublic {@@ -184,13 +187,15 @@ setup.Vk.IC = append(setup.Vk.IC, a)
} bt := Utils.PF.Eval(betas[i], setup.Toxic.T) - rhoBbt := Utils.Bn.Fq1.Mul(setup.Toxic.RhoB, bt) + // rhoBbt := Utils.Bn.Fq1.Mul(setup.Toxic.RhoB, bt) + rhoBbt := Utils.FqR.Mul(setup.Toxic.RhoB, bt) bg1 := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoBbt) bg2 := Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, rhoBbt) setup.Pk.B = append(setup.Pk.B, bg2) ct := Utils.PF.Eval(gammas[i], setup.Toxic.T) - rhoCct := Utils.Bn.Fq1.Mul(setup.Toxic.RhoC, ct) + // rhoCct := Utils.Bn.Fq1.Mul(setup.Toxic.RhoC, ct) + rhoCct := Utils.FqR.Mul(setup.Toxic.RhoC, ct) c := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoCct) setup.Pk.C = append(setup.Pk.C, c)@@ -212,8 +217,7 @@ }
// z pol zpol := []*big.Int{big.NewInt(int64(1))} - // for i := 1; i < len(circuit.Constraints); i++ { - for i := 1; i <= circuit.NPublic; i++ { // circuit.NPublic == d + for i := 1; i < len(circuit.Constraints); i++ { zpol = Utils.PF.Mul( zpol, []*big.Int{@@ -222,10 +226,12 @@ big.NewInt(int64(i))),
big.NewInt(int64(1)), }) } + fmt.Println("zpol", zpol) setup.Pk.Z = zpol zt := Utils.PF.Eval(zpol, setup.Toxic.T) - rhoCzt := Utils.Bn.Fq1.Mul(setup.Toxic.RhoC, zt) + // rhoCzt := Utils.Bn.Fq1.Mul(setup.Toxic.RhoC, zt) + rhoCzt := Utils.FqR.Mul(setup.Toxic.RhoC, zt) setup.Vk.Vkz = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, rhoCzt) // encrypt t values with curve generators@@ -234,7 +240,8 @@ gt1 = append(gt1, Utils.Bn.G1.G) // the first is t**0 * G1 = 1 * G1 = G1
tEncr := setup.Toxic.T for i := 1; i < len(zpol); i++ { //should be G1T = pkH = (tau**i * G1) from i=0 to d, where d is degree of pol Z(x) gt1 = append(gt1, Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, tEncr)) - tEncr = Utils.Bn.Fq1.Mul(tEncr, setup.Toxic.T) + // tEncr = Utils.Bn.Fq1.Mul(tEncr, setup.Toxic.T) + tEncr = Utils.FqR.Mul(tEncr, setup.Toxic.T) } fmt.Println("len(G1T)", len(gt1)) setup.G1T = gt1@@ -272,8 +279,8 @@
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) // maybe move this calculation to a previous step // piH = pkH,0 + sum ( hi * pk H,i ), where pkH = G1T, hi=hx - proof.PiH = Utils.Bn.G1.Add(proof.PiH, setup.G1T[0]) - for i := 1; i < len(setup.Pk.Z); i++ { + // proof.PiH = Utils.Bn.G1.Add(proof.PiH, setup.G1T[0]) + for i := 0; i < len(hx); i++ { proof.PiH = Utils.Bn.G1.Add(proof.PiH, Utils.Bn.G1.MulScalar(setup.G1T[i], hx[i])) }
M
snark_test.go
→
snark_test.go
@@ -50,10 +50,11 @@ fmt.Println("b:", b)
fmt.Println("c:", c) // R1CS to QAP + // TODO zxQAP is not used and is an old impl, bad calculated. TODO remove alphas, betas, gammas, zxQAP := Utils.PF.R1CSToQAP(a, b, c) fmt.Println("qap") fmt.Println("alphas", len(alphas)) - fmt.Println("alphas", alphas[0]) + fmt.Println("alphas[1]", alphas[1]) fmt.Println("betas", len(betas)) fmt.Println("gammas", len(gammas)) fmt.Println("zx length", len(zxQAP))@@ -63,6 +64,10 @@ fmt.Println("ax length", len(ax))
fmt.Println("bx length", len(bx)) fmt.Println("cx length", len(cx)) fmt.Println("px length", len(px)) + fmt.Println("px[last]", px[0]) + px0 := Utils.PF.F.Add(px[0], big.NewInt(int64(88))) + fmt.Println(px0) + assert.Equal(t, px0.Bytes(), Utils.PF.F.Zero().Bytes()) hxQAP := Utils.PF.DivisorPolynomial(px, zxQAP) fmt.Println("hx length", len(hxQAP))@@ -92,15 +97,18 @@ fmt.Println("hx pk.z", hxQAP)
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) fmt.Println("hx pk.z", hx) // assert.Equal(t, hxQAP, hx) + assert.Equal(t, px, Utils.PF.Mul(hxQAP, zxQAP)) + // hx==px/zx so px==hx*zx assert.Equal(t, px, Utils.PF.Mul(hx, setup.Pk.Z)) + // check length of polynomials H(x) and Z(x) assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1) assert.Equal(t, len(hxQAP), len(px)-len(zxQAP)+1) + // fmt.Println("pk.Z", len(setup.Pk.Z)) // fmt.Println("zxQAP", len(zxQAP)) - // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t) proof, err := GenerateProofs(*circuit, setup, w, px) assert.Nil(t, err)