mirror of
https://github.com/arnaucube/go-snark-study.git
synced 2026-02-02 17:26:41 +01:00
snark.Utils packed
This commit is contained in:
48
README.md
48
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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
194
snark.go
194
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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user