Browse Source

split trustedsetup in Pk & Vk for proof generation & verification smaller inputs

pull/14/head
arnaucube 5 years ago
parent
commit
469eabd451
8 changed files with 136 additions and 137 deletions
  1. +6
    -7
      cli/main.go
  2. +52
    -49
      groth16/groth16.go
  3. +3
    -3
      groth16/groth16_test.go
  4. +47
    -44
      snark.go
  5. +12
    -12
      snark_test.go
  6. +4
    -4
      wasm/go-snark-wasm-wrapper.go
  7. BIN
      wasm/go-snark.wasm
  8. +12
    -18
      wasm/utils/utils.go

+ 6
- 7
cli/main.go

@ -274,8 +274,7 @@ func TrustedSetup(context *cli.Context) error {
var tsetup snark.Setup var tsetup snark.Setup
tsetup.Pk = setup.Pk tsetup.Pk = setup.Pk
tsetup.Vk = setup.Vk tsetup.Vk = setup.Vk
tsetup.G1T = setup.G1T
tsetup.G2T = setup.G2T
tsetup.Pk.G1T = setup.Pk.G1T
// store setup to json // store setup to json
jsonData, err := json.Marshal(tsetup) jsonData, err := json.Marshal(tsetup)
@ -344,10 +343,10 @@ func GenerateProofs(context *cli.Context) error {
hx := snark.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z) hx := snark.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z)
fmt.Println(circuit) fmt.Println(circuit)
fmt.Println(trustedsetup.G1T)
fmt.Println(trustedsetup.Pk.G1T)
fmt.Println(hx) fmt.Println(hx)
fmt.Println(w) fmt.Println(w)
proof, err := snark.GenerateProofs(circuit, trustedsetup, w, px)
proof, err := snark.GenerateProofs(circuit, trustedsetup.Pk, w, px)
panicErr(err) panicErr(err)
fmt.Println("\n proofs:") fmt.Println("\n proofs:")
@ -388,7 +387,7 @@ func VerifyProofs(context *cli.Context) error {
err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals) err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
panicErr(err) panicErr(err)
verified := snark.VerifyProof(trustedsetup, proof, publicSignals, true)
verified := snark.VerifyProof(trustedsetup.Vk, proof, publicSignals, true)
if !verified { if !verified {
fmt.Println("ERROR: proofs not verified") fmt.Println("ERROR: proofs not verified")
} else { } else {
@ -499,7 +498,7 @@ func Groth16GenerateProofs(context *cli.Context) error {
fmt.Println(trustedsetup.Pk.PowersTauDelta) fmt.Println(trustedsetup.Pk.PowersTauDelta)
fmt.Println(hx) fmt.Println(hx)
fmt.Println(w) fmt.Println(w)
proof, err := groth16.GenerateProofs(circuit, trustedsetup, w, px)
proof, err := groth16.GenerateProofs(circuit, trustedsetup.Pk, w, px)
panicErr(err) panicErr(err)
fmt.Println("\n proofs:") fmt.Println("\n proofs:")
@ -540,7 +539,7 @@ func Groth16VerifyProofs(context *cli.Context) error {
err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals) err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
panicErr(err) panicErr(err)
verified := groth16.VerifyProof(trustedsetup, proof, publicSignals, true)
verified := groth16.VerifyProof(trustedsetup.Vk, proof, publicSignals, true)
if !verified { if !verified {
fmt.Println("ERROR: proofs not verified") fmt.Println("ERROR: proofs not verified")
} else { } else {

+ 52
- 49
groth16/groth16.go

@ -12,6 +12,36 @@ import (
"github.com/arnaucube/go-snark/r1csqap" "github.com/arnaucube/go-snark/r1csqap"
) )
type Pk struct { // Proving Key
BACDelta [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m
Z []*big.Int
G1 struct {
Alpha [3]*big.Int
Beta [3]*big.Int
Delta [3]*big.Int
At [][3]*big.Int // {a(τ)} from 0 to m
BACGamma [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to m
}
G2 struct {
Beta [3][2]*big.Int
Gamma [3][2]*big.Int
Delta [3][2]*big.Int
BACGamma [][3][2]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to m
}
PowersTauDelta [][3]*big.Int // powers of τ encrypted in G1 curve, divided by δ
}
type Vk struct {
IC [][3]*big.Int
G1 struct {
Alpha [3]*big.Int
}
G2 struct {
Beta [3][2]*big.Int
Gamma [3][2]*big.Int
Delta [3][2]*big.Int
}
}
// Setup is the data structure holding the Trusted Setup data. The Setup.Toxic sub struct must be destroyed after the GenerateTrustedSetup function is completed // Setup is the data structure holding the Trusted Setup data. The Setup.Toxic sub struct must be destroyed after the GenerateTrustedSetup function is completed
type Setup struct { type Setup struct {
Toxic struct { Toxic struct {
@ -23,35 +53,8 @@ type Setup struct {
} }
// public // public
Pk struct { // Proving Key
BACDelta [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m
Z []*big.Int
G1 struct {
Alpha [3]*big.Int
Beta [3]*big.Int
Delta [3]*big.Int
At [][3]*big.Int // {a(τ)} from 0 to m
BACGamma [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to m
}
G2 struct {
Beta [3][2]*big.Int
Gamma [3][2]*big.Int
Delta [3][2]*big.Int
BACGamma [][3][2]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to m
}
PowersTauDelta [][3]*big.Int // powers of τ encrypted in G1 curve, divided by δ
}
Vk struct {
IC [][3]*big.Int
G1 struct {
Alpha [3]*big.Int
}
G2 struct {
Beta [3][2]*big.Int
Gamma [3][2]*big.Int
Delta [3][2]*big.Int
}
}
Pk Pk
Vk Vk
} }
// Proof contains the parameters to proof the zkSNARK // Proof contains the parameters to proof the zkSNARK
@ -219,7 +222,7 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
} }
// 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, w []*big.Int, px []*big.Int) (Proof, error) {
func GenerateProofs(circuit circuitcompiler.Circuit, pk Pk, 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.PiB = Utils.Bn.Fq6.Zero() proof.PiB = Utils.Bn.Fq6.Zero()
@ -238,57 +241,57 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, w []*big.Int,
piBG1 := [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()} piBG1 := [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
for i := 0; i < circuit.NVars; i++ { for i := 0; i < circuit.NVars; i++ {
proof.PiA = Utils.Bn.G1.Add(proof.PiA, Utils.Bn.G1.MulScalar(setup.Pk.G1.At[i], w[i]))
piBG1 = Utils.Bn.G1.Add(piBG1, Utils.Bn.G1.MulScalar(setup.Pk.G1.BACGamma[i], w[i]))
proof.PiB = Utils.Bn.G2.Add(proof.PiB, Utils.Bn.G2.MulScalar(setup.Pk.G2.BACGamma[i], w[i]))
proof.PiA = Utils.Bn.G1.Add(proof.PiA, Utils.Bn.G1.MulScalar(pk.G1.At[i], w[i]))
piBG1 = Utils.Bn.G1.Add(piBG1, Utils.Bn.G1.MulScalar(pk.G1.BACGamma[i], w[i]))
proof.PiB = Utils.Bn.G2.Add(proof.PiB, Utils.Bn.G2.MulScalar(pk.G2.BACGamma[i], w[i]))
} }
for i := circuit.NPublic + 1; i < circuit.NVars; i++ { for i := circuit.NPublic + 1; i < circuit.NVars; i++ {
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(setup.Pk.BACDelta[i], w[i]))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(pk.BACDelta[i], w[i]))
} }
// piA = (Σ from 0 to m (pk.A * w[i])) + pk.Alpha1 + r * δ // piA = (Σ from 0 to m (pk.A * w[i])) + pk.Alpha1 + r * δ
proof.PiA = Utils.Bn.G1.Add(proof.PiA, setup.Pk.G1.Alpha)
deltaR := Utils.Bn.G1.MulScalar(setup.Pk.G1.Delta, r)
proof.PiA = Utils.Bn.G1.Add(proof.PiA, pk.G1.Alpha)
deltaR := Utils.Bn.G1.MulScalar(pk.G1.Delta, r)
proof.PiA = Utils.Bn.G1.Add(proof.PiA, deltaR) proof.PiA = Utils.Bn.G1.Add(proof.PiA, deltaR)
// piBG1 = (Σ from 0 to m (pk.B1 * w[i])) + pk.g1.Beta + s * δ // piBG1 = (Σ from 0 to m (pk.B1 * w[i])) + pk.g1.Beta + s * δ
// piB = piB2 = (Σ from 0 to m (pk.B2 * w[i])) + pk.g2.Beta + s * δ // piB = piB2 = (Σ from 0 to m (pk.B2 * w[i])) + pk.g2.Beta + s * δ
piBG1 = Utils.Bn.G1.Add(piBG1, setup.Pk.G1.Beta)
proof.PiB = Utils.Bn.G2.Add(proof.PiB, setup.Pk.G2.Beta)
deltaSG1 := Utils.Bn.G1.MulScalar(setup.Pk.G1.Delta, s)
piBG1 = Utils.Bn.G1.Add(piBG1, pk.G1.Beta)
proof.PiB = Utils.Bn.G2.Add(proof.PiB, pk.G2.Beta)
deltaSG1 := Utils.Bn.G1.MulScalar(pk.G1.Delta, s)
piBG1 = Utils.Bn.G1.Add(piBG1, deltaSG1) piBG1 = Utils.Bn.G1.Add(piBG1, deltaSG1)
deltaSG2 := Utils.Bn.G2.MulScalar(setup.Pk.G2.Delta, s)
deltaSG2 := Utils.Bn.G2.MulScalar(pk.G2.Delta, s)
proof.PiB = Utils.Bn.G2.Add(proof.PiB, deltaSG2) proof.PiB = Utils.Bn.G2.Add(proof.PiB, deltaSG2)
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) // maybe move this calculation to a previous step
hx := Utils.PF.DivisorPolynomial(px, pk.Z) // maybe move this calculation to a previous step
// piC = (Σ from l+1 to m (w[i] * (pk.g1.Beta + pk.g1.Alpha + pk.C)) + h(tau)) / δ) + piA*s + r*piB - r*s*δ // piC = (Σ from l+1 to m (w[i] * (pk.g1.Beta + pk.g1.Alpha + pk.C)) + h(tau)) / δ) + piA*s + r*piB - r*s*δ
for i := 0; i < len(hx); i++ { for i := 0; i < len(hx); i++ {
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(setup.Pk.PowersTauDelta[i], hx[i]))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(pk.PowersTauDelta[i], hx[i]))
} }
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(proof.PiA, s)) proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(proof.PiA, s))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(piBG1, r)) proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(piBG1, r))
negRS := Utils.FqR.Neg(Utils.FqR.Mul(r, s)) negRS := Utils.FqR.Neg(Utils.FqR.Mul(r, s))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(setup.Pk.G1.Delta, negRS))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(pk.G1.Delta, negRS))
return proof, nil return proof, nil
} }
// VerifyProof verifies over the BN128 the Pairings of the Proof // VerifyProof verifies over the BN128 the Pairings of the Proof
func VerifyProof(setup Setup, proof Proof, publicSignals []*big.Int, debug bool) bool {
func VerifyProof(vk Vk, proof Proof, publicSignals []*big.Int, debug bool) bool {
icPubl := setup.Vk.IC[0]
icPubl := vk.IC[0]
for i := 0; i < len(publicSignals); i++ { for i := 0; i < len(publicSignals); i++ {
icPubl = Utils.Bn.G1.Add(icPubl, Utils.Bn.G1.MulScalar(setup.Vk.IC[i+1], publicSignals[i]))
icPubl = Utils.Bn.G1.Add(icPubl, Utils.Bn.G1.MulScalar(vk.IC[i+1], publicSignals[i]))
} }
if !Utils.Bn.Fq12.Equal( if !Utils.Bn.Fq12.Equal(
Utils.Bn.Pairing(proof.PiA, proof.PiB), Utils.Bn.Pairing(proof.PiA, proof.PiB),
Utils.Bn.Fq12.Mul( Utils.Bn.Fq12.Mul(
Utils.Bn.Pairing(setup.Vk.G1.Alpha, setup.Vk.G2.Beta),
Utils.Bn.Pairing(vk.G1.Alpha, vk.G2.Beta),
Utils.Bn.Fq12.Mul( Utils.Bn.Fq12.Mul(
Utils.Bn.Pairing(icPubl, setup.Vk.G2.Gamma),
Utils.Bn.Pairing(proof.PiC, setup.Vk.G2.Delta)))) {
Utils.Bn.Pairing(icPubl, vk.G2.Gamma),
Utils.Bn.Pairing(proof.PiC, vk.G2.Delta)))) {
if debug { if debug {
fmt.Println("❌ groth16 verification not passed") fmt.Println("❌ groth16 verification not passed")
} }

+ 3
- 3
groth16/groth16_test.go

@ -85,7 +85,7 @@ func TestGroth16MinimalFlow(t *testing.T) {
// check length of polynomials H(x) and Z(x) // 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)
proof, err := GenerateProofs(*circuit, setup, w, px)
proof, err := GenerateProofs(*circuit, setup.Pk, w, px)
assert.Nil(t, err) assert.Nil(t, err)
// fmt.Println("\n proofs:") // fmt.Println("\n proofs:")
@ -97,11 +97,11 @@ func TestGroth16MinimalFlow(t *testing.T) {
b35Verif := big.NewInt(int64(35)) b35Verif := big.NewInt(int64(35))
publicSignalsVerif := []*big.Int{b35Verif} publicSignalsVerif := []*big.Int{b35Verif}
before := time.Now() before := time.Now()
assert.True(t, VerifyProof(setup, proof, publicSignalsVerif, true))
assert.True(t, VerifyProof(setup.Vk, proof, publicSignalsVerif, true))
fmt.Println("verify proof time elapsed:", time.Since(before)) fmt.Println("verify proof time elapsed:", time.Since(before))
// check that with another public input the verification returns false // check that with another public input the verification returns false
bOtherWrongPublic := big.NewInt(int64(34)) bOtherWrongPublic := big.NewInt(int64(34))
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic} wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
assert.True(t, !VerifyProof(setup, proof, wrongPublicSignalsVerif, false))
assert.True(t, !VerifyProof(setup.Vk, proof, wrongPublicSignalsVerif, false))
} }

+ 47
- 44
snark.go

@ -13,6 +13,29 @@ import (
"github.com/arnaucube/go-snark/r1csqap" "github.com/arnaucube/go-snark/r1csqap"
) )
type Pk struct { // Proving Key pk:=(pkA, pkB, pkC, pkH)
G1T [][3]*big.Int // t encrypted in G1 curve, G1T == Pk.H
A [][3]*big.Int
B [][3][2]*big.Int
C [][3]*big.Int
Kp [][3]*big.Int
Ap [][3]*big.Int
Bp [][3]*big.Int
Cp [][3]*big.Int
Z []*big.Int
}
type Vk struct {
Vka [3][2]*big.Int
Vkb [3]*big.Int
Vkc [3][2]*big.Int
IC [][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
Vkz [3][2]*big.Int
}
// Setup is the data structure holding the Trusted Setup data. The Setup.Toxic sub struct must be destroyed after the GenerateTrustedSetup function is completed // Setup is the data structure holding the Trusted Setup data. The Setup.Toxic sub struct must be destroyed after the GenerateTrustedSetup function is completed
type Setup struct { type Setup struct {
Toxic struct { Toxic struct {
@ -28,28 +51,8 @@ type Setup struct {
} }
// public // public
G1T [][3]*big.Int // t encrypted in G1 curve, G1T == Pk.H
G2T [][3][2]*big.Int // t encrypted in G2 curve
Pk struct { // Proving Key pk:=(pkA, pkB, pkC, pkH)
A [][3]*big.Int
B [][3][2]*big.Int
C [][3]*big.Int
Kp [][3]*big.Int
Ap [][3]*big.Int
Bp [][3]*big.Int
Cp [][3]*big.Int
Z []*big.Int
}
Vk struct {
Vka [3][2]*big.Int
Vkb [3]*big.Int
Vkc [3][2]*big.Int
IC [][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
Vkz [3][2]*big.Int
}
Pk Pk
Vk Vk
} }
// Proof contains the parameters to proof the zkSNARK // Proof contains the parameters to proof the zkSNARK
@ -242,13 +245,13 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
// 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) tEncr = Utils.FqR.Mul(tEncr, setup.Toxic.T)
} }
setup.G1T = gt1
setup.Pk.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, w []*big.Int, px []*big.Int) (Proof, error) {
func GenerateProofs(circuit circuitcompiler.Circuit, pk Pk, 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()}
@ -260,35 +263,35 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, w []*big.Int,
proof.PiKp = [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++ { for i := circuit.NPublic + 1; i < circuit.NVars; 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]))
proof.PiA = Utils.Bn.G1.Add(proof.PiA, Utils.Bn.G1.MulScalar(pk.A[i], w[i]))
proof.PiAp = Utils.Bn.G1.Add(proof.PiAp, Utils.Bn.G1.MulScalar(pk.Ap[i], w[i]))
} }
for i := 0; i < circuit.NVars; i++ { for i := 0; i < circuit.NVars; 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.PiB = Utils.Bn.G2.Add(proof.PiB, Utils.Bn.G2.MulScalar(pk.B[i], w[i]))
proof.PiBp = Utils.Bn.G1.Add(proof.PiBp, Utils.Bn.G1.MulScalar(pk.Bp[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.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(pk.C[i], w[i]))
proof.PiCp = Utils.Bn.G1.Add(proof.PiCp, Utils.Bn.G1.MulScalar(pk.Cp[i], w[i]))
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(pk.Kp[i], w[i]))
} }
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) // maybe move this calculation to a previous step
hx := Utils.PF.DivisorPolynomial(px, 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, pk.G1T[0])
for i := 0; i < len(hx); 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(pk.G1T[i], hx[i]))
} }
return proof, nil return proof, nil
} }
// VerifyProof verifies over the BN128 the Pairings of the Proof // VerifyProof verifies over the BN128 the Pairings of the Proof
func VerifyProof(setup Setup, proof Proof, publicSignals []*big.Int, debug bool) bool {
func VerifyProof(vk Vk, 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, 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) {
if debug { if debug {
@ -301,7 +304,7 @@ func VerifyProof(setup Setup, proof Proof, publicSignals []*big.Int, debug bool)
} }
// e(Vb, piB) == e(piB', g2) // e(Vb, piB) == e(piB', g2)
pairingVbPib := Utils.Bn.Pairing(setup.Vk.Vkb, proof.PiB)
pairingVbPib := Utils.Bn.Pairing(vk.Vkb, proof.PiB)
pairingPibpG2 := Utils.Bn.Pairing(proof.PiBp, Utils.Bn.G2.G) pairingPibpG2 := Utils.Bn.Pairing(proof.PiBp, Utils.Bn.G2.G)
if !Utils.Bn.Fq12.Equal(pairingVbPib, pairingPibpG2) { if !Utils.Bn.Fq12.Equal(pairingVbPib, pairingPibpG2) {
if debug { if debug {
@ -314,7 +317,7 @@ func VerifyProof(setup Setup, proof Proof, publicSignals []*big.Int, debug bool)
} }
// e(piC, Vc) == e(piC', g2) // e(piC, Vc) == e(piC', g2)
pairingPicVc := Utils.Bn.Pairing(proof.PiC, setup.Vk.Vkc)
pairingPicVc := Utils.Bn.Pairing(proof.PiC, vk.Vkc)
pairingPicpG2 := Utils.Bn.Pairing(proof.PiCp, Utils.Bn.G2.G) pairingPicpG2 := Utils.Bn.Pairing(proof.PiCp, Utils.Bn.G2.G)
if !Utils.Bn.Fq12.Equal(pairingPicVc, pairingPicpG2) { if !Utils.Bn.Fq12.Equal(pairingPicVc, pairingPicpG2) {
if debug { if debug {
@ -327,16 +330,16 @@ func VerifyProof(setup Setup, proof Proof, publicSignals []*big.Int, debug bool)
} }
// Vkx, to then calculate Vkx+piA // Vkx, to then calculate Vkx+piA
vkxpia := setup.Vk.IC[0]
vkxpia := vk.IC[0]
for i := 0; i < len(publicSignals); i++ { for i := 0; i < len(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(vk.IC[i+1], publicSignals[i]))
} }
// e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2) // e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2)
if !Utils.Bn.Fq12.Equal( if !Utils.Bn.Fq12.Equal(
Utils.Bn.Pairing(Utils.Bn.G1.Add(vkxpia, proof.PiA), proof.PiB), // TODO Add(vkxpia, proof.PiA) can go outside in order to save computation, as is reused later Utils.Bn.Pairing(Utils.Bn.G1.Add(vkxpia, proof.PiA), proof.PiB), // TODO Add(vkxpia, proof.PiA) can go outside in order to save computation, as is reused later
Utils.Bn.Fq12.Mul( Utils.Bn.Fq12.Mul(
Utils.Bn.Pairing(proof.PiH, setup.Vk.Vkz),
Utils.Bn.Pairing(proof.PiH, vk.Vkz),
Utils.Bn.Pairing(proof.PiC, Utils.Bn.G2.G))) { Utils.Bn.Pairing(proof.PiC, Utils.Bn.G2.G))) {
if debug { 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")
@ -350,10 +353,10 @@ func VerifyProof(setup Setup, proof Proof, publicSignals []*big.Int, debug bool)
// e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) // e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB)
// == e(piK, g2Kgamma) // == e(piK, g2Kgamma)
piApiC := Utils.Bn.G1.Add(Utils.Bn.G1.Add(vkxpia, proof.PiA), proof.PiC) 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)
pairingPiACG2Kbg := Utils.Bn.Pairing(piApiC, vk.G2Kbg)
pairingG1KbgPiB := Utils.Bn.Pairing(vk.G1Kbg, proof.PiB)
pairingL := Utils.Bn.Fq12.Mul(pairingPiACG2Kbg, pairingG1KbgPiB) pairingL := Utils.Bn.Fq12.Mul(pairingPiACG2Kbg, pairingG1KbgPiB)
pairingR := Utils.Bn.Pairing(proof.PiKp, setup.Vk.G2Kg)
pairingR := Utils.Bn.Pairing(proof.PiKp, vk.G2Kg)
if !Utils.Bn.Fq12.Equal(pairingL, pairingR) { if !Utils.Bn.Fq12.Equal(pairingL, pairingR) {
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 false return false

+ 12
- 12
snark_test.go

@ -86,7 +86,7 @@ func TestGroth16MinimalFlow(t *testing.T) {
// check length of polynomials H(x) and Z(x) // 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)
proof, err := groth16.GenerateProofs(*circuit, setup, w, px)
proof, err := groth16.GenerateProofs(*circuit, setup.Pk, w, px)
assert.Nil(t, err) assert.Nil(t, err)
// fmt.Println("\n proofs:") // fmt.Println("\n proofs:")
@ -98,13 +98,13 @@ func TestGroth16MinimalFlow(t *testing.T) {
b35Verif := big.NewInt(int64(35)) b35Verif := big.NewInt(int64(35))
publicSignalsVerif := []*big.Int{b35Verif} publicSignalsVerif := []*big.Int{b35Verif}
before := time.Now() before := time.Now()
assert.True(t, groth16.VerifyProof(setup, proof, publicSignalsVerif, true))
assert.True(t, groth16.VerifyProof(setup.Vk, proof, publicSignalsVerif, true))
fmt.Println("verify proof time elapsed:", time.Since(before)) fmt.Println("verify proof time elapsed:", time.Since(before))
// check that with another public input the verification returns false // check that with another public input the verification returns false
bOtherWrongPublic := big.NewInt(int64(34)) bOtherWrongPublic := big.NewInt(int64(34))
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic} wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
assert.True(t, !groth16.VerifyProof(setup, proof, wrongPublicSignalsVerif, false))
assert.True(t, !groth16.VerifyProof(setup.Vk, proof, wrongPublicSignalsVerif, false))
} }
func TestZkFromFlatCircuitCode(t *testing.T) { func TestZkFromFlatCircuitCode(t *testing.T) {
@ -221,7 +221,7 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
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)
proof, err := GenerateProofs(*circuit, setup, w, px)
proof, err := GenerateProofs(*circuit, setup.Pk, w, px)
assert.Nil(t, err) assert.Nil(t, err)
// fmt.Println("\n proofs:") // fmt.Println("\n proofs:")
@ -233,13 +233,13 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
b35Verif := big.NewInt(int64(35)) b35Verif := big.NewInt(int64(35))
publicSignalsVerif := []*big.Int{b35Verif} publicSignalsVerif := []*big.Int{b35Verif}
before := time.Now() before := time.Now()
assert.True(t, VerifyProof(setup, proof, publicSignalsVerif, true))
assert.True(t, VerifyProof(setup.Vk, proof, publicSignalsVerif, true))
fmt.Println("verify proof time elapsed:", time.Since(before)) fmt.Println("verify proof time elapsed:", time.Since(before))
// check that with another public input the verification returns false // check that with another public input the verification returns false
bOtherWrongPublic := big.NewInt(int64(34)) bOtherWrongPublic := big.NewInt(int64(34))
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic} wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
assert.True(t, !VerifyProof(setup, proof, wrongPublicSignalsVerif, false))
assert.True(t, !VerifyProof(setup.Vk, proof, wrongPublicSignalsVerif, false))
} }
func TestZkMultiplication(t *testing.T) { func TestZkMultiplication(t *testing.T) {
@ -329,7 +329,7 @@ func TestZkMultiplication(t *testing.T) {
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)
proof, err := GenerateProofs(*circuit, setup, w, px)
proof, err := GenerateProofs(*circuit, setup.Pk, w, px)
assert.Nil(t, err) assert.Nil(t, err)
// fmt.Println("\n proofs:") // fmt.Println("\n proofs:")
@ -341,13 +341,13 @@ func TestZkMultiplication(t *testing.T) {
b12Verif := big.NewInt(int64(12)) b12Verif := big.NewInt(int64(12))
publicSignalsVerif := []*big.Int{b12Verif} publicSignalsVerif := []*big.Int{b12Verif}
before := time.Now() before := time.Now()
assert.True(t, VerifyProof(setup, proof, publicSignalsVerif, true))
assert.True(t, VerifyProof(setup.Vk, proof, publicSignalsVerif, true))
fmt.Println("verify proof time elapsed:", time.Since(before)) fmt.Println("verify proof time elapsed:", time.Since(before))
// check that with another public input the verification returns false // check that with another public input the verification returns false
bOtherWrongPublic := big.NewInt(int64(11)) bOtherWrongPublic := big.NewInt(int64(11))
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic} wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
assert.True(t, !VerifyProof(setup, proof, wrongPublicSignalsVerif, false))
assert.True(t, !VerifyProof(setup.Vk, proof, wrongPublicSignalsVerif, false))
} }
func TestMinimalFlow(t *testing.T) { func TestMinimalFlow(t *testing.T) {
@ -418,7 +418,7 @@ func TestMinimalFlow(t *testing.T) {
// check length of polynomials H(x) and Z(x) // 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)
proof, err := GenerateProofs(*circuit, setup, w, px)
proof, err := GenerateProofs(*circuit, setup.Pk, w, px)
assert.Nil(t, err) assert.Nil(t, err)
// fmt.Println("\n proofs:") // fmt.Println("\n proofs:")
@ -430,11 +430,11 @@ func TestMinimalFlow(t *testing.T) {
b35Verif := big.NewInt(int64(35)) b35Verif := big.NewInt(int64(35))
publicSignalsVerif := []*big.Int{b35Verif} publicSignalsVerif := []*big.Int{b35Verif}
before := time.Now() before := time.Now()
assert.True(t, VerifyProof(setup, proof, publicSignalsVerif, true))
assert.True(t, VerifyProof(setup.Vk, proof, publicSignalsVerif, true))
fmt.Println("verify proof time elapsed:", time.Since(before)) fmt.Println("verify proof time elapsed:", time.Since(before))
// check that with another public input the verification returns false // check that with another public input the verification returns false
bOtherWrongPublic := big.NewInt(int64(34)) bOtherWrongPublic := big.NewInt(int64(34))
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic} wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
assert.True(t, !VerifyProof(setup, proof, wrongPublicSignalsVerif, false))
assert.True(t, !VerifyProof(setup.Vk, proof, wrongPublicSignalsVerif, false))
} }

+ 4
- 4
wasm/go-snark-wasm-wrapper.go

@ -80,7 +80,7 @@ func generateProofs(this js.Value, i []js.Value) interface{} {
} }
w, err := circuit.CalculateWitness(inputs.Private, inputs.Public) w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
proof, err := snark.GenerateProofs(circuit, setup, w, px)
proof, err := snark.GenerateProofs(circuit, setup.Pk, w, px)
if err != nil { if err != nil {
println("error generating proof", err) println("error generating proof", err)
} }
@ -123,7 +123,7 @@ func verifyProofs(this js.Value, i []js.Value) interface{} {
println("error parsing publicInputs from stringified json") println("error parsing publicInputs from stringified json")
} }
verified := snark.VerifyProof(setup, proof, publicInputs, false)
verified := snark.VerifyProof(setup.Vk, proof, publicInputs, false)
if err != nil { if err != nil {
println("error verifiyng proof", err) println("error verifiyng proof", err)
} }
@ -190,7 +190,7 @@ func grothGenerateProofs(this js.Value, i []js.Value) interface{} {
} }
w, err := circuit.CalculateWitness(inputs.Private, inputs.Public) w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
proof, err := groth16.GenerateProofs(circuit, setup, w, px)
proof, err := groth16.GenerateProofs(circuit, setup.Pk, w, px)
if err != nil { if err != nil {
println("error generating proof", err) println("error generating proof", err)
} }
@ -233,7 +233,7 @@ func grothVerifyProofs(this js.Value, i []js.Value) interface{} {
println("error parsing publicInputs from stringified json") println("error parsing publicInputs from stringified json")
} }
verified := groth16.VerifyProof(setup, proof, publicInputs, false)
verified := groth16.VerifyProof(setup.Vk, proof, publicInputs, false)
if err != nil { if err != nil {
println("error verifiyng proof", err) println("error verifiyng proof", err)
} }

BIN
wasm/go-snark.wasm


+ 12
- 18
wasm/utils/utils.go

@ -134,17 +134,16 @@ func Array32BigIntToString(b [][3][2]*big.Int) [][3][2]string {
// Setup // Setup
type SetupString struct { type SetupString struct {
// public // public
G1T [][3]string
G2T [][3][2]string
Pk struct {
A [][3]string
B [][3][2]string
C [][3]string
Kp [][3]string
Ap [][3]string
Bp [][3]string
Cp [][3]string
Z []string
Pk struct {
G1T [][3]string
A [][3]string
B [][3][2]string
C [][3]string
Kp [][3]string
Ap [][3]string
Bp [][3]string
Cp [][3]string
Z []string
} }
Vk struct { Vk struct {
Vka [3][2]string Vka [3][2]string
@ -160,8 +159,7 @@ type SetupString struct {
func SetupToString(setup snark.Setup) SetupString { func SetupToString(setup snark.Setup) SetupString {
var s SetupString var s SetupString
s.G1T = Array3BigIntToString(setup.G1T)
s.G2T = Array32BigIntToString(setup.G2T)
s.Pk.G1T = Array3BigIntToString(setup.Pk.G1T)
s.Pk.A = Array3BigIntToString(setup.Pk.A) s.Pk.A = Array3BigIntToString(setup.Pk.A)
s.Pk.B = Array32BigIntToString(setup.Pk.B) s.Pk.B = Array32BigIntToString(setup.Pk.B)
s.Pk.C = Array3BigIntToString(setup.Pk.C) s.Pk.C = Array3BigIntToString(setup.Pk.C)
@ -183,11 +181,7 @@ func SetupToString(setup snark.Setup) SetupString {
func SetupFromString(s SetupString) (snark.Setup, error) { func SetupFromString(s SetupString) (snark.Setup, error) {
var o snark.Setup var o snark.Setup
var err error var err error
o.G1T, err = Array3StringToBigInt(s.G1T)
if err != nil {
return o, err
}
o.G2T, err = Array32StringToBigInt(s.G2T)
o.Pk.G1T, err = Array3StringToBigInt(s.Pk.G1T)
if err != nil { if err != nil {
return o, err return o, err
} }

Loading…
Cancel
Save