Browse Source

snark.Utils packed

pull/5/head
arnaucube 5 years ago
parent
commit
1375596a74
6 changed files with 164 additions and 154 deletions
  1. +23
    -25
      README.md
  2. +1
    -1
      circuitcompiler/circuit.go
  3. +2
    -2
      r1csqap/r1csqap.go
  4. +1
    -1
      r1csqap/r1csqap_test.go
  5. +107
    -87
      snark.go
  6. +30
    -38
      snark_test.go

+ 23
- 25
README.md

@ -13,7 +13,7 @@ Not finished, implementing this in my free time to understand it better, so I do
Current implementation status: Current implementation status:
- [x] Finite Fields (1, 2, 6, 12) operations - [x] Finite Fields (1, 2, 6, 12) operations
- [x] G1 and G2 operations
- [x] G1 and G2 curve operations
- [x] BN128 Pairing - [x] BN128 Pairing
- [x] circuit code compiler - [x] circuit code compiler
- [ ] code to flat code - [ ] code to flat code
@ -35,15 +35,6 @@ Current implementation status:
Example: Example:
```go ```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 // compile circuit and get the R1CS
flatCode := ` flatCode := `
func test(x): func test(x):
@ -52,11 +43,23 @@ func test(x):
z = x + y z = x + y
out = z + 5 out = z + 5
` `
// parse the code // parse the code
parser := circuitcompiler.NewParser(strings.NewReader(flatCode)) parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
circuit, err := parser.Parse() circuit, err := parser.Parse()
assert.Nil(t, err) assert.Nil(t, err)
fmt.Println(circuit) 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 // flat code to R1CS
fmt.Println("generating R1CS from flat code") fmt.Println("generating R1CS from flat code")
a, b, c := circuit.GenerateR1CS() 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 // 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) // 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) assert.Equal(t, abc, px)
hz := pf.Mul(hx, zx)
hz := snark.Utils.PF.Mul(hx, zx)
assert.Equal(t, abc, hz) 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, hx, div)
assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4)) assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
// calculate trusted setup // 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) assert.Nil(t, err)
fmt.Println("t", setup.Toxic.T) fmt.Println("t", setup.Toxic.T)
// piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(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.Nil(t, err)
assert.True(t, VerifyProof(bn, circuit, setup, proof))
assert.True(t, snark.VerifyProof(circuit, setup, proof))
``` ```
### Test ### Test

+ 1
- 1
circuitcompiler/circuit.go

