mirror of
https://github.com/arnaucube/go-snark-study.git
synced 2026-02-02 17:26:41 +01:00
snark trusted setup + generate proof + verify proof working. Added test to bn128 pairing
This commit is contained in:
27
README.md
27
README.md
@@ -5,6 +5,7 @@ zkSNARK library implementation in Go
|
||||
|
||||
|
||||
`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
|
||||
|
||||
### Usage
|
||||
- [](https://godoc.org/github.com/arnaucube/go-snark) zkSnark
|
||||
@@ -18,7 +19,7 @@ bn, err := bn128.NewBn128()
|
||||
assert.Nil(t, err)
|
||||
|
||||
// new Finite Field
|
||||
f := fields.NewFq(bn.R)
|
||||
fqR := fields.NewFq(bn.R)
|
||||
|
||||
// new Polynomial Field
|
||||
pf := r1csqap.NewPolynomialField(f)
|
||||
@@ -34,6 +35,13 @@ w = [1, 3, 35, 9, 27, 30]
|
||||
|
||||
alphas, betas, gammas, zx := pf.R1CSToQAP(a, b, c)
|
||||
|
||||
// wittness = 1, 3, 35, 9, 27, 30
|
||||
w := []*big.Int{b1, b3, b35, b9, b27, b30}
|
||||
circuit := compiler.Circuit{
|
||||
NVars: 6,
|
||||
NPublic: 0,
|
||||
NSignals: len(w),
|
||||
}
|
||||
ax, bx, cx, px := pf.CombinePolynomials(w, alphas, betas, gammas)
|
||||
|
||||
hx := pf.DivisorPolinomial(px, zx)
|
||||
@@ -47,21 +55,20 @@ assert.Equal(t, abc, px)
|
||||
hz := pf.Mul(hx, zx)
|
||||
assert.Equal(t, abc, hz)
|
||||
|
||||
div, rem := pf.Div(px, zx)
|
||||
assert.Equal(t, hx, div)
|
||||
assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
|
||||
|
||||
// calculate trusted setup
|
||||
setup, err := GenerateTrustedSetup(bn, len(ax))
|
||||
setup, err := GenerateTrustedSetup(bn, fqR, pf, len(w), circuit, alphas, betas, gammas, zx)
|
||||
assert.Nil(t, err)
|
||||
fmt.Println("trusted setup:")
|
||||
fmt.Println(setup.G1T)
|
||||
fmt.Println(setup.G2T)
|
||||
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, f, setup, ax, bx, cx, hx, zx)
|
||||
proof, err := GenerateProofs(bn, fqR, circuit, setup, hx, w)
|
||||
assert.Nil(t, err)
|
||||
|
||||
|
||||
// verify the proofs with the bn128 pairing
|
||||
verified := VerifyProof(bn, publicSetup, proof)
|
||||
assert.True(t, verified)
|
||||
assert.True(t, VerifyProof(bn, circuit, setup, proof))
|
||||
```
|
||||
|
||||
### Test
|
||||
|
||||
@@ -105,7 +105,7 @@ func NewBn128() (Bn128, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func NewFqR() (fields.Fq, error){
|
||||
func NewFqR() (fields.Fq, error) {
|
||||
r, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
|
||||
if !ok {
|
||||
return fields.Fq{}, errors.New("err parsing R")
|
||||
@@ -172,16 +172,13 @@ func (bn128 *Bn128) preparePairing() error {
|
||||
|
||||
}
|
||||
|
||||
func (bn128 Bn128) Pairing(p1 [3]*big.Int, p2 [3][2]*big.Int) ([2][3][2]*big.Int, error) {
|
||||
func (bn128 Bn128) Pairing(p1 [3]*big.Int, p2 [3][2]*big.Int) [2][3][2]*big.Int {
|
||||
pre1 := bn128.PreComputeG1(p1)
|
||||
pre2, err := bn128.PreComputeG2(p2)
|
||||
if err != nil {
|
||||
return [2][3][2]*big.Int{}, err
|
||||
}
|
||||
pre2 := bn128.PreComputeG2(p2)
|
||||
|
||||
r1 := bn128.MillerLoop(pre1, pre2)
|
||||
res := bn128.FinalExponentiation(r1)
|
||||
return res, nil
|
||||
return res
|
||||
}
|
||||
|
||||
type AteG1Precomp struct {
|
||||
@@ -209,7 +206,7 @@ type AteG2Precomp struct {
|
||||
Coeffs []EllCoeffs
|
||||
}
|
||||
|
||||
func (bn128 Bn128) PreComputeG2(p [3][2]*big.Int) (AteG2Precomp, error) {
|
||||
func (bn128 Bn128) PreComputeG2(p [3][2]*big.Int) AteG2Precomp {
|
||||
qCopy := bn128.G2.Affine(p)
|
||||
res := AteG2Precomp{
|
||||
qCopy[0],
|
||||
@@ -235,11 +232,13 @@ func (bn128 Bn128) PreComputeG2(p [3][2]*big.Int) (AteG2Precomp, error) {
|
||||
|
||||
q1 := bn128.G2.Affine(bn128.G2MulByQ(qCopy))
|
||||
if !bn128.Fq2.Equal(q1[2], bn128.Fq2.One()) {
|
||||
return res, errors.New("q1[2] != Fq2.One")
|
||||
// return res, errors.New("q1[2] != Fq2.One")
|
||||
panic(errors.New("q1[2] != Fq2.One()"))
|
||||
}
|
||||
q2 := bn128.G2.Affine(bn128.G2MulByQ(q1))
|
||||
if !bn128.Fq2.Equal(q2[2], bn128.Fq2.One()) {
|
||||
return res, errors.New("q2[2] != Fq2.One")
|
||||
// return res, errors.New("q2[2] != Fq2.One")
|
||||
panic(errors.New("q2[2] != Fq2.One()"))
|
||||
}
|
||||
|
||||
if bn128.LoopCountNeg {
|
||||
@@ -253,7 +252,7 @@ func (bn128 Bn128) PreComputeG2(p [3][2]*big.Int) (AteG2Precomp, error) {
|
||||
c, r = bn128.MixedAdditionStep(q2, r)
|
||||
res.Coeffs = append(res.Coeffs, c)
|
||||
|
||||
return res, nil
|
||||
return res
|
||||
}
|
||||
|
||||
func (bn128 Bn128) DoublingStep(current [3][2]*big.Int) (EllCoeffs, [3][2]*big.Int) {
|
||||
|
||||
@@ -22,10 +22,10 @@ func TestBN128(t *testing.T) {
|
||||
g2b := bn128.G2.MulScalar(bn128.G2.G, bn128.Fq1.Copy(big40))
|
||||
|
||||
pre1a := bn128.PreComputeG1(g1a)
|
||||
pre2a, err := bn128.PreComputeG2(g2a)
|
||||
pre2a := bn128.PreComputeG2(g2a)
|
||||
assert.Nil(t, err)
|
||||
pre1b := bn128.PreComputeG1(g1b)
|
||||
pre2b, err := bn128.PreComputeG2(g2b)
|
||||
pre2b := bn128.PreComputeG2(g2b)
|
||||
assert.Nil(t, err)
|
||||
|
||||
r1 := bn128.MillerLoop(pre1a, pre2a)
|
||||
@@ -55,10 +55,8 @@ func TestBN128Pairing(t *testing.T) {
|
||||
g1b := bn128.G1.MulScalar(bn128.G1.G, big30)
|
||||
g2b := bn128.G2.MulScalar(bn128.G2.G, big25)
|
||||
|
||||
pA, err := bn128.Pairing(g1a, g2a)
|
||||
assert.Nil(t, err)
|
||||
pB, err := bn128.Pairing(g1b, g2b)
|
||||
assert.Nil(t, err)
|
||||
pA := bn128.Pairing(g1a, g2a)
|
||||
pB := bn128.Pairing(g1b, g2b)
|
||||
|
||||
assert.True(t, bn128.Fq12.Equal(pA, pB))
|
||||
|
||||
@@ -67,3 +65,24 @@ func TestBN128Pairing(t *testing.T) {
|
||||
// assert.Equal(t, pA[0][0][0].String(), "73680848340331011700282047627232219336104151861349893575958589557226556635706")
|
||||
// assert.Equal(t, bn128.Fq12.Affine(pA)[0][0][0].String(), "8016119724813186033542830391460394070015218389456422587891475873290878009957")
|
||||
}
|
||||
|
||||
func TestBN128Pairing2(t *testing.T) {
|
||||
// test idea from https://bplib.readthedocs.io/en/latest/ by George Danezis
|
||||
bn, err := NewBn128()
|
||||
assert.Nil(t, err)
|
||||
|
||||
gt := bn.Pairing(bn.G1.G, bn.G2.G)
|
||||
|
||||
gt6 := bn.Fq12.Exp(gt, big.NewInt(int64(6)))
|
||||
|
||||
// e(g1, g2)^6 == e(g1, 6*g2)
|
||||
assert.True(t, bn.Fq12.Equal(gt6, bn.Pairing(bn.G1.G, bn.G2.MulScalar(bn.G2.G, big.NewInt(int64(6))))))
|
||||
|
||||
// e(g1, g2)^6 == e(6* g1, g2)
|
||||
assert.True(t, bn.Fq12.Equal(gt6, bn.Pairing(bn.G1.MulScalar(bn.G1.G, big.NewInt(int64(6))), bn.G2.G)))
|
||||
// e(g1, g2)^6 == e(3*g1, 2*g2)
|
||||
assert.True(t, bn.Fq12.Equal(gt6, bn.Pairing(bn.G1.MulScalar(bn.G1.G, big.NewInt(int64(3))), bn.G2.MulScalar(bn.G2.G, big.NewInt(int64(2))))))
|
||||
// e(g1, g2)^6 == e(2*g1, 3*g2)
|
||||
assert.True(t, bn.Fq12.Equal(gt6, bn.Pairing(bn.G1.MulScalar(bn.G1.G, big.NewInt(int64(2))), bn.G2.MulScalar(bn.G2.G, big.NewInt(int64(3))))))
|
||||
|
||||
}
|
||||
|
||||
7
compiler/circuit.go
Normal file
7
compiler/circuit.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package compiler
|
||||
|
||||
type Circuit struct {
|
||||
NVars int
|
||||
NPublic int
|
||||
NSignals int
|
||||
}
|
||||
21
fields/fq.go
21
fields/fq.go
@@ -2,6 +2,7 @@ package fields
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
@@ -117,6 +118,26 @@ func (fq Fq) Exp(base *big.Int, e *big.Int) *big.Int {
|
||||
return res
|
||||
}
|
||||
|
||||
func (fq Fq) Rand() (*big.Int, error) {
|
||||
|
||||
// twoexp := new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(maxbits)), nil)
|
||||
// max := new(big.Int).Sub(twoexp, big.NewInt(1))
|
||||
|
||||
maxbits := fq.Q.BitLen()
|
||||
b := make([]byte, (maxbits/8)-1)
|
||||
// b := make([]byte, 3)
|
||||
// b := make([]byte, 3)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r := new(big.Int).SetBytes(b)
|
||||
rq := new(big.Int).Mod(r, fq.Q)
|
||||
|
||||
// return r over q, nil
|
||||
return rq, nil
|
||||
}
|
||||
|
||||
func (fq Fq) IsZero(a *big.Int) bool {
|
||||
return bytes.Equal(a.Bytes(), fq.Zero().Bytes())
|
||||
}
|
||||
|
||||
3
go.mod
3
go.mod
@@ -2,5 +2,8 @@ module github.com/arnaucube/go-snark
|
||||
|
||||
require (
|
||||
github.com/arnaucube/cryptofun v0.0.0-20181124004321-9b11ae8280bd
|
||||
github.com/fatih/color v1.7.0
|
||||
github.com/mattn/go-colorable v0.0.9 // indirect
|
||||
github.com/mattn/go-isatty v0.0.4 // indirect
|
||||
github.com/stretchr/testify v1.2.2
|
||||
)
|
||||
|
||||
6
go.sum
6
go.sum
@@ -2,6 +2,12 @@ github.com/arnaucube/cryptofun v0.0.0-20181124004321-9b11ae8280bd h1:NDpNBTFeHNE
|
||||
github.com/arnaucube/cryptofun v0.0.0-20181124004321-9b11ae8280bd/go.mod h1:PZE8kKpHPD1UMrS3mTfAMmEEinGtijSwjxLRqRcD64A=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
|
||||
@@ -95,7 +95,6 @@ func (pf PolynomialField) Sub(a, b []*big.Int) []*big.Int {
|
||||
func (pf PolynomialField) Eval(v []*big.Int, x *big.Int) *big.Int {
|
||||
r := big.NewInt(int64(0))
|
||||
for i := 0; i < len(v); i++ {
|
||||
// xi := FloatPow(x, i)
|
||||
xi := pf.F.Exp(x, big.NewInt(int64(i)))
|
||||
elem := pf.F.Mul(v[i], xi)
|
||||
r = pf.F.Add(r, elem)
|
||||
|
||||
200
snark.go
200
snark.go
@@ -1,11 +1,12 @@
|
||||
package snark
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/arnaucube/go-snark/bn128"
|
||||
"github.com/arnaucube/go-snark/compiler"
|
||||
"github.com/arnaucube/go-snark/fields"
|
||||
"github.com/arnaucube/go-snark/r1csqap"
|
||||
)
|
||||
@@ -36,9 +37,10 @@ type Setup struct {
|
||||
Cp [][3]*big.Int
|
||||
}
|
||||
Vk struct {
|
||||
A [3][2]*big.Int
|
||||
B [3]*big.Int
|
||||
C [3][2]*big.Int
|
||||
Vka [3][2]*big.Int
|
||||
Vkb [3]*big.Int
|
||||
Vkc [3][2]*big.Int
|
||||
A [][3]*big.Int
|
||||
G1Kbg [3]*big.Int // g1 * Kbeta * Kgamma
|
||||
G2Kbg [3][2]*big.Int // g2 * Kbeta * Kgamma
|
||||
G2Kg [3][2]*big.Int // g2 * Kgamma
|
||||
@@ -47,67 +49,66 @@ type Setup struct {
|
||||
}
|
||||
|
||||
type Proof struct {
|
||||
PiA [3]*big.Int
|
||||
PiAp [3]*big.Int
|
||||
PiB [3][2]*big.Int
|
||||
PiBp [3]*big.Int
|
||||
PiC [3]*big.Int
|
||||
PiCp [3]*big.Int
|
||||
PiH [3]*big.Int
|
||||
PiKp [3]*big.Int
|
||||
PiA [3]*big.Int
|
||||
PiAp [3]*big.Int
|
||||
PiB [3][2]*big.Int
|
||||
PiBp [3]*big.Int
|
||||
PiC [3]*big.Int
|
||||
PiCp [3]*big.Int
|
||||
PiH [3]*big.Int
|
||||
PiKp [3]*big.Int
|
||||
PublicSignals []*big.Int
|
||||
}
|
||||
|
||||
const bits = 512
|
||||
|
||||
func GenerateTrustedSetup(bn bn128.Bn128, pf r1csqap.PolynomialField, witnessLength int, alphas, betas, gammas [][]*big.Int, ax, bx, cx, hx, zx []*big.Int) (Setup, error) {
|
||||
func GenerateTrustedSetup(bn bn128.Bn128, fqR fields.Fq, pf r1csqap.PolynomialField, witnessLength int, circuit compiler.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 = rand.Prime(rand.Reader, bits)
|
||||
setup.Toxic.T, err = fqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
|
||||
// k for calculating pi' and Vk
|
||||
setup.Toxic.Ka, err = rand.Prime(rand.Reader, bits)
|
||||
setup.Toxic.Ka, err = fqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
setup.Toxic.Kb, err = rand.Prime(rand.Reader, bits)
|
||||
setup.Toxic.Kb, err = fqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
setup.Toxic.Kc, err = rand.Prime(rand.Reader, bits)
|
||||
setup.Toxic.Kc, err = fqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
|
||||
// generate Kβ (Kbeta) and Kγ (Kgamma)
|
||||
setup.Toxic.Kbeta, err = rand.Prime(rand.Reader, bits)
|
||||
setup.Toxic.Kbeta, err = fqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
setup.Toxic.Kgamma, err = rand.Prime(rand.Reader, bits)
|
||||
setup.Toxic.Kgamma, err = fqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
|
||||
// generate ρ (Rho): ρA, ρB, ρC
|
||||
setup.Toxic.RhoA, err = rand.Prime(rand.Reader, bits)
|
||||
setup.Toxic.RhoA, err = fqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
setup.Toxic.RhoB, err = rand.Prime(rand.Reader, bits)
|
||||
setup.Toxic.RhoB, err = fqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
setup.Toxic.RhoC = bn.Fq1.Mul(setup.Toxic.RhoA, setup.Toxic.RhoB)
|
||||
setup.Toxic.RhoC = 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 := bn.Fq1.Exp(setup.Toxic.T, big.NewInt(int64(i)))
|
||||
tPow := fqR.Exp(setup.Toxic.T, big.NewInt(int64(i)))
|
||||
tEncr1 := bn.G1.MulScalar(bn.G1.G, tPow)
|
||||
gt1 = append(gt1, tEncr1)
|
||||
tEncr2 := bn.G2.MulScalar(bn.G2.G, tPow)
|
||||
@@ -118,9 +119,9 @@ func GenerateTrustedSetup(bn bn128.Bn128, pf r1csqap.PolynomialField, witnessLen
|
||||
setup.G1T = gt1
|
||||
setup.G2T = gt2
|
||||
|
||||
setup.Vk.A = bn.G2.MulScalar(bn.G2.G, setup.Toxic.Ka)
|
||||
setup.Vk.B = bn.G1.MulScalar(bn.G1.G, setup.Toxic.Kb)
|
||||
setup.Vk.C = bn.G2.MulScalar(bn.G2.G, setup.Toxic.Kc)
|
||||
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)
|
||||
|
||||
/*
|
||||
Verification keys:
|
||||
@@ -128,16 +129,19 @@ func GenerateTrustedSetup(bn bn128.Bn128, pf r1csqap.PolynomialField, witnessLen
|
||||
- Vk_betagamma2: setup.G2Kbg = g2 * Kbeta*Kgamma
|
||||
- Vk_gamma: setup.G2Kg = g2 * Kgamma
|
||||
*/
|
||||
kbg := bn.Fq1.Mul(setup.Toxic.Kbeta, setup.Toxic.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)
|
||||
|
||||
for i := 0; i < witnessLength; i++ {
|
||||
// A[i] = g1 * ax[t]
|
||||
// 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)
|
||||
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)
|
||||
@@ -148,20 +152,27 @@ func GenerateTrustedSetup(bn bn128.Bn128, pf r1csqap.PolynomialField, witnessLen
|
||||
c := bn.G1.MulScalar(bn.G1.G, ct)
|
||||
setup.Pk.C = append(setup.Pk.C, c)
|
||||
|
||||
kt := bn.Fq1.Add(bn.Fq1.Add(at, bt), ct)
|
||||
k := bn.G1.MulScalar(bn.G1.G, kt)
|
||||
kt := fqR.Add(fqR.Add(at, bt), ct)
|
||||
k := bn.G1.Affine(bn.G1.MulScalar(bn.G1.G, kt))
|
||||
|
||||
ktest := bn.G1.Affine(bn.G1.Add(bn.G1.Add(a, bg1), c))
|
||||
if !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))
|
||||
setup.Pk.Kp = append(setup.Pk.Kp, bn.G1.MulScalar(k, setup.Toxic.Kbeta))
|
||||
k_ := bn.G1.MulScalar(bn.G1.G, kt)
|
||||
setup.Pk.Kp = append(setup.Pk.Kp, bn.G1.MulScalar(k_, setup.Toxic.Kbeta))
|
||||
}
|
||||
setup.Vk.Vkz = bn.G2.MulScalar(bn.G2.G, pf.Eval(zx, setup.Toxic.T))
|
||||
|
||||
return setup, nil
|
||||
}
|
||||
|
||||
func GenerateProofs(bn bn128.Bn128, f fields.Fq, setup Setup, hx []*big.Int, w []*big.Int) (Proof, error) {
|
||||
func GenerateProofs(bn bn128.Bn128, f fields.Fq, circuit compiler.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()}
|
||||
@@ -172,12 +183,12 @@ func GenerateProofs(bn bn128.Bn128, f fields.Fq, setup Setup, hx []*big.Int, w [
|
||||
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()}
|
||||
|
||||
for i := 0; i < len(w); 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]))
|
||||
}
|
||||
|
||||
for i := 0; i < len(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]))
|
||||
|
||||
@@ -186,122 +197,73 @@ func GenerateProofs(bn bn128.Bn128, f fields.Fq, setup Setup, hx []*big.Int, w [
|
||||
|
||||
proof.PiKp = bn.G1.Add(proof.PiKp, 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.PublicSignals = w[1 : circuit.NPublic+1]
|
||||
|
||||
return proof, nil
|
||||
}
|
||||
|
||||
func VerifyProof(bn bn128.Bn128, setup Setup, proof Proof) bool {
|
||||
func VerifyProof(bn bn128.Bn128, circuit compiler.Circuit, setup Setup, proof Proof) bool {
|
||||
|
||||
// e(piA, Va) == e(piA', g2)
|
||||
pairingPiaVa, err := bn.Pairing(proof.PiA, setup.Vk.A)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
pairingPiapG2, err := bn.Pairing(proof.PiAp, bn.G2.G)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
pairingPiaVa := bn.Pairing(proof.PiA, setup.Vk.Vka)
|
||||
pairingPiapG2 := bn.Pairing(proof.PiAp, bn.G2.G)
|
||||
if !bn.Fq12.Equal(pairingPiaVa, pairingPiapG2) {
|
||||
return false
|
||||
} else {
|
||||
fmt.Println("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, err := bn.Pairing(setup.Vk.B, proof.PiB)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
pairingPibpG2, err := bn.Pairing(proof.PiBp, bn.G2.G)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
pairingVbPib := bn.Pairing(setup.Vk.Vkb, proof.PiB)
|
||||
pairingPibpG2 := bn.Pairing(proof.PiBp, bn.G2.G)
|
||||
if !bn.Fq12.Equal(pairingVbPib, pairingPibpG2) {
|
||||
return false
|
||||
} else {
|
||||
fmt.Println("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, err := bn.Pairing(proof.PiC, setup.Vk.C)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
pairingPicpG2, err := bn.Pairing(proof.PiCp, bn.G2.G)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
pairingPicVc := bn.Pairing(proof.PiC, setup.Vk.Vkc)
|
||||
pairingPicpG2 := bn.Pairing(proof.PiCp, bn.G2.G)
|
||||
if !bn.Fq12.Equal(pairingPicVc, pairingPicpG2) {
|
||||
return false
|
||||
} else {
|
||||
fmt.Println("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]))
|
||||
}
|
||||
|
||||
// e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2)
|
||||
pairingPiaPib, err := bn.Pairing(proof.PiA, proof.PiB)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
pairingPihVkz, err := bn.Pairing(proof.PiH, setup.Vk.Vkz)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
pairingPicG2, err := bn.Pairing(proof.PiC, bn.G2.G)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
pairingR := bn.Fq12.Mul(pairingPihVkz, pairingPicG2)
|
||||
if !bn.Fq12.Equal(pairingPiaPib, pairingR) {
|
||||
fmt.Println("p4")
|
||||
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))) {
|
||||
return false
|
||||
} else {
|
||||
fmt.Println("QAP disibility checked")
|
||||
fmt.Println("✓ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked")
|
||||
}
|
||||
|
||||
// e(piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB)
|
||||
// e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB)
|
||||
// == e(piK, g2Kgamma)
|
||||
// piApiC := bn.G1.Add(proof.PiA, proof.PiC)
|
||||
// pairingPiACG2Kbg, err := bn.Pairing(piApiC, setup.Vk.G2Kbg)
|
||||
// if err != nil {
|
||||
// return false
|
||||
// }
|
||||
// pairingG1KbgPiB, err := bn.Pairing(setup.Vk.G1Kbg, proof.PiB)
|
||||
// if err != nil {
|
||||
// return false
|
||||
// }
|
||||
// pairingL := bn.Fq12.Mul(pairingPiACG2Kbg, pairingG1KbgPiB)
|
||||
// pairingR, err := bn.Pairing(proof.PiKp, setup.Vk.G2Kg)
|
||||
// if err != nil {
|
||||
// return false
|
||||
// }
|
||||
// if !bn.Fq12.Equal(pairingL, pairingR) {
|
||||
// fmt.Println("p5")
|
||||
// return false
|
||||
// }
|
||||
|
||||
//
|
||||
|
||||
// e(piA, piB) == e(piH, Vz) * e(piC, g2)
|
||||
// pairingPiaPib, err := bn.Pairing(proof.PiA, proof.PiB)
|
||||
// if err != nil {
|
||||
// return false
|
||||
// }
|
||||
// pairingPihVz, err := bn.Pairing(proof.PiH, setup.Vk.Vkz)
|
||||
// if err != nil {
|
||||
// return false
|
||||
// }
|
||||
// pairingPicG2, err := bn.Pairing(proof.PiC, bn.G2.G)
|
||||
// if err != nil {
|
||||
// return false
|
||||
// }
|
||||
// if !bn.Fq12.Equal(pairingPiaPib, bn.Fq12.Mul(pairingPihVz, pairingPicG2)) {
|
||||
// return false
|
||||
// }
|
||||
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) {
|
||||
return false
|
||||
} else {
|
||||
fmt.Println("✓ e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) == e(piK, g2Kgamma)")
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/arnaucube/go-snark/bn128"
|
||||
"github.com/arnaucube/go-snark/compiler"
|
||||
"github.com/arnaucube/go-snark/fields"
|
||||
"github.com/arnaucube/go-snark/r1csqap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -16,10 +17,10 @@ func TestZk(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
|
||||
// new Finite Field
|
||||
f := fields.NewFq(bn.R)
|
||||
fqR := fields.NewFq(bn.R)
|
||||
|
||||
// new Polynomial Field
|
||||
pf := r1csqap.NewPolynomialField(f)
|
||||
pf := r1csqap.NewPolynomialField(fqR)
|
||||
|
||||
b0 := big.NewInt(int64(0))
|
||||
b1 := big.NewInt(int64(1))
|
||||
@@ -49,7 +50,13 @@ func TestZk(t *testing.T) {
|
||||
}
|
||||
alphas, betas, gammas, zx := pf.R1CSToQAP(a, b, c)
|
||||
|
||||
// wittness = 1, 3, 35, 9, 27, 30
|
||||
w := []*big.Int{b1, b3, b35, b9, b27, b30}
|
||||
circuit := compiler.Circuit{
|
||||
NVars: 6,
|
||||
NPublic: 0,
|
||||
NSignals: len(w),
|
||||
}
|
||||
ax, bx, cx, px := pf.CombinePolynomials(w, alphas, betas, gammas)
|
||||
|
||||
hx := pf.DivisorPolinomial(px, zx)
|
||||
@@ -63,22 +70,18 @@ func TestZk(t *testing.T) {
|
||||
hz := pf.Mul(hx, zx)
|
||||
assert.Equal(t, abc, hz)
|
||||
|
||||
div, rem := pf.Div(px, zx)
|
||||
assert.Equal(t, hx, div)
|
||||
assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
|
||||
|
||||
// calculate trusted setup
|
||||
setup, err := GenerateTrustedSetup(bn, pf, len(w), alphas, betas, gammas, ax, bx, cx, hx, zx)
|
||||
setup, err := GenerateTrustedSetup(bn, fqR, pf, len(w), circuit, alphas, betas, gammas, zx)
|
||||
assert.Nil(t, err)
|
||||
fmt.Println("trusted setup:")
|
||||
fmt.Println(setup.G1T)
|
||||
fmt.Println(setup.G2T)
|
||||
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, f, setup, hx, w)
|
||||
proof, err := GenerateProofs(bn, fqR, circuit, setup, hx, w)
|
||||
assert.Nil(t, err)
|
||||
fmt.Println("proofs:")
|
||||
fmt.Println(proof.PiA)
|
||||
fmt.Println(proof.PiB)
|
||||
fmt.Println(proof.PiC)
|
||||
fmt.Println(proof.PiH)
|
||||
// fmt.Println(proof.Vz)
|
||||
|
||||
assert.True(t, VerifyProof(bn, setup, proof))
|
||||
assert.True(t, VerifyProof(bn, circuit, setup, proof))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user