Browse Source

small update, fix trusted setup ops over Field R

pull/5/head
arnaucube 5 years ago
parent
commit
de33c12283
4 changed files with 41 additions and 25 deletions
  1. +5
    -4
      README.md
  2. +8
    -8
      r1csqap/r1csqap.go
  3. +18
    -11
      snark.go
  4. +10
    -2
      snark_test.go

+ 5
- 4
README.md

@ -7,7 +7,7 @@ zkSNARK library implementation in Go
- `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

+ 8
- 8
r1csqap/r1csqap.go

@ -189,24 +189,24 @@ func (pf PolynomialField) R1CSToQAP(a, b, c [][]*big.Int) ([][]*big.Int, [][]*bi
// 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

+ 18
- 11
snark.go

@ -99,13 +99,15 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
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()
if err != nil {
@ -176,7 +178,8 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
// 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 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
}
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 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
// 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 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
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 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
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 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, w []*big.Int,
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]))
}

+ 10
- 2
snark_test.go

@ -50,10 +50,11 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
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 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
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 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
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)

Loading…
Cancel
Save