@ -33,7 +33,7 @@ type Constraint struct {
Out string Out string
Literal string Literal string
Inputs []string // in func delcaration case
Inputs []string // in func declaration case
} }
func indexInArray(arr []string, e string) int { func indexInArray(arr []string, e string) int {

+ 2
- 2
r1csqap/r1csqap.go

@ -90,7 +90,7 @@ func (pf PolynomialField) Add(a, b []*big.Int) []*big.Int {
return r 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 { func (pf PolynomialField) Sub(a, b []*big.Int) []*big.Int {
r := ArrayOfBigZeros(max(len(a), len(b))) r := ArrayOfBigZeros(max(len(a), len(b)))
for i := 0; i < len(a); i++ { 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 // 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) quo, _ := pf.Div(px, z)
return quo return quo
} }

+ 1
- 1
r1csqap/r1csqap_test.go

@ -146,7 +146,7 @@ func TestR1CSToQAP(t *testing.T) {
fmt.Println(cx) fmt.Println(cx)
fmt.Println(px) fmt.Println(px)
hx := pf.DivisorPolinomial(px, zx)
hx := pf.DivisorPolynomial(px, zx)
fmt.Println(hx) fmt.Println(hx)
// hx==px/zx so px==hx*zx // hx==px/zx so px==hx*zx

+ 107
- 87
snark.go

@ -62,59 +62,85 @@ type Proof struct {
PublicSignals []*big.Int 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 // 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 setup Setup
var err error var err error
// generate random t value // generate random t value
setup.Toxic.T, err = fqR.Rand()
setup.Toxic.T, err = Utils.FqR.Rand()
if err != nil { if err != nil {
return Setup{}, err return Setup{}, err
} }
// k for calculating pi' and Vk // k for calculating pi' and Vk
setup.Toxic.Ka, err = fqR.Rand()
setup.Toxic.Ka, err = Utils.FqR.Rand()
if err != nil { if err != nil {
return Setup{}, err return Setup{}, err
} }
setup.Toxic.Kb, err = fqR.Rand()
setup.Toxic.Kb, err = Utils.FqR.Rand()
if err != nil { if err != nil {
return Setup{}, err return Setup{}, err
} }
setup.Toxic.Kc, err = fqR.Rand()
setup.Toxic.Kc, err = Utils.FqR.Rand()
if err != nil { if err != nil {
return Setup{}, err return Setup{}, err
} }
// generate Kβ (Kbeta) and Kγ (Kgamma) // generate Kβ (Kbeta) and Kγ (Kgamma)
setup.Toxic.Kbeta, err = fqR.Rand()
setup.Toxic.Kbeta, err = Utils.FqR.Rand()
if err != nil { if err != nil {
return Setup{}, err return Setup{}, err
} }
setup.Toxic.Kgamma, err = fqR.Rand()
setup.Toxic.Kgamma, err = Utils.FqR.Rand()
if err != nil { if err != nil {
return Setup{}, err return Setup{}, err
} }
// generate ρ (Rho): ρA, ρB, ρC // generate ρ (Rho): ρA, ρB, ρC
setup.Toxic.RhoA, err = fqR.Rand()
setup.Toxic.RhoA, err = Utils.FqR.Rand()
if err != nil { if err != nil {
return Setup{}, err return Setup{}, err
} }
setup.Toxic.RhoB, err = fqR.Rand()
setup.Toxic.RhoB, err = Utils.FqR.Rand()
if err != nil { if err != nil {
return Setup{}, err 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 // encrypt t values with curve generators
var gt1 [][3]*big.Int var gt1 [][3]*big.Int
var gt2 [][3][2]*big.Int var gt2 [][3][2]*big.Int
for i := 0; i < witnessLength; i++ { 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) 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) gt2 = append(gt2, tEncr2)
} }
// gt1: g1, g1*t, g1*t^2, g1*t^3, ... // 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.G1T = gt1
setup.G2T = gt2 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: 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_betagamma2: setup.G2Kbg = g2 * Kbeta*Kgamma
- Vk_gamma: setup.G2Kg = g2 * 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.NSignals; i++ {
for i := 0; i < circuit.NVars; 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) setup.Pk.A = append(setup.Pk.A, a)
if i <= circuit.NPublic { if i <= circuit.NPublic {
setup.Vk.A = append(setup.Vk.A, a) 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) 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) 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) os.Exit(1)
return setup, err 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 return setup, nil
} }
// GenerateProofs generates all the parameters to proof the zkSNARK from the Circuit, Setup and the Witness // 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 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++ { 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++ { 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++ { 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] 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 // 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) // 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 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) // 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 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) // 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 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 // Vkx, to then calculate Vkx+piA
vkxpia := setup.Vk.A[0] vkxpia := setup.Vk.A[0]
for i := 0; i < circuit.NPublic; i++ { 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) // 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 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(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB)
// == e(piK, g2Kgamma) // == 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 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 return true
} }

+ 30
- 38
snark_test.go

@ -5,23 +5,14 @@ import (
"math/big" "math/big"
"strings" "strings"
"testing" "testing"
"time"
"github.com/arnaucube/go-snark/bn128"
"github.com/arnaucube/go-snark/circuitcompiler" "github.com/arnaucube/go-snark/circuitcompiler"
"github.com/arnaucube/go-snark/fields"
"github.com/arnaucube/go-snark/r1csqap" "github.com/arnaucube/go-snark/r1csqap"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestZkFromFlatCircuitCode(t *testing.T) { 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 // compile circuit and get the R1CS
flatCode := ` flatCode := `
@ -54,46 +45,47 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
fmt.Println("b:", b) fmt.Println("b:", b)
fmt.Println("c:", c) 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 // 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) // 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) assert.Equal(t, abc, px)
hz := pf.Mul(hx, zx)
hz := Utils.PF.Mul(hx, zx)
assert.Equal(t, abc, hz) 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, hx, div)
assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4)) assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
// calculate trusted setup // 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) assert.Nil(t, err)
fmt.Println("\nt:", setup.Toxic.T) fmt.Println("\nt:", setup.Toxic.T)
// piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(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.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) { 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)) b0 := big.NewInt(int64(0))
b1 := big.NewInt(int64(1)) 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, b0, b0, b0, b1},
[]*big.Int{b0, b0, b1, b0, b0, b0}, []*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 // wittness = 1, 3, 35, 9, 27, 30
w := []*big.Int{b1, b3, b35, b9, b27, b30} w := []*big.Int{b1, b3, b35, b9, b27, b30}
@ -130,31 +122,31 @@ func TestZkFromHardcodedR1CS(t *testing.T) {
NPublic: 0, NPublic: 0,
NSignals: len(w), 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 // 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) // 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) assert.Equal(t, abc, px)
hz := pf.Mul(hx, zx)
hz := Utils.PF.Mul(hx, zx)
assert.Equal(t, abc, hz) 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, hx, div)
assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4)) assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
// calculate trusted setup // 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) assert.Nil(t, err)
fmt.Println("t", setup.Toxic.T) fmt.Println("t", setup.Toxic.T)
// piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(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.Nil(t, err)
assert.True(t, VerifyProof(bn, circuit, setup, proof))
assert.True(t, VerifyProof(circuit, setup, proof))
} }

Loading…
Cancel
Save