diff --git a/README.md b/README.md index 9ba5773..4c168e4 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Not finished, implementing this in my free time to understand it better, so I do Current implementation status: - [x] Finite Fields (1, 2, 6, 12) operations -- [x] G1 and G2 operations +- [x] G1 and G2 curve operations - [x] BN128 Pairing - [x] circuit code compiler - [ ] code to flat code @@ -35,15 +35,6 @@ Current implementation status: Example: ```go -bn, err := bn128.NewBn128() -assert.Nil(t, err) - -// new Finite Field -fqR := fields.NewFq(bn.R) - -// new Polynomial Field -pf := r1csqap.NewPolynomialField(f) - // compile circuit and get the R1CS flatCode := ` func test(x): @@ -52,11 +43,23 @@ func test(x): z = x + y out = z + 5 ` + // parse the code parser := circuitcompiler.NewParser(strings.NewReader(flatCode)) circuit, err := parser.Parse() assert.Nil(t, err) fmt.Println(circuit) + +// witness +b3 := big.NewInt(int64(3)) +inputs := []*big.Int{b3} +w := circuit.CalculateWitness(inputs) +fmt.Println("\nwitness", w) +/* +now we have the witness: +w = [1 3 35 9 27 30] +*/ + // flat code to R1CS fmt.Println("generating R1CS from flat code") a, b, c := circuit.GenerateR1CS() @@ -69,41 +72,36 @@ c == [[0 0 0 1 0 0] [0 0 0 0 1 0] [0 0 0 0 0 1] [0 0 1 0 0 0]] */ -alphas, betas, gammas, zx := pf.R1CSToQAP(a, b, c) +alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c) -// wittness -b3 := big.NewInt(int64(3)) -inputs := []*big.Int{b3} -w := circuit.CalculateWitness(inputs) -fmt.Println("\nwitness", w) -ax, bx, cx, px := pf.CombinePolynomials(w, alphas, betas, gammas) +ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas) -hx := pf.DivisorPolinomial(px, zx) +hx := snark.Utils.PF.DivisorPolinomial(px, zx) // hx==px/zx so px==hx*zx -assert.Equal(t, px, pf.Mul(hx, zx)) +assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx)) // p(x) = a(x) * b(x) - c(x) == h(x) * z(x) -abc := pf.Sub(pf.Mul(ax, bx), cx) +abc := snark.Utils.PF.Sub(pf.Mul(ax, bx), cx) assert.Equal(t, abc, px) -hz := pf.Mul(hx, zx) +hz := snark.Utils.PF.Mul(hx, zx) assert.Equal(t, abc, hz) -div, rem := pf.Div(px, zx) +div, rem := snark.Utils.PF.Div(px, zx) assert.Equal(t, hx, div) assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4)) // calculate trusted setup -setup, err := GenerateTrustedSetup(bn, fqR, pf, len(w), circuit, alphas, betas, gammas, zx) +setup, err := snark.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas, zx) assert.Nil(t, err) fmt.Println("t", setup.Toxic.T) // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t) -proof, err := GenerateProofs(bn, fqR, circuit, setup, hx, w) +proof, err := snark.GenerateProofs(circuit, setup, hx, w) assert.Nil(t, err) -assert.True(t, VerifyProof(bn, circuit, setup, proof)) +assert.True(t, snark.VerifyProof(circuit, setup, proof)) ``` ### Test diff --git a/circuitcompiler/circuit.go b/circuitcompiler/circuit.go index f3f6c3b..af16b9e 100644 --- a/circuitcompiler/circuit.go +++ b/circuitcompiler/circuit.go @@ -33,7 +33,7 @@ type Constraint struct { Out string Literal string - Inputs []string // in func delcaration case + Inputs []string // in func declaration case } func indexInArray(arr []string, e string) int { diff --git a/r1csqap/r1csqap.go b/r1csqap/r1csqap.go index 8e6458b..d764d2c 100644 --- a/r1csqap/r1csqap.go +++ b/r1csqap/r1csqap.go @@ -90,7 +90,7 @@ func (pf PolynomialField) Add(a, b []*big.Int) []*big.Int { return r } -// Sub substracts two polinomials over the Finite Field +// Sub subtracts two polinomials over the Finite Field func (pf PolynomialField) Sub(a, b []*big.Int) []*big.Int { r := ArrayOfBigZeros(max(len(a), len(b))) for i := 0; i < len(a); i++ { @@ -194,7 +194,7 @@ func (pf PolynomialField) CombinePolynomials(r []*big.Int, ap, bp, cp [][]*big.I } // DivisorPolynomial returns the divisor polynomial given two polynomials -func (pf PolynomialField) DivisorPolinomial(px, z []*big.Int) []*big.Int { +func (pf PolynomialField) DivisorPolynomial(px, z []*big.Int) []*big.Int { quo, _ := pf.Div(px, z) return quo } diff --git a/r1csqap/r1csqap_test.go b/r1csqap/r1csqap_test.go index aba859f..08c4597 100644 --- a/r1csqap/r1csqap_test.go +++ b/r1csqap/r1csqap_test.go @@ -146,7 +146,7 @@ func TestR1CSToQAP(t *testing.T) { fmt.Println(cx) fmt.Println(px) - hx := pf.DivisorPolinomial(px, zx) + hx := pf.DivisorPolynomial(px, zx) fmt.Println(hx) // hx==px/zx so px==hx*zx diff --git a/snark.go b/snark.go index 43691b8..0ac61de 100644 --- a/snark.go +++ b/snark.go @@ -62,59 +62,85 @@ type Proof struct { PublicSignals []*big.Int } +type utils struct { + Bn bn128.Bn128 + FqR fields.Fq + PF r1csqap.PolynomialField +} + +// Utils is the data structure holding the BN128, FqR Finite Field over R, PolynomialField, that will be used inside the snarks operations +var Utils = prepareUtils() + +func prepareUtils() utils { + bn, err := bn128.NewBn128() + if err != nil { + panic(err) + } + // new Finite Field + fqR := fields.NewFq(bn.R) + // new Polynomial Field + pf := r1csqap.NewPolynomialField(fqR) + + return utils{ + Bn: bn, + FqR: fqR, + PF: pf, + } +} + // GenerateTrustedSetup generates the Trusted Setup from a compiled Circuit. The Setup.Toxic sub data structure must be destroyed -func GenerateTrustedSetup(bn bn128.Bn128, fqR fields.Fq, pf r1csqap.PolynomialField, witnessLength int, circuit circuitcompiler.Circuit, alphas, betas, gammas [][]*big.Int, zx []*big.Int) (Setup, error) { +func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, alphas, betas, gammas [][]*big.Int, zx []*big.Int) (Setup, error) { var setup Setup var err error // generate random t value - setup.Toxic.T, err = fqR.Rand() + setup.Toxic.T, err = Utils.FqR.Rand() if err != nil { return Setup{}, err } // k for calculating pi' and Vk - setup.Toxic.Ka, err = fqR.Rand() + setup.Toxic.Ka, err = Utils.FqR.Rand() if err != nil { return Setup{}, err } - setup.Toxic.Kb, err = fqR.Rand() + setup.Toxic.Kb, err = Utils.FqR.Rand() if err != nil { return Setup{}, err } - setup.Toxic.Kc, err = fqR.Rand() + setup.Toxic.Kc, err = Utils.FqR.Rand() if err != nil { return Setup{}, err } // generate Kβ (Kbeta) and Kγ (Kgamma) - setup.Toxic.Kbeta, err = fqR.Rand() + setup.Toxic.Kbeta, err = Utils.FqR.Rand() if err != nil { return Setup{}, err } - setup.Toxic.Kgamma, err = fqR.Rand() + setup.Toxic.Kgamma, err = Utils.FqR.Rand() if err != nil { return Setup{}, err } // generate ρ (Rho): ρA, ρB, ρC - setup.Toxic.RhoA, err = fqR.Rand() + setup.Toxic.RhoA, err = Utils.FqR.Rand() if err != nil { return Setup{}, err } - setup.Toxic.RhoB, err = fqR.Rand() + setup.Toxic.RhoB, err = Utils.FqR.Rand() if err != nil { return Setup{}, err } - setup.Toxic.RhoC = fqR.Mul(setup.Toxic.RhoA, setup.Toxic.RhoB) + setup.Toxic.RhoC = Utils.FqR.Mul(setup.Toxic.RhoA, setup.Toxic.RhoB) // encrypt t values with curve generators var gt1 [][3]*big.Int var gt2 [][3][2]*big.Int for i := 0; i < witnessLength; i++ { - tPow := fqR.Exp(setup.Toxic.T, big.NewInt(int64(i))) - tEncr1 := bn.G1.MulScalar(bn.G1.G, tPow) + tPow := Utils.FqR.Exp(setup.Toxic.T, big.NewInt(int64(i))) + tEncr1 := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, tPow) gt1 = append(gt1, tEncr1) - tEncr2 := bn.G2.MulScalar(bn.G2.G, tPow) + tEncr2 := Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, tPow) gt2 = append(gt2, tEncr2) } // gt1: g1, g1*t, g1*t^2, g1*t^3, ... @@ -122,9 +148,9 @@ func GenerateTrustedSetup(bn bn128.Bn128, fqR fields.Fq, pf r1csqap.PolynomialFi setup.G1T = gt1 setup.G2T = gt2 - setup.Vk.Vka = bn.G2.MulScalar(bn.G2.G, setup.Toxic.Ka) - setup.Vk.Vkb = bn.G1.MulScalar(bn.G1.G, setup.Toxic.Kb) - setup.Vk.Vkc = bn.G2.MulScalar(bn.G2.G, setup.Toxic.Kc) + setup.Vk.Vka = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Ka) + setup.Vk.Vkb = Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, setup.Toxic.Kb) + setup.Vk.Vkc = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kc) /* Verification keys: @@ -132,78 +158,78 @@ func GenerateTrustedSetup(bn bn128.Bn128, fqR fields.Fq, pf r1csqap.PolynomialFi - Vk_betagamma2: setup.G2Kbg = g2 * Kbeta*Kgamma - Vk_gamma: setup.G2Kg = g2 * Kgamma */ - kbg := fqR.Mul(setup.Toxic.Kbeta, setup.Toxic.Kgamma) - setup.Vk.G1Kbg = bn.G1.MulScalar(bn.G1.G, kbg) - setup.Vk.G2Kbg = bn.G2.MulScalar(bn.G2.G, kbg) - setup.Vk.G2Kg = bn.G2.MulScalar(bn.G2.G, setup.Toxic.Kgamma) + kbg := Utils.FqR.Mul(setup.Toxic.Kbeta, setup.Toxic.Kgamma) + setup.Vk.G1Kbg = Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, kbg) + setup.Vk.G2Kbg = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, kbg) + setup.Vk.G2Kg = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kgamma) // for i := 0; i < circuit.NSignals; i++ { for i := 0; i < circuit.NVars; i++ { - at := pf.Eval(alphas[i], setup.Toxic.T) - a := bn.G1.MulScalar(bn.G1.G, at) + at := Utils.PF.Eval(alphas[i], setup.Toxic.T) + a := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, at) setup.Pk.A = append(setup.Pk.A, a) if i <= circuit.NPublic { setup.Vk.A = append(setup.Vk.A, a) } - bt := pf.Eval(betas[i], setup.Toxic.T) - bg1 := bn.G1.MulScalar(bn.G1.G, bt) - bg2 := bn.G2.MulScalar(bn.G2.G, bt) + bt := Utils.PF.Eval(betas[i], setup.Toxic.T) + bg1 := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, bt) + bg2 := Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, bt) setup.Pk.B = append(setup.Pk.B, bg2) - ct := pf.Eval(gammas[i], setup.Toxic.T) - c := bn.G1.MulScalar(bn.G1.G, ct) + ct := Utils.PF.Eval(gammas[i], setup.Toxic.T) + c := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, ct) setup.Pk.C = append(setup.Pk.C, c) - kt := fqR.Add(fqR.Add(at, bt), ct) - k := bn.G1.Affine(bn.G1.MulScalar(bn.G1.G, kt)) + kt := Utils.FqR.Add(Utils.FqR.Add(at, bt), ct) + k := Utils.Bn.G1.Affine(Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, kt)) - ktest := bn.G1.Affine(bn.G1.Add(bn.G1.Add(a, bg1), c)) - if !bn.Fq2.Equal(k, ktest) { + ktest := Utils.Bn.G1.Affine(Utils.Bn.G1.Add(Utils.Bn.G1.Add(a, bg1), c)) + if !Utils.Bn.Fq2.Equal(k, ktest) { os.Exit(1) return setup, err } - setup.Pk.Ap = append(setup.Pk.Ap, bn.G1.MulScalar(a, setup.Toxic.Ka)) - setup.Pk.Bp = append(setup.Pk.Bp, bn.G1.MulScalar(bg1, setup.Toxic.Kb)) - setup.Pk.Cp = append(setup.Pk.Cp, bn.G1.MulScalar(c, setup.Toxic.Kc)) - k_ := bn.G1.MulScalar(bn.G1.G, kt) - setup.Pk.Kp = append(setup.Pk.Kp, bn.G1.MulScalar(k_, setup.Toxic.Kbeta)) + setup.Pk.Ap = append(setup.Pk.Ap, Utils.Bn.G1.MulScalar(a, setup.Toxic.Ka)) + setup.Pk.Bp = append(setup.Pk.Bp, Utils.Bn.G1.MulScalar(bg1, setup.Toxic.Kb)) + setup.Pk.Cp = append(setup.Pk.Cp, Utils.Bn.G1.MulScalar(c, setup.Toxic.Kc)) + k_ := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, kt) + setup.Pk.Kp = append(setup.Pk.Kp, Utils.Bn.G1.MulScalar(k_, setup.Toxic.Kbeta)) } - setup.Vk.Vkz = bn.G2.MulScalar(bn.G2.G, pf.Eval(zx, setup.Toxic.T)) + setup.Vk.Vkz = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, Utils.PF.Eval(zx, setup.Toxic.T)) return setup, nil } // GenerateProofs generates all the parameters to proof the zkSNARK from the Circuit, Setup and the Witness -func GenerateProofs(bn bn128.Bn128, f fields.Fq, circuit circuitcompiler.Circuit, setup Setup, hx []*big.Int, w []*big.Int) (Proof, error) { +func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, hx []*big.Int, w []*big.Int) (Proof, error) { var proof Proof - proof.PiA = [3]*big.Int{bn.G1.F.Zero(), bn.G1.F.Zero(), bn.G1.F.Zero()} - proof.PiAp = [3]*big.Int{bn.G1.F.Zero(), bn.G1.F.Zero(), bn.G1.F.Zero()} - proof.PiB = bn.Fq6.Zero() - proof.PiBp = [3]*big.Int{bn.G1.F.Zero(), bn.G1.F.Zero(), bn.G1.F.Zero()} - proof.PiC = [3]*big.Int{bn.G1.F.Zero(), bn.G1.F.Zero(), bn.G1.F.Zero()} - proof.PiCp = [3]*big.Int{bn.G1.F.Zero(), bn.G1.F.Zero(), bn.G1.F.Zero()} - proof.PiH = [3]*big.Int{bn.G1.F.Zero(), bn.G1.F.Zero(), bn.G1.F.Zero()} - proof.PiKp = [3]*big.Int{bn.G1.F.Zero(), bn.G1.F.Zero(), bn.G1.F.Zero()} + proof.PiA = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()} + proof.PiAp = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()} + proof.PiB = Utils.Bn.Fq6.Zero() + proof.PiBp = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()} + proof.PiC = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()} + proof.PiCp = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()} + proof.PiH = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()} + proof.PiKp = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()} for i := circuit.NPublic + 1; i < circuit.NVars; i++ { - proof.PiA = bn.G1.Add(proof.PiA, bn.G1.MulScalar(setup.Pk.A[i], w[i])) - proof.PiAp = bn.G1.Add(proof.PiAp, bn.G1.MulScalar(setup.Pk.Ap[i], w[i])) + proof.PiA = Utils.Bn.G1.Add(proof.PiA, Utils.Bn.G1.MulScalar(setup.Pk.A[i], w[i])) + proof.PiAp = Utils.Bn.G1.Add(proof.PiAp, Utils.Bn.G1.MulScalar(setup.Pk.Ap[i], w[i])) } for i := 0; i < circuit.NVars; i++ { - proof.PiB = bn.G2.Add(proof.PiB, bn.G2.MulScalar(setup.Pk.B[i], w[i])) - proof.PiBp = bn.G1.Add(proof.PiBp, bn.G1.MulScalar(setup.Pk.Bp[i], w[i])) + proof.PiB = Utils.Bn.G2.Add(proof.PiB, Utils.Bn.G2.MulScalar(setup.Pk.B[i], w[i])) + proof.PiBp = Utils.Bn.G1.Add(proof.PiBp, Utils.Bn.G1.MulScalar(setup.Pk.Bp[i], w[i])) - proof.PiC = bn.G1.Add(proof.PiC, bn.G1.MulScalar(setup.Pk.C[i], w[i])) - proof.PiCp = bn.G1.Add(proof.PiCp, bn.G1.MulScalar(setup.Pk.Cp[i], w[i])) + proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(setup.Pk.C[i], w[i])) + proof.PiCp = Utils.Bn.G1.Add(proof.PiCp, Utils.Bn.G1.MulScalar(setup.Pk.Cp[i], w[i])) - proof.PiKp = bn.G1.Add(proof.PiKp, bn.G1.MulScalar(setup.Pk.Kp[i], w[i])) + proof.PiKp = Utils.Bn.G1.Add(proof.PiKp, Utils.Bn.G1.MulScalar(setup.Pk.Kp[i], w[i])) } for i := 0; i < len(hx); i++ { - proof.PiH = bn.G1.Add(proof.PiH, bn.G1.MulScalar(setup.G1T[i], hx[i])) + proof.PiH = Utils.Bn.G1.Add(proof.PiH, Utils.Bn.G1.MulScalar(setup.G1T[i], hx[i])) } proof.PublicSignals = w[1 : circuit.NPublic+1] @@ -211,64 +237,58 @@ func GenerateProofs(bn bn128.Bn128, f fields.Fq, circuit circuitcompiler.Circuit } // VerifyProof verifies over the BN128 the Pairings of the Proof -func VerifyProof(bn bn128.Bn128, circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool { - +func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool { // e(piA, Va) == e(piA', g2) - pairingPiaVa := bn.Pairing(proof.PiA, setup.Vk.Vka) - pairingPiapG2 := bn.Pairing(proof.PiAp, bn.G2.G) - if !bn.Fq12.Equal(pairingPiaVa, pairingPiapG2) { + pairingPiaVa := Utils.Bn.Pairing(proof.PiA, setup.Vk.Vka) + pairingPiapG2 := Utils.Bn.Pairing(proof.PiAp, Utils.Bn.G2.G) + if !Utils.Bn.Fq12.Equal(pairingPiaVa, pairingPiapG2) { return false - } else { - fmt.Println("✓ e(piA, Va) == e(piA', g2), valid knowledge commitment for A") } + fmt.Println("✓ e(piA, Va) == e(piA', g2), valid knowledge commitment for A") // e(Vb, piB) == e(piB', g2) - pairingVbPib := bn.Pairing(setup.Vk.Vkb, proof.PiB) - pairingPibpG2 := bn.Pairing(proof.PiBp, bn.G2.G) - if !bn.Fq12.Equal(pairingVbPib, pairingPibpG2) { + pairingVbPib := Utils.Bn.Pairing(setup.Vk.Vkb, proof.PiB) + pairingPibpG2 := Utils.Bn.Pairing(proof.PiBp, Utils.Bn.G2.G) + if !Utils.Bn.Fq12.Equal(pairingVbPib, pairingPibpG2) { return false - } else { - fmt.Println("✓ e(Vb, piB) == e(piB', g2), valid knowledge commitment for B") } + fmt.Println("✓ e(Vb, piB) == e(piB', g2), valid knowledge commitment for B") // e(piC, Vc) == e(piC', g2) - pairingPicVc := bn.Pairing(proof.PiC, setup.Vk.Vkc) - pairingPicpG2 := bn.Pairing(proof.PiCp, bn.G2.G) - if !bn.Fq12.Equal(pairingPicVc, pairingPicpG2) { + pairingPicVc := Utils.Bn.Pairing(proof.PiC, setup.Vk.Vkc) + pairingPicpG2 := Utils.Bn.Pairing(proof.PiCp, Utils.Bn.G2.G) + if !Utils.Bn.Fq12.Equal(pairingPicVc, pairingPicpG2) { return false - } else { - fmt.Println("✓ e(piC, Vc) == e(piC', g2), valid knowledge commitment for C") } + fmt.Println("✓ e(piC, Vc) == e(piC', g2), valid knowledge commitment for C") // Vkx, to then calculate Vkx+piA vkxpia := setup.Vk.A[0] for i := 0; i < circuit.NPublic; i++ { - vkxpia = bn.G1.Add(vkxpia, bn.G1.MulScalar(setup.Vk.A[i+1], proof.PublicSignals[i])) + vkxpia = Utils.Bn.G1.Add(vkxpia, Utils.Bn.G1.MulScalar(setup.Vk.A[i+1], proof.PublicSignals[i])) } // e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2) - if !bn.Fq12.Equal( - bn.Pairing(bn.G1.Add(vkxpia, proof.PiA), proof.PiB), - bn.Fq12.Mul( - bn.Pairing(proof.PiH, setup.Vk.Vkz), - bn.Pairing(proof.PiC, bn.G2.G))) { + if !Utils.Bn.Fq12.Equal( + Utils.Bn.Pairing(Utils.Bn.G1.Add(vkxpia, proof.PiA), proof.PiB), + Utils.Bn.Fq12.Mul( + Utils.Bn.Pairing(proof.PiH, setup.Vk.Vkz), + Utils.Bn.Pairing(proof.PiC, Utils.Bn.G2.G))) { return false - } else { - fmt.Println("✓ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked") } + fmt.Println("✓ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked") // e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) // == e(piK, g2Kgamma) - piApiC := bn.G1.Add(bn.G1.Add(vkxpia, proof.PiA), proof.PiC) - pairingPiACG2Kbg := bn.Pairing(piApiC, setup.Vk.G2Kbg) - pairingG1KbgPiB := bn.Pairing(setup.Vk.G1Kbg, proof.PiB) - pairingL := bn.Fq12.Mul(pairingPiACG2Kbg, pairingG1KbgPiB) - pairingR := bn.Pairing(proof.PiKp, setup.Vk.G2Kg) - if !bn.Fq12.Equal(pairingL, pairingR) { + piApiC := Utils.Bn.G1.Add(Utils.Bn.G1.Add(vkxpia, proof.PiA), proof.PiC) + pairingPiACG2Kbg := Utils.Bn.Pairing(piApiC, setup.Vk.G2Kbg) + pairingG1KbgPiB := Utils.Bn.Pairing(setup.Vk.G1Kbg, proof.PiB) + pairingL := Utils.Bn.Fq12.Mul(pairingPiACG2Kbg, pairingG1KbgPiB) + pairingR := Utils.Bn.Pairing(proof.PiKp, setup.Vk.G2Kg) + if !Utils.Bn.Fq12.Equal(pairingL, pairingR) { return false - } else { - fmt.Println("✓ e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) == e(piK, g2Kgamma)") } + fmt.Println("✓ e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) == e(piK, g2Kgamma)") return true } diff --git a/snark_test.go b/snark_test.go index e415304..898fe5d 100644 --- a/snark_test.go +++ b/snark_test.go @@ -5,23 +5,14 @@ import ( "math/big" "strings" "testing" + "time" - "github.com/arnaucube/go-snark/bn128" "github.com/arnaucube/go-snark/circuitcompiler" - "github.com/arnaucube/go-snark/fields" "github.com/arnaucube/go-snark/r1csqap" "github.com/stretchr/testify/assert" ) func TestZkFromFlatCircuitCode(t *testing.T) { - bn, err := bn128.NewBn128() - assert.Nil(t, err) - - // new Finite Field - fqR := fields.NewFq(bn.R) - - // new Polynomial Field - pf := r1csqap.NewPolynomialField(fqR) // compile circuit and get the R1CS flatCode := ` @@ -54,46 +45,47 @@ func TestZkFromFlatCircuitCode(t *testing.T) { fmt.Println("b:", b) fmt.Println("c:", c) - alphas, betas, gammas, zx := pf.R1CSToQAP(a, b, c) + // R1CS to QAP + alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c) + fmt.Println("qap") + fmt.Println(alphas) + fmt.Println(betas) + fmt.Println(gammas) - ax, bx, cx, px := pf.CombinePolynomials(w, alphas, betas, gammas) + ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas) - hx := pf.DivisorPolinomial(px, zx) + hx := Utils.PF.DivisorPolynomial(px, zx) // hx==px/zx so px==hx*zx - assert.Equal(t, px, pf.Mul(hx, zx)) + assert.Equal(t, px, Utils.PF.Mul(hx, zx)) // p(x) = a(x) * b(x) - c(x) == h(x) * z(x) - abc := pf.Sub(pf.Mul(ax, bx), cx) + abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx) assert.Equal(t, abc, px) - hz := pf.Mul(hx, zx) + hz := Utils.PF.Mul(hx, zx) assert.Equal(t, abc, hz) - div, rem := pf.Div(px, zx) + div, rem := Utils.PF.Div(px, zx) assert.Equal(t, hx, div) assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4)) // calculate trusted setup - setup, err := GenerateTrustedSetup(bn, fqR, pf, len(w), *circuit, alphas, betas, gammas, zx) + setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx) assert.Nil(t, err) fmt.Println("\nt:", setup.Toxic.T) // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t) - proof, err := GenerateProofs(bn, fqR, *circuit, setup, hx, w) + proof, err := GenerateProofs(*circuit, setup, hx, w) assert.Nil(t, err) - assert.True(t, VerifyProof(bn, *circuit, setup, proof)) + fmt.Println("\n proofs:") + fmt.Println(proof) + before := time.Now() + assert.True(t, VerifyProof(*circuit, setup, proof)) + fmt.Println("verify proof time elapsed:", time.Since(before)) } func TestZkFromHardcodedR1CS(t *testing.T) { - bn, err := bn128.NewBn128() - assert.Nil(t, err) - - // new Finite Field - fqR := fields.NewFq(bn.R) - - // new Polynomial Field - pf := r1csqap.NewPolynomialField(fqR) b0 := big.NewInt(int64(0)) b1 := big.NewInt(int64(1)) @@ -121,7 +113,7 @@ func TestZkFromHardcodedR1CS(t *testing.T) { []*big.Int{b0, b0, b0, b0, b0, b1}, []*big.Int{b0, b0, b1, b0, b0, b0}, } - alphas, betas, gammas, zx := pf.R1CSToQAP(a, b, c) + alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c) // wittness = 1, 3, 35, 9, 27, 30 w := []*big.Int{b1, b3, b35, b9, b27, b30} @@ -130,31 +122,31 @@ func TestZkFromHardcodedR1CS(t *testing.T) { NPublic: 0, NSignals: len(w), } - ax, bx, cx, px := pf.CombinePolynomials(w, alphas, betas, gammas) + ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas) - hx := pf.DivisorPolinomial(px, zx) + hx := Utils.PF.DivisorPolynomial(px, zx) // hx==px/zx so px==hx*zx - assert.Equal(t, px, pf.Mul(hx, zx)) + assert.Equal(t, px, Utils.PF.Mul(hx, zx)) // p(x) = a(x) * b(x) - c(x) == h(x) * z(x) - abc := pf.Sub(pf.Mul(ax, bx), cx) + abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx) assert.Equal(t, abc, px) - hz := pf.Mul(hx, zx) + hz := Utils.PF.Mul(hx, zx) assert.Equal(t, abc, hz) - div, rem := pf.Div(px, zx) + div, rem := Utils.PF.Div(px, zx) assert.Equal(t, hx, div) assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4)) // calculate trusted setup - setup, err := GenerateTrustedSetup(bn, fqR, pf, len(w), circuit, alphas, betas, gammas, zx) + setup, err := GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas, zx) assert.Nil(t, err) fmt.Println("t", setup.Toxic.T) // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t) - proof, err := GenerateProofs(bn, fqR, circuit, setup, hx, w) + proof, err := GenerateProofs(circuit, setup, hx, w) assert.Nil(t, err) - assert.True(t, VerifyProof(bn, circuit, setup, proof)) + assert.True(t, VerifyProof(circuit, setup, proof)) }