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
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -15,17 +15,18 @@ Current implementation status:
|
||||
- [x] Finite Fields (1, 2, 6, 12) operations
|
||||
- [x] G1 and G2 curve operations
|
||||
- [x] BN128 Pairing
|
||||
- [x] circuit code compiler
|
||||
- [ ] circuit code compiler
|
||||
- [ ] code to flat code (improve circuit compiler)
|
||||
- [x] flat code compiler
|
||||
- [ ] private & public inputs. fix circuit compiler
|
||||
- [x] circuit to R1CS
|
||||
- [x] polynomial operations
|
||||
- [x] R1CS to QAP
|
||||
- [x] generate trusted setup
|
||||
- [x] generate proofs
|
||||
- [x] verify proofs with BN128 pairing
|
||||
- [ ] fix 4th pairing proofs generation & verification: ê(Vkx+piA, piB) == ê(piH, Vkz) * ê(piC, g2)
|
||||
- [ ] WASM implementation to run on browsers
|
||||
- [ ] fix 4th pairing proofs generation & verification: ê(Vkx+piA, piB) == ê(piH, Vkz) * ê(piC, G2)
|
||||
- [ ] move witness calculation outside the setup phase
|
||||
|
||||
|
||||
## 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)
|
||||
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++ {
|
||||
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++ {
|
||||
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++ {
|
||||
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)
|
||||
return alpha, beta, gamma, px
|
||||
px := pf.Sub(pf.Mul(ax, bx), cx)
|
||||
return ax, bx, cx, px
|
||||
}
|
||||
|
||||
// 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 j := 0; j < len(alphas[i]); j++ {
|
||||
if j <= circuit.NPublic {
|
||||
if bytes.Equal(alphas[i][j].Bytes(), Utils.Bn.Fq1.Zero().Bytes()) {
|
||||
alphas[i][j] = Utils.Bn.Fq1.One()
|
||||
if bytes.Equal(alphas[i][j].Bytes(), Utils.FqR.Zero().Bytes()) {
|
||||
alphas[i][j] = Utils.FqR.One()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("alphas[1]", alphas[1])
|
||||
|
||||
// generate random t value
|
||||
setup.Toxic.T, err = Utils.FqR.Rand()
|
||||
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 < len(circuit.Signals); i++ {
|
||||
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)
|
||||
setup.Pk.A = append(setup.Pk.A, a)
|
||||
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)
|
||||
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)
|
||||
bg2 := Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, rhoBbt)
|
||||
setup.Pk.B = append(setup.Pk.B, bg2)
|
||||
|
||||
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)
|
||||
setup.Pk.C = append(setup.Pk.C, c)
|
||||
|
||||
@@ -212,8 +217,7 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
||||
|
||||
// z pol
|
||||
zpol := []*big.Int{big.NewInt(int64(1))}
|
||||
// for i := 1; i < len(circuit.Constraints); i++ {
|
||||
for i := 1; i <= circuit.NPublic; i++ { // circuit.NPublic == d
|
||||
for i := 1; i < len(circuit.Constraints); i++ {
|
||||
zpol = Utils.PF.Mul(
|
||||
zpol,
|
||||
[]*big.Int{
|
||||
@@ -222,10 +226,12 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
||||
big.NewInt(int64(1)),
|
||||
})
|
||||
}
|
||||
fmt.Println("zpol", zpol)
|
||||
setup.Pk.Z = zpol
|
||||
|
||||
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)
|
||||
|
||||
// encrypt t values with curve generators
|
||||
@@ -234,7 +240,8 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
||||
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)
|
||||
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))
|
||||
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
|
||||
|
||||
// piH = pkH,0 + sum ( hi * pk H,i ), where pkH = G1T, hi=hx
|
||||
proof.PiH = Utils.Bn.G1.Add(proof.PiH, setup.G1T[0])
|
||||
for i := 1; i < len(setup.Pk.Z); i++ {
|
||||
// proof.PiH = Utils.Bn.G1.Add(proof.PiH, setup.G1T[0])
|
||||
for i := 0; i < len(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)
|
||||
|
||||
// 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)
|
||||
fmt.Println("qap")
|
||||
fmt.Println("alphas", len(alphas))
|
||||
fmt.Println("alphas", alphas[0])
|
||||
fmt.Println("alphas[1]", alphas[1])
|
||||
fmt.Println("betas", len(betas))
|
||||
fmt.Println("gammas", len(gammas))
|
||||
fmt.Println("zx length", len(zxQAP))
|
||||
@@ -63,6 +64,10 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
||||
fmt.Println("bx length", len(bx))
|
||||
fmt.Println("cx length", len(cx))
|
||||
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)
|
||||
fmt.Println("hx length", len(hxQAP))
|
||||
@@ -92,15 +97,18 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
||||
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z)
|
||||
fmt.Println("hx pk.z", hx)
|
||||
// assert.Equal(t, hxQAP, hx)
|
||||
|
||||
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))
|
||||
|
||||
// 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(hxQAP), len(px)-len(zxQAP)+1)
|
||||
|
||||
// fmt.Println("pk.Z", len(setup.Pk.Z))
|
||||
// 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)
|
||||
assert.Nil(t, err)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user