mirror of
https://github.com/arnaucube/go-snark-study.git
synced 2026-02-02 17:26:41 +01:00
small update, fix trusted setup ops over Field R
This commit is contained in:
@@ -7,7 +7,7 @@ zkSNARK library implementation in Go
|
|||||||
- `Pinocchio: Nearly practical verifiable computation`, Bryan Parno, Craig Gentry, Jon Howell, Mariana Raykova https://eprint.iacr.org/2013/279.pdf
|
- `Pinocchio: Nearly practical verifiable computation`, Bryan Parno, Craig Gentry, Jon Howell, Mariana Raykova https://eprint.iacr.org/2013/279.pdf
|
||||||
|
|
||||||
## Caution
|
## Caution
|
||||||
Implementation from scratch in Go to understand the concepts. Do not use in production.
|
Implementation of the zkSNARK [Pinocchio protocol](https://eprint.iacr.org/2013/279.pdf) from scratch in Go to understand the concepts. Do not use in production.
|
||||||
|
|
||||||
Not finished, implementing this in my free time to understand it better, so I don't have much time.
|
Not finished, implementing this in my free time to understand it better, so I don't have much time.
|
||||||
|
|
||||||
@@ -15,17 +15,18 @@ Current implementation status:
|
|||||||
- [x] Finite Fields (1, 2, 6, 12) operations
|
- [x] Finite Fields (1, 2, 6, 12) operations
|
||||||
- [x] G1 and G2 curve operations
|
- [x] G1 and G2 curve operations
|
||||||
- [x] BN128 Pairing
|
- [x] BN128 Pairing
|
||||||
- [x] circuit code compiler
|
- [ ] circuit code compiler
|
||||||
- [ ] code to flat code (improve circuit compiler)
|
- [ ] code to flat code (improve circuit compiler)
|
||||||
- [x] flat code compiler
|
- [x] flat code compiler
|
||||||
|
- [ ] private & public inputs. fix circuit compiler
|
||||||
- [x] circuit to R1CS
|
- [x] circuit to R1CS
|
||||||
- [x] polynomial operations
|
- [x] polynomial operations
|
||||||
- [x] R1CS to QAP
|
- [x] R1CS to QAP
|
||||||
- [x] generate trusted setup
|
- [x] generate trusted setup
|
||||||
- [x] generate proofs
|
- [x] generate proofs
|
||||||
- [x] verify proofs with BN128 pairing
|
- [x] verify proofs with BN128 pairing
|
||||||
- [ ] fix 4th pairing proofs generation & verification: ê(Vkx+piA, piB) == ê(piH, Vkz) * ê(piC, g2)
|
- [ ] fix 4th pairing proofs generation & verification: ê(Vkx+piA, piB) == ê(piH, Vkz) * ê(piC, G2)
|
||||||
- [ ] WASM implementation to run on browsers
|
- [ ] move witness calculation outside the setup phase
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -189,24 +189,24 @@ func (pf PolynomialField) R1CSToQAP(a, b, c [][]*big.Int) ([][]*big.Int, [][]*bi
|
|||||||
|
|
||||||
// CombinePolynomials combine the given polynomials arrays into one, also returns the P(x)
|
// CombinePolynomials combine the given polynomials arrays into one, also returns the P(x)
|
||||||
func (pf PolynomialField) CombinePolynomials(r []*big.Int, ap, bp, cp [][]*big.Int) ([]*big.Int, []*big.Int, []*big.Int, []*big.Int) {
|
func (pf PolynomialField) CombinePolynomials(r []*big.Int, ap, bp, cp [][]*big.Int) ([]*big.Int, []*big.Int, []*big.Int, []*big.Int) {
|
||||||
var alpha []*big.Int
|
var ax []*big.Int
|
||||||
for i := 0; i < len(r); i++ {
|
for i := 0; i < len(r); i++ {
|
||||||
m := pf.Mul([]*big.Int{r[i]}, ap[i])
|
m := pf.Mul([]*big.Int{r[i]}, ap[i])
|
||||||
alpha = pf.Add(alpha, m)
|
ax = pf.Add(ax, m)
|
||||||
}
|
}
|
||||||
var beta []*big.Int
|
var bx []*big.Int
|
||||||
for i := 0; i < len(r); i++ {
|
for i := 0; i < len(r); i++ {
|
||||||
m := pf.Mul([]*big.Int{r[i]}, bp[i])
|
m := pf.Mul([]*big.Int{r[i]}, bp[i])
|
||||||
beta = pf.Add(beta, m)
|
bx = pf.Add(bx, m)
|
||||||
}
|
}
|
||||||
var gamma []*big.Int
|
var cx []*big.Int
|
||||||
for i := 0; i < len(r); i++ {
|
for i := 0; i < len(r); i++ {
|
||||||
m := pf.Mul([]*big.Int{r[i]}, cp[i])
|
m := pf.Mul([]*big.Int{r[i]}, cp[i])
|
||||||
gamma = pf.Add(gamma, m)
|
cx = pf.Add(cx, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
px := pf.Sub(pf.Mul(alpha, beta), gamma)
|
px := pf.Sub(pf.Mul(ax, bx), cx)
|
||||||
return alpha, beta, gamma, px
|
return ax, bx, cx, px
|
||||||
}
|
}
|
||||||
|
|
||||||
// DivisorPolynomial returns the divisor polynomial given two polynomials
|
// DivisorPolynomial returns the divisor polynomial given two polynomials
|
||||||
|
|||||||
29
snark.go
29
snark.go
@@ -99,13 +99,15 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
|||||||
for i := 0; i < len(alphas); i++ {
|
for i := 0; i < len(alphas); i++ {
|
||||||
for j := 0; j < len(alphas[i]); j++ {
|
for j := 0; j < len(alphas[i]); j++ {
|
||||||
if j <= circuit.NPublic {
|
if j <= circuit.NPublic {
|
||||||
if bytes.Equal(alphas[i][j].Bytes(), Utils.Bn.Fq1.Zero().Bytes()) {
|
if bytes.Equal(alphas[i][j].Bytes(), Utils.FqR.Zero().Bytes()) {
|
||||||
alphas[i][j] = Utils.Bn.Fq1.One()
|
alphas[i][j] = Utils.FqR.One()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println("alphas[1]", alphas[1])
|
||||||
|
|
||||||
// generate random t value
|
// generate random t value
|
||||||
setup.Toxic.T, err = Utils.FqR.Rand()
|
setup.Toxic.T, err = Utils.FqR.Rand()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -176,7 +178,8 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
|||||||
// for i := 0; i < circuit.NVars; i++ {
|
// for i := 0; i < circuit.NVars; i++ {
|
||||||
for i := 0; i < len(circuit.Signals); i++ {
|
for i := 0; i < len(circuit.Signals); i++ {
|
||||||
at := Utils.PF.Eval(alphas[i], setup.Toxic.T)
|
at := Utils.PF.Eval(alphas[i], setup.Toxic.T)
|
||||||
rhoAat := Utils.Bn.Fq1.Mul(setup.Toxic.RhoA, at)
|
// rhoAat := Utils.Bn.Fq1.Mul(setup.Toxic.RhoA, at)
|
||||||
|
rhoAat := Utils.FqR.Mul(setup.Toxic.RhoA, at)
|
||||||
a := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoAat)
|
a := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoAat)
|
||||||
setup.Pk.A = append(setup.Pk.A, a)
|
setup.Pk.A = append(setup.Pk.A, a)
|
||||||
if i <= circuit.NPublic {
|
if i <= circuit.NPublic {
|
||||||
@@ -184,13 +187,15 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
|||||||
}
|
}
|
||||||
|
|
||||||
bt := Utils.PF.Eval(betas[i], setup.Toxic.T)
|
bt := Utils.PF.Eval(betas[i], setup.Toxic.T)
|
||||||
rhoBbt := Utils.Bn.Fq1.Mul(setup.Toxic.RhoB, bt)
|
// rhoBbt := Utils.Bn.Fq1.Mul(setup.Toxic.RhoB, bt)
|
||||||
|
rhoBbt := Utils.FqR.Mul(setup.Toxic.RhoB, bt)
|
||||||
bg1 := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoBbt)
|
bg1 := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoBbt)
|
||||||
bg2 := Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, rhoBbt)
|
bg2 := Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, rhoBbt)
|
||||||
setup.Pk.B = append(setup.Pk.B, bg2)
|
setup.Pk.B = append(setup.Pk.B, bg2)
|
||||||
|
|
||||||
ct := Utils.PF.Eval(gammas[i], setup.Toxic.T)
|
ct := Utils.PF.Eval(gammas[i], setup.Toxic.T)
|
||||||
rhoCct := Utils.Bn.Fq1.Mul(setup.Toxic.RhoC, ct)
|
// rhoCct := Utils.Bn.Fq1.Mul(setup.Toxic.RhoC, ct)
|
||||||
|
rhoCct := Utils.FqR.Mul(setup.Toxic.RhoC, ct)
|
||||||
c := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoCct)
|
c := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoCct)
|
||||||
setup.Pk.C = append(setup.Pk.C, c)
|
setup.Pk.C = append(setup.Pk.C, c)
|
||||||
|
|
||||||
@@ -212,8 +217,7 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
|||||||
|
|
||||||
// z pol
|
// z pol
|
||||||
zpol := []*big.Int{big.NewInt(int64(1))}
|
zpol := []*big.Int{big.NewInt(int64(1))}
|
||||||
// for i := 1; i < len(circuit.Constraints); i++ {
|
for i := 1; i < len(circuit.Constraints); i++ {
|
||||||
for i := 1; i <= circuit.NPublic; i++ { // circuit.NPublic == d
|
|
||||||
zpol = Utils.PF.Mul(
|
zpol = Utils.PF.Mul(
|
||||||
zpol,
|
zpol,
|
||||||
[]*big.Int{
|
[]*big.Int{
|
||||||
@@ -222,10 +226,12 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
|||||||
big.NewInt(int64(1)),
|
big.NewInt(int64(1)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fmt.Println("zpol", zpol)
|
||||||
setup.Pk.Z = zpol
|
setup.Pk.Z = zpol
|
||||||
|
|
||||||
zt := Utils.PF.Eval(zpol, setup.Toxic.T)
|
zt := Utils.PF.Eval(zpol, setup.Toxic.T)
|
||||||
rhoCzt := Utils.Bn.Fq1.Mul(setup.Toxic.RhoC, zt)
|
// rhoCzt := Utils.Bn.Fq1.Mul(setup.Toxic.RhoC, zt)
|
||||||
|
rhoCzt := Utils.FqR.Mul(setup.Toxic.RhoC, zt)
|
||||||
setup.Vk.Vkz = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, rhoCzt)
|
setup.Vk.Vkz = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, rhoCzt)
|
||||||
|
|
||||||
// encrypt t values with curve generators
|
// encrypt t values with curve generators
|
||||||
@@ -234,7 +240,8 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
|||||||
tEncr := setup.Toxic.T
|
tEncr := setup.Toxic.T
|
||||||
for i := 1; i < len(zpol); i++ { //should be G1T = pkH = (tau**i * G1) from i=0 to d, where d is degree of pol Z(x)
|
for i := 1; i < len(zpol); i++ { //should be G1T = pkH = (tau**i * G1) from i=0 to d, where d is degree of pol Z(x)
|
||||||
gt1 = append(gt1, Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, tEncr))
|
gt1 = append(gt1, Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, tEncr))
|
||||||
tEncr = Utils.Bn.Fq1.Mul(tEncr, setup.Toxic.T)
|
// tEncr = Utils.Bn.Fq1.Mul(tEncr, setup.Toxic.T)
|
||||||
|
tEncr = Utils.FqR.Mul(tEncr, setup.Toxic.T)
|
||||||
}
|
}
|
||||||
fmt.Println("len(G1T)", len(gt1))
|
fmt.Println("len(G1T)", len(gt1))
|
||||||
setup.G1T = gt1
|
setup.G1T = gt1
|
||||||
@@ -272,8 +279,8 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, w []*big.Int,
|
|||||||
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) // maybe move this calculation to a previous step
|
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) // maybe move this calculation to a previous step
|
||||||
|
|
||||||
// piH = pkH,0 + sum ( hi * pk H,i ), where pkH = G1T, hi=hx
|
// piH = pkH,0 + sum ( hi * pk H,i ), where pkH = G1T, hi=hx
|
||||||
proof.PiH = Utils.Bn.G1.Add(proof.PiH, setup.G1T[0])
|
// proof.PiH = Utils.Bn.G1.Add(proof.PiH, setup.G1T[0])
|
||||||
for i := 1; i < len(setup.Pk.Z); i++ {
|
for i := 0; i < len(hx); i++ {
|
||||||
proof.PiH = Utils.Bn.G1.Add(proof.PiH, Utils.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]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,10 +50,11 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
|||||||
fmt.Println("c:", c)
|
fmt.Println("c:", c)
|
||||||
|
|
||||||
// R1CS to QAP
|
// R1CS to QAP
|
||||||
|
// TODO zxQAP is not used and is an old impl, bad calculated. TODO remove
|
||||||
alphas, betas, gammas, zxQAP := Utils.PF.R1CSToQAP(a, b, c)
|
alphas, betas, gammas, zxQAP := Utils.PF.R1CSToQAP(a, b, c)
|
||||||
fmt.Println("qap")
|
fmt.Println("qap")
|
||||||
fmt.Println("alphas", len(alphas))
|
fmt.Println("alphas", len(alphas))
|
||||||
fmt.Println("alphas", alphas[0])
|
fmt.Println("alphas[1]", alphas[1])
|
||||||
fmt.Println("betas", len(betas))
|
fmt.Println("betas", len(betas))
|
||||||
fmt.Println("gammas", len(gammas))
|
fmt.Println("gammas", len(gammas))
|
||||||
fmt.Println("zx length", len(zxQAP))
|
fmt.Println("zx length", len(zxQAP))
|
||||||
@@ -63,6 +64,10 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
|||||||
fmt.Println("bx length", len(bx))
|
fmt.Println("bx length", len(bx))
|
||||||
fmt.Println("cx length", len(cx))
|
fmt.Println("cx length", len(cx))
|
||||||
fmt.Println("px length", len(px))
|
fmt.Println("px length", len(px))
|
||||||
|
fmt.Println("px[last]", px[0])
|
||||||
|
px0 := Utils.PF.F.Add(px[0], big.NewInt(int64(88)))
|
||||||
|
fmt.Println(px0)
|
||||||
|
assert.Equal(t, px0.Bytes(), Utils.PF.F.Zero().Bytes())
|
||||||
|
|
||||||
hxQAP := Utils.PF.DivisorPolynomial(px, zxQAP)
|
hxQAP := Utils.PF.DivisorPolynomial(px, zxQAP)
|
||||||
fmt.Println("hx length", len(hxQAP))
|
fmt.Println("hx length", len(hxQAP))
|
||||||
@@ -92,15 +97,18 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
|||||||
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z)
|
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z)
|
||||||
fmt.Println("hx pk.z", hx)
|
fmt.Println("hx pk.z", hx)
|
||||||
// assert.Equal(t, hxQAP, hx)
|
// assert.Equal(t, hxQAP, hx)
|
||||||
|
|
||||||
assert.Equal(t, px, Utils.PF.Mul(hxQAP, zxQAP))
|
assert.Equal(t, px, Utils.PF.Mul(hxQAP, zxQAP))
|
||||||
|
// hx==px/zx so px==hx*zx
|
||||||
assert.Equal(t, px, Utils.PF.Mul(hx, setup.Pk.Z))
|
assert.Equal(t, px, Utils.PF.Mul(hx, setup.Pk.Z))
|
||||||
|
|
||||||
|
// check length of polynomials H(x) and Z(x)
|
||||||
assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1)
|
assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1)
|
||||||
assert.Equal(t, len(hxQAP), len(px)-len(zxQAP)+1)
|
assert.Equal(t, len(hxQAP), len(px)-len(zxQAP)+1)
|
||||||
|
|
||||||
// fmt.Println("pk.Z", len(setup.Pk.Z))
|
// fmt.Println("pk.Z", len(setup.Pk.Z))
|
||||||
// fmt.Println("zxQAP", len(zxQAP))
|
// fmt.Println("zxQAP", len(zxQAP))
|
||||||
|
|
||||||
// piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
|
|
||||||
proof, err := GenerateProofs(*circuit, setup, w, px)
|
proof, err := GenerateProofs(*circuit, setup, w, px)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user