mirror of
https://github.com/arnaucube/go-snark-study.git
synced 2026-02-02 17:26:41 +01:00
fixing Z(x), VkIC, Vkz, piH calculations
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ cli/proofs.json
|
|||||||
cli/test.circuit
|
cli/test.circuit
|
||||||
cli/trustedsetup.json
|
cli/trustedsetup.json
|
||||||
tmp
|
tmp
|
||||||
|
tmpBackup
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Current implementation status:
|
|||||||
- [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
|
- [ ] fix 4th pairing proofs generation & verification: ê(Vkx+piA, piB) == ê(piH, Vkz) * ê(piC, g2)
|
||||||
- [ ] WASM implementation to run on browsers
|
- [ ] WASM implementation to run on browsers
|
||||||
|
|
||||||
|
|
||||||
@@ -36,6 +36,8 @@ Current implementation status:
|
|||||||
- [](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler) Circuit Compiler
|
- [](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler) Circuit Compiler
|
||||||
|
|
||||||
### Library usage
|
### Library usage
|
||||||
|
Warning: not finished.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```go
|
```go
|
||||||
// compile circuit and get the R1CS
|
// compile circuit and get the R1CS
|
||||||
|
|||||||
@@ -153,6 +153,7 @@ type Inputs struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CalculateWitness calculates the Witness of a Circuit based on the given inputs
|
// CalculateWitness calculates the Witness of a Circuit based on the given inputs
|
||||||
|
// witness = [ one, output, publicInputs, privateInputs, ...]
|
||||||
func (circ *Circuit) CalculateWitness(inputs []*big.Int) ([]*big.Int, error) {
|
func (circ *Circuit) CalculateWitness(inputs []*big.Int) ([]*big.Int, error) {
|
||||||
if len(inputs) != len(circ.Inputs) {
|
if len(inputs) != len(circ.Inputs) {
|
||||||
return []*big.Int{}, errors.New("given inputs != circuit.Inputs")
|
return []*big.Int{}, errors.New("given inputs != circuit.Inputs")
|
||||||
|
|||||||
@@ -175,10 +175,14 @@ func (pf PolynomialField) R1CSToQAP(a, b, c [][]*big.Int) ([][]*big.Int, [][]*bi
|
|||||||
gammas = append(gammas, pf.LagrangeInterpolation(cT[i]))
|
gammas = append(gammas, pf.LagrangeInterpolation(cT[i]))
|
||||||
}
|
}
|
||||||
z := []*big.Int{big.NewInt(int64(1))}
|
z := []*big.Int{big.NewInt(int64(1))}
|
||||||
for i := 1; i < len(aT[0])+1; i++ {
|
for i := 1; i < len(alphas)-1; i++ {
|
||||||
ineg := big.NewInt(int64(-i))
|
z = pf.Mul(
|
||||||
b1 := big.NewInt(int64(1))
|
z,
|
||||||
z = pf.Mul(z, []*big.Int{ineg, b1})
|
[]*big.Int{
|
||||||
|
pf.F.Neg(
|
||||||
|
big.NewInt(int64(i))),
|
||||||
|
big.NewInt(int64(1)),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return alphas, betas, gammas, z
|
return alphas, betas, gammas, z
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package r1csqap
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -31,9 +30,14 @@ func TestTranspose(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func neg(a *big.Int) *big.Int {
|
||||||
|
return new(big.Int).Neg(a)
|
||||||
|
}
|
||||||
|
|
||||||
func TestPol(t *testing.T) {
|
func TestPol(t *testing.T) {
|
||||||
b0 := big.NewInt(int64(0))
|
b0 := big.NewInt(int64(0))
|
||||||
b1 := big.NewInt(int64(1))
|
b1 := big.NewInt(int64(1))
|
||||||
|
b2 := big.NewInt(int64(2))
|
||||||
b3 := big.NewInt(int64(3))
|
b3 := big.NewInt(int64(3))
|
||||||
b4 := big.NewInt(int64(4))
|
b4 := big.NewInt(int64(4))
|
||||||
b5 := big.NewInt(int64(5))
|
b5 := big.NewInt(int64(5))
|
||||||
@@ -55,6 +59,17 @@ func TestPol(t *testing.T) {
|
|||||||
o := pf.Mul(a, b)
|
o := pf.Mul(a, b)
|
||||||
assert.Equal(t, o, []*big.Int{b3, b0, b16, b0, b5})
|
assert.Equal(t, o, []*big.Int{b3, b0, b16, b0, b5})
|
||||||
|
|
||||||
|
// polynomial division
|
||||||
|
quo, rem := pf.Div(a, b)
|
||||||
|
assert.Equal(t, quo[0].Int64(), int64(5))
|
||||||
|
assert.Equal(t, new(big.Int).Sub(rem[0], r).Int64(), int64(-14)) // check the rem result without modulo
|
||||||
|
|
||||||
|
c := []*big.Int{neg(b4), b0, neg(b2), b1}
|
||||||
|
d := []*big.Int{neg(b3), b1}
|
||||||
|
quo2, rem2 := pf.Div(c, d)
|
||||||
|
assert.Equal(t, quo2, []*big.Int{b3, b1, b1})
|
||||||
|
assert.Equal(t, rem2[0].Int64(), int64(5))
|
||||||
|
|
||||||
// polynomial addition
|
// polynomial addition
|
||||||
o = pf.Add(a, b)
|
o = pf.Add(a, b)
|
||||||
assert.Equal(t, o, []*big.Int{b4, b0, b6})
|
assert.Equal(t, o, []*big.Int{b4, b0, b6})
|
||||||
@@ -67,8 +82,8 @@ func TestPol(t *testing.T) {
|
|||||||
assert.True(t, bytes.Equal(b0.Bytes(), o[1].Bytes()))
|
assert.True(t, bytes.Equal(b0.Bytes(), o[1].Bytes()))
|
||||||
assert.True(t, bytes.Equal(b0.Bytes(), o[2].Bytes()))
|
assert.True(t, bytes.Equal(b0.Bytes(), o[2].Bytes()))
|
||||||
|
|
||||||
c := []*big.Int{b5, b6, b1}
|
c = []*big.Int{b5, b6, b1}
|
||||||
d := []*big.Int{b1, b3}
|
d = []*big.Int{b1, b3}
|
||||||
o = pf.Sub(c, d)
|
o = pf.Sub(c, d)
|
||||||
assert.Equal(t, o, []*big.Int{b4, b3, b1})
|
assert.Equal(t, o, []*big.Int{b4, b3, b1})
|
||||||
|
|
||||||
@@ -133,21 +148,21 @@ func TestR1CSToQAP(t *testing.T) {
|
|||||||
[]*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 := pf.R1CSToQAP(a, b, c)
|
||||||
fmt.Println(alphas)
|
// fmt.Println(alphas)
|
||||||
fmt.Println(betas)
|
// fmt.Println(betas)
|
||||||
fmt.Println(gammas)
|
// fmt.Println(gammas)
|
||||||
fmt.Print("Z(x): ")
|
// fmt.Print("Z(x): ")
|
||||||
fmt.Println(zx)
|
// fmt.Println(zx)
|
||||||
|
|
||||||
w := []*big.Int{b1, b3, b35, b9, b27, b30}
|
w := []*big.Int{b1, b3, b35, b9, b27, b30}
|
||||||
ax, bx, cx, px := pf.CombinePolynomials(w, alphas, betas, gammas)
|
ax, bx, cx, px := pf.CombinePolynomials(w, alphas, betas, gammas)
|
||||||
fmt.Println(ax)
|
// fmt.Println(ax)
|
||||||
fmt.Println(bx)
|
// fmt.Println(bx)
|
||||||
fmt.Println(cx)
|
// fmt.Println(cx)
|
||||||
fmt.Println(px)
|
// fmt.Println(px)
|
||||||
|
|
||||||
hx := pf.DivisorPolynomial(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
|
||||||
assert.Equal(t, px, pf.Mul(hx, zx))
|
assert.Equal(t, px, pf.Mul(hx, zx))
|
||||||
|
|||||||
69
snark.go
69
snark.go
@@ -27,7 +27,7 @@ type Setup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// public
|
// public
|
||||||
G1T [][3]*big.Int // t encrypted in G1 curve
|
G1T [][3]*big.Int // t encrypted in G1 curve, G1T == Pk.H
|
||||||
G2T [][3][2]*big.Int // t encrypted in G2 curve
|
G2T [][3][2]*big.Int // t encrypted in G2 curve
|
||||||
Pk struct { // Proving Key pk:=(pkA, pkB, pkC, pkH)
|
Pk struct { // Proving Key pk:=(pkA, pkB, pkC, pkH)
|
||||||
A [][3]*big.Int
|
A [][3]*big.Int
|
||||||
@@ -37,6 +37,7 @@ type Setup struct {
|
|||||||
Ap [][3]*big.Int
|
Ap [][3]*big.Int
|
||||||
Bp [][3]*big.Int
|
Bp [][3]*big.Int
|
||||||
Cp [][3]*big.Int
|
Cp [][3]*big.Int
|
||||||
|
Z []*big.Int
|
||||||
}
|
}
|
||||||
Vk struct {
|
Vk struct {
|
||||||
Vka [3][2]*big.Int
|
Vka [3][2]*big.Int
|
||||||
@@ -90,7 +91,7 @@ func prepareUtils() utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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(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) (Setup, error) {
|
||||||
var setup Setup
|
var setup Setup
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -146,15 +147,7 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
|||||||
}
|
}
|
||||||
setup.Toxic.RhoC = Utils.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
|
// calculated more down
|
||||||
var gt1 [][3]*big.Int
|
|
||||||
var gt2 [][3][2]*big.Int
|
|
||||||
gt1 = append(gt1, Utils.Bn.G1.G)
|
|
||||||
tEncr := setup.Toxic.T
|
|
||||||
for i := 1; i < witnessLength; i++ {
|
|
||||||
gt1 = append(gt1, Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, tEncr))
|
|
||||||
tEncr = Utils.Bn.Fq1.Mul(tEncr, setup.Toxic.T)
|
|
||||||
}
|
|
||||||
// for i := 0; i < witnessLength; i++ {
|
// for i := 0; i < witnessLength; i++ {
|
||||||
// tPow := Utils.FqR.Exp(setup.Toxic.T, big.NewInt(int64(i)))
|
// tPow := Utils.FqR.Exp(setup.Toxic.T, big.NewInt(int64(i)))
|
||||||
// tEncr1 := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, tPow)
|
// tEncr1 := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, tPow)
|
||||||
@@ -164,8 +157,6 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
|||||||
// }
|
// }
|
||||||
// gt1: g1, g1*t, g1*t^2, g1*t^3, ...
|
// gt1: g1, g1*t, g1*t^2, g1*t^3, ...
|
||||||
// gt2: g2, g2*t, g2*t^2, ...
|
// gt2: g2, g2*t, g2*t^2, ...
|
||||||
setup.G1T = gt1
|
|
||||||
setup.G2T = gt2
|
|
||||||
|
|
||||||
setup.Vk.Vka = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Ka)
|
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.Vkb = Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, setup.Toxic.Kb)
|
||||||
@@ -182,7 +173,8 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
|||||||
setup.Vk.G2Kbg = Utils.Bn.G2.MulScalar(Utils.Bn.G2.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)
|
setup.Vk.G2Kg = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kgamma)
|
||||||
|
|
||||||
for i := 0; i < circuit.NVars; i++ {
|
// for i := 0; i < circuit.NVars; 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)
|
||||||
a := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoAat)
|
a := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, rhoAat)
|
||||||
@@ -217,15 +209,41 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
|
|||||||
k_ := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, kt)
|
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.Pk.Kp = append(setup.Pk.Kp, Utils.Bn.G1.MulScalar(k_, setup.Toxic.Kbeta))
|
||||||
}
|
}
|
||||||
zt := Utils.PF.Eval(zx, setup.Toxic.T)
|
|
||||||
|
// 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
|
||||||
|
zpol = Utils.PF.Mul(
|
||||||
|
zpol,
|
||||||
|
[]*big.Int{
|
||||||
|
Utils.FqR.Neg( // neg over R
|
||||||
|
big.NewInt(int64(i))),
|
||||||
|
big.NewInt(int64(1)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
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)
|
||||||
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
|
||||||
|
var gt1 [][3]*big.Int
|
||||||
|
gt1 = append(gt1, Utils.Bn.G1.G) // the first is t**0 * G1 = 1 * G1 = G1
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
fmt.Println("len(G1T)", len(gt1))
|
||||||
|
setup.G1T = gt1
|
||||||
|
|
||||||
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(circuit circuitcompiler.Circuit, setup Setup, hx []*big.Int, w []*big.Int) (Proof, error) {
|
func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, w []*big.Int, px []*big.Int) (Proof, error) {
|
||||||
var proof Proof
|
var proof Proof
|
||||||
proof.PiA = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.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.PiAp = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
|
||||||
@@ -251,7 +269,11 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, hx []*big.Int,
|
|||||||
proof.PiKp = Utils.Bn.G1.Add(proof.PiKp, Utils.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++ {
|
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, 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]))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,14 +281,14 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, hx []*big.Int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VerifyProof verifies over the BN128 the Pairings of the Proof
|
// VerifyProof verifies over the BN128 the Pairings of the Proof
|
||||||
func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publicSignals []*big.Int, printVer bool) bool {
|
func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publicSignals []*big.Int, debug bool) bool {
|
||||||
// e(piA, Va) == e(piA', g2)
|
// e(piA, Va) == e(piA', g2)
|
||||||
pairingPiaVa := Utils.Bn.Pairing(proof.PiA, setup.Vk.Vka)
|
pairingPiaVa := Utils.Bn.Pairing(proof.PiA, setup.Vk.Vka)
|
||||||
pairingPiapG2 := Utils.Bn.Pairing(proof.PiAp, Utils.Bn.G2.G)
|
pairingPiapG2 := Utils.Bn.Pairing(proof.PiAp, Utils.Bn.G2.G)
|
||||||
if !Utils.Bn.Fq12.Equal(pairingPiaVa, pairingPiapG2) {
|
if !Utils.Bn.Fq12.Equal(pairingPiaVa, pairingPiapG2) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if printVer {
|
if debug {
|
||||||
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +298,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
|
|||||||
if !Utils.Bn.Fq12.Equal(pairingVbPib, pairingPibpG2) {
|
if !Utils.Bn.Fq12.Equal(pairingVbPib, pairingPibpG2) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if printVer {
|
if debug {
|
||||||
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,13 +308,14 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
|
|||||||
if !Utils.Bn.Fq12.Equal(pairingPicVc, pairingPicpG2) {
|
if !Utils.Bn.Fq12.Equal(pairingPicVc, pairingPicpG2) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if printVer {
|
if debug {
|
||||||
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.IC[0]
|
vkxpia := setup.Vk.IC[0]
|
||||||
for i := 0; i < len(publicSignals); i++ {
|
for i := 0; i < len(publicSignals); i++ {
|
||||||
|
fmt.Println("pub sig", publicSignals[i])
|
||||||
vkxpia = Utils.Bn.G1.Add(vkxpia, Utils.Bn.G1.MulScalar(setup.Vk.IC[i+1], publicSignals[i]))
|
vkxpia = Utils.Bn.G1.Add(vkxpia, Utils.Bn.G1.MulScalar(setup.Vk.IC[i+1], publicSignals[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +327,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
|
|||||||
Utils.Bn.Pairing(proof.PiC, Utils.Bn.G2.G))) {
|
Utils.Bn.Pairing(proof.PiC, Utils.Bn.G2.G))) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if printVer {
|
if debug {
|
||||||
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,7 +341,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
|
|||||||
if !Utils.Bn.Fq12.Equal(pairingL, pairingR) {
|
if !Utils.Bn.Fq12.Equal(pairingL, pairingR) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if printVer {
|
if debug {
|
||||||
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)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
195
snark_test.go
195
snark_test.go
@@ -13,6 +13,111 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestZkFromFlatCircuitCode(t *testing.T) {
|
||||||
|
|
||||||
|
// compile circuit and get the R1CS
|
||||||
|
flatCode := `
|
||||||
|
func test(x):
|
||||||
|
aux = x*x
|
||||||
|
y = aux*x
|
||||||
|
z = x + y
|
||||||
|
out = z + 5
|
||||||
|
`
|
||||||
|
fmt.Print("\nflat code of the circuit:")
|
||||||
|
fmt.Println(flatCode)
|
||||||
|
|
||||||
|
// parse the code
|
||||||
|
parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
|
||||||
|
circuit, err := parser.Parse()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
fmt.Println("\ncircuit data:", circuit)
|
||||||
|
circuitJson, _ := json.Marshal(circuit)
|
||||||
|
fmt.Println("circuit:", string(circuitJson))
|
||||||
|
|
||||||
|
b3 := big.NewInt(int64(3))
|
||||||
|
privateInputs := []*big.Int{b3}
|
||||||
|
// wittness
|
||||||
|
w, err := circuit.CalculateWitness(privateInputs)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
fmt.Println("\nwitness", w)
|
||||||
|
|
||||||
|
// flat code to R1CS
|
||||||
|
fmt.Println("\ngenerating R1CS from flat code")
|
||||||
|
a, b, c := circuit.GenerateR1CS()
|
||||||
|
fmt.Println("\nR1CS:")
|
||||||
|
fmt.Println("a:", a)
|
||||||
|
fmt.Println("b:", b)
|
||||||
|
fmt.Println("c:", c)
|
||||||
|
|
||||||
|
// R1CS to QAP
|
||||||
|
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("betas", len(betas))
|
||||||
|
fmt.Println("gammas", len(gammas))
|
||||||
|
fmt.Println("zx length", len(zxQAP))
|
||||||
|
|
||||||
|
ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||||
|
fmt.Println("ax length", len(ax))
|
||||||
|
fmt.Println("bx length", len(bx))
|
||||||
|
fmt.Println("cx length", len(cx))
|
||||||
|
fmt.Println("px length", len(px))
|
||||||
|
|
||||||
|
hxQAP := Utils.PF.DivisorPolynomial(px, zxQAP)
|
||||||
|
fmt.Println("hx length", len(hxQAP))
|
||||||
|
|
||||||
|
// hx==px/zx so px==hx*zx
|
||||||
|
assert.Equal(t, px, Utils.PF.Mul(hxQAP, zxQAP))
|
||||||
|
|
||||||
|
// p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
|
||||||
|
abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
|
||||||
|
assert.Equal(t, abc, px)
|
||||||
|
hzQAP := Utils.PF.Mul(hxQAP, zxQAP)
|
||||||
|
assert.Equal(t, abc, hzQAP)
|
||||||
|
|
||||||
|
div, rem := Utils.PF.Div(px, zxQAP)
|
||||||
|
assert.Equal(t, hxQAP, div)
|
||||||
|
assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
|
||||||
|
|
||||||
|
// calculate trusted setup
|
||||||
|
setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
fmt.Println("\nt:", setup.Toxic.T)
|
||||||
|
|
||||||
|
// zx and setup.Pk.Z should be the same (currently not, the correct one is the calculation used inside GenerateTrustedSetup function), the calculation is repeated. TODO avoid repeating calculation
|
||||||
|
// assert.Equal(t, zxQAP, setup.Pk.Z)
|
||||||
|
|
||||||
|
fmt.Println("hx pk.z", hxQAP)
|
||||||
|
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))
|
||||||
|
assert.Equal(t, px, Utils.PF.Mul(hx, setup.Pk.Z))
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
// fmt.Println("\n proofs:")
|
||||||
|
// fmt.Println(proof)
|
||||||
|
|
||||||
|
// fmt.Println("public signals:", proof.PublicSignals)
|
||||||
|
fmt.Println("\nwitness", w)
|
||||||
|
// b1 := big.NewInt(int64(1))
|
||||||
|
b35 := big.NewInt(int64(35))
|
||||||
|
// publicSignals := []*big.Int{b1, b35}
|
||||||
|
publicSignals := []*big.Int{b35}
|
||||||
|
before := time.Now()
|
||||||
|
assert.True(t, VerifyProof(*circuit, setup, proof, publicSignals, true))
|
||||||
|
fmt.Println("verify proof time elapsed:", time.Since(before))
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func TestZkMultiplication(t *testing.T) {
|
func TestZkMultiplication(t *testing.T) {
|
||||||
|
|
||||||
@@ -82,96 +187,6 @@ func TestZkMultiplication(t *testing.T) {
|
|||||||
assert.True(t, VerifyProof(*circuit, setup, proof, publicSignals, true))
|
assert.True(t, VerifyProof(*circuit, setup, proof, publicSignals, true))
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func TestZkFromFlatCircuitCode(t *testing.T) {
|
|
||||||
|
|
||||||
// compile circuit and get the R1CS
|
|
||||||
flatCode := `
|
|
||||||
func test(x):
|
|
||||||
aux = x*x
|
|
||||||
y = aux*x
|
|
||||||
z = x + y
|
|
||||||
out = z + 5
|
|
||||||
`
|
|
||||||
fmt.Print("\nflat code of the circuit:")
|
|
||||||
fmt.Println(flatCode)
|
|
||||||
|
|
||||||
// parse the code
|
|
||||||
parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
|
|
||||||
circuit, err := parser.Parse()
|
|
||||||
assert.Nil(t, err)
|
|
||||||
fmt.Println("\ncircuit data:", circuit)
|
|
||||||
circuitJson, _ := json.Marshal(circuit)
|
|
||||||
fmt.Println("circuit:", string(circuitJson))
|
|
||||||
|
|
||||||
b3 := big.NewInt(int64(3))
|
|
||||||
privateInputs := []*big.Int{b3}
|
|
||||||
// wittness
|
|
||||||
w, err := circuit.CalculateWitness(privateInputs)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
fmt.Println("\nwitness", w)
|
|
||||||
|
|
||||||
// flat code to R1CS
|
|
||||||
fmt.Println("\ngenerating R1CS from flat code")
|
|
||||||
a, b, c := circuit.GenerateR1CS()
|
|
||||||
fmt.Println("\nR1CS:")
|
|
||||||
fmt.Println("a:", a)
|
|
||||||
fmt.Println("b:", b)
|
|
||||||
fmt.Println("c:", c)
|
|
||||||
|
|
||||||
// R1CS to QAP
|
|
||||||
alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
|
|
||||||
fmt.Println("qap")
|
|
||||||
fmt.Println("alphas", alphas)
|
|
||||||
fmt.Println("betas", betas)
|
|
||||||
fmt.Println("gammas", gammas)
|
|
||||||
fmt.Println("zx", zx)
|
|
||||||
|
|
||||||
ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
|
||||||
fmt.Println("ax", ax)
|
|
||||||
// fmt.Println("bx", bx)
|
|
||||||
// fmt.Println("cx", cx)
|
|
||||||
// fmt.Println("px", px)
|
|
||||||
|
|
||||||
hx := Utils.PF.DivisorPolynomial(px, zx)
|
|
||||||
|
|
||||||
// hx==px/zx so px==hx*zx
|
|
||||||
assert.Equal(t, px, Utils.PF.Mul(hx, zx))
|
|
||||||
|
|
||||||
// p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
|
|
||||||
abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
|
|
||||||
assert.Equal(t, abc, px)
|
|
||||||
hz := Utils.PF.Mul(hx, zx)
|
|
||||||
assert.Equal(t, abc, hz)
|
|
||||||
|
|
||||||
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(len(w), *circuit, alphas, betas, gammas, zx)
|
|
||||||
// setup, err := GenerateTrustedSetup(len(w), *circuit, ax, bx, cx, 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(*circuit, setup, hx, w)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
fmt.Println("IC", setup.Vk.IC)
|
|
||||||
|
|
||||||
// fmt.Println("\n proofs:")
|
|
||||||
// fmt.Println(proof)
|
|
||||||
|
|
||||||
// fmt.Println("public signals:", proof.PublicSignals)
|
|
||||||
fmt.Println("\nwitness", w)
|
|
||||||
b35 := big.NewInt(int64(35))
|
|
||||||
publicSignals := []*big.Int{b35}
|
|
||||||
fmt.Println("public signals:", publicSignals)
|
|
||||||
before := time.Now()
|
|
||||||
assert.True(t, VerifyProof(*circuit, setup, proof, publicSignals, true))
|
|
||||||
fmt.Println("verify proof time elapsed:", time.Since(before))
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func TestZkFromHardcodedR1CS(t *testing.T) {
|
func TestZkFromHardcodedR1CS(t *testing.T) {
|
||||||
b0 := big.NewInt(int64(0))
|
b0 := big.NewInt(int64(0))
|
||||||
|
|||||||
Reference in New Issue
Block a user