mirror of
https://github.com/arnaucube/go-snark-study.git
synced 2026-02-03 01:36:41 +01:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f57599c091 | ||
|
|
e3cd35c1c9 | ||
|
|
fa91b9ffad | ||
|
|
a37361abf7 | ||
|
|
7b1a15df7f |
7
.travis.yml
Normal file
7
.travis.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- "1.12"
|
||||
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
29
README.md
29
README.md
@@ -1,18 +1,21 @@
|
||||
# go-snark [](https://goreportcard.com/report/github.com/arnaucube/go-snark)
|
||||
# go-snark [](https://goreportcard.com/report/github.com/arnaucube/go-snark) [](https://travis-ci.org/arnaucube/go-snark) [](https://gitter.im/go-snark/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
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
|
||||
- `On the Size of Pairing-based Non-interactive Arguments`, Jens Groth https://eprint.iacr.org/2016/260.pdf
|
||||
|
||||
## Caution & Warning
|
||||
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.
|
||||
Implementation of the zkSNARK [Pinocchio protocol](https://eprint.iacr.org/2013/279.pdf) and [Groth16 protocol](https://eprint.iacr.org/2016/260.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.
|
||||
|
||||
Currently allows to do the complete path with [Pinocchio protocol](https://eprint.iacr.org/2013/279.pdf) :
|
||||
1. compile circuuit
|
||||
Currently allows to do the complete path with [Pinocchio protocol](https://eprint.iacr.org/2013/279.pdf) and [Groth16 protocol](https://eprint.iacr.org/2016/260.pdf) :
|
||||
|
||||
0. write circuit
|
||||
1. compile circuit
|
||||
2. generate trusted setup
|
||||
3. calculate witness
|
||||
4. generate proofs
|
||||
@@ -35,12 +38,13 @@ Improvements from the minimal implementation:
|
||||
- [x] allow `import` in circuits language
|
||||
- [ ] allow `for` in circuits language
|
||||
- [ ] move witness values calculation outside the setup phase
|
||||
- [ ] Groth16
|
||||
- [x] Groth16
|
||||
- [ ] multiple optimizations
|
||||
|
||||
|
||||
## Usage
|
||||
- [](https://godoc.org/github.com/arnaucube/go-snark) zkSnark
|
||||
- [](https://godoc.org/github.com/arnaucube/go-snark/groth16) zkSnark Groth16
|
||||
- [](https://godoc.org/github.com/arnaucube/go-snark/bn128) bn128 (more details: https://github.com/arnaucube/go-snark/tree/master/bn128)
|
||||
- [](https://godoc.org/github.com/arnaucube/go-snark/fields) Finite Fields operations
|
||||
- [](https://godoc.org/github.com/arnaucube/go-snark/r1csqap) R1CS to QAP (more details: https://github.com/arnaucube/go-snark/tree/master/r1csqap)
|
||||
@@ -109,6 +113,16 @@ Having the `proofs.json`, `compiledcircuit.json`, `trustedsetup.json` `publicInp
|
||||
```
|
||||
This will return a `true` if the proofs are verified, or a `false` if the proofs are not verified.
|
||||
|
||||
### Cli using Groth16
|
||||
All this process can be done using [Groth16 protocol](https://eprint.iacr.org/2016/260.pdf) protocol:
|
||||
```
|
||||
> ./go-snark-cli compile test.circuit
|
||||
> ./go-snark-cli groth16 trustedsetup
|
||||
> ./go-snark-cli groth16 genproofs
|
||||
> ./go-snark-cli verify
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Library usage
|
||||
|
||||
@@ -179,6 +193,11 @@ assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
|
||||
```
|
||||
|
||||
|
||||
## Versions
|
||||
History of versions & tags of this project:
|
||||
- v0.0.1: zkSnark complete flow working with Pinocchio protocol
|
||||
- v0.0.2: circuit language improved (allow function calls and file imports)
|
||||
- v0.0.3: Groth16 zkSnark protocol added
|
||||
|
||||
## Test
|
||||
```
|
||||
|
||||
187
cli/main.go
187
cli/main.go
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
snark "github.com/arnaucube/go-snark"
|
||||
"github.com/arnaucube/go-snark/circuitcompiler"
|
||||
"github.com/arnaucube/go-snark/groth16"
|
||||
"github.com/arnaucube/go-snark/r1csqap"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
@@ -48,12 +49,37 @@ var commands = []cli.Command{
|
||||
Usage: "verify the snark proofs",
|
||||
Action: VerifyProofs,
|
||||
},
|
||||
{
|
||||
Name: "groth16",
|
||||
Aliases: []string{},
|
||||
Usage: "use groth16 protocol",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "trustedsetup",
|
||||
Aliases: []string{},
|
||||
Usage: "generate trusted setup for a circuit",
|
||||
Action: Groth16TrustedSetup,
|
||||
},
|
||||
{
|
||||
Name: "genproofs",
|
||||
Aliases: []string{},
|
||||
Usage: "generate the snark proofs",
|
||||
Action: Groth16GenerateProofs,
|
||||
},
|
||||
{
|
||||
Name: "verify",
|
||||
Aliases: []string{},
|
||||
Usage: "verify the snark proofs",
|
||||
Action: Groth16VerifyProofs,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "go-snarks-cli"
|
||||
app.Version = "0.0.1-alpha"
|
||||
app.Version = "0.0.3-alpha"
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{Name: "config"},
|
||||
}
|
||||
@@ -322,3 +348,162 @@ func VerifyProofs(context *cli.Context) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Groth16TrustedSetup(context *cli.Context) error {
|
||||
// open compiledcircuit.json
|
||||
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
|
||||
panicErr(err)
|
||||
var circuit circuitcompiler.Circuit
|
||||
json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
|
||||
panicErr(err)
|
||||
|
||||
// read privateInputs file
|
||||
privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
|
||||
panicErr(err)
|
||||
// read publicInputs file
|
||||
publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
|
||||
panicErr(err)
|
||||
|
||||
// parse inputs from inputsFile
|
||||
var inputs circuitcompiler.Inputs
|
||||
err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
|
||||
panicErr(err)
|
||||
err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
|
||||
panicErr(err)
|
||||
|
||||
// calculate wittness
|
||||
w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
|
||||
panicErr(err)
|
||||
|
||||
// R1CS to QAP
|
||||
alphas, betas, gammas, _ := snark.Utils.PF.R1CSToQAP(circuit.R1CS.A, circuit.R1CS.B, circuit.R1CS.C)
|
||||
fmt.Println("qap")
|
||||
fmt.Println(alphas)
|
||||
fmt.Println(betas)
|
||||
fmt.Println(gammas)
|
||||
|
||||
// calculate trusted setup
|
||||
setup, err := groth16.GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas)
|
||||
panicErr(err)
|
||||
fmt.Println("\nt:", setup.Toxic.T)
|
||||
|
||||
// remove setup.Toxic
|
||||
var tsetup groth16.Setup
|
||||
tsetup.Pk = setup.Pk
|
||||
tsetup.Vk = setup.Vk
|
||||
|
||||
// store setup to json
|
||||
jsonData, err := json.Marshal(tsetup)
|
||||
panicErr(err)
|
||||
// store setup into file
|
||||
jsonFile, err := os.Create("trustedsetup.json")
|
||||
panicErr(err)
|
||||
defer jsonFile.Close()
|
||||
jsonFile.Write(jsonData)
|
||||
jsonFile.Close()
|
||||
fmt.Println("Trusted Setup data written to ", jsonFile.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
func Groth16GenerateProofs(context *cli.Context) error {
|
||||
// open compiledcircuit.json
|
||||
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
|
||||
panicErr(err)
|
||||
var circuit circuitcompiler.Circuit
|
||||
json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
|
||||
panicErr(err)
|
||||
|
||||
// open trustedsetup.json
|
||||
trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
|
||||
panicErr(err)
|
||||
var trustedsetup groth16.Setup
|
||||
json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
|
||||
panicErr(err)
|
||||
|
||||
// read privateInputs file
|
||||
privateInputsFile, err := ioutil.ReadFile("privateInputs.json")
|
||||
panicErr(err)
|
||||
// read publicInputs file
|
||||
publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
|
||||
panicErr(err)
|
||||
// parse inputs from inputsFile
|
||||
var inputs circuitcompiler.Inputs
|
||||
err = json.Unmarshal([]byte(string(privateInputsFile)), &inputs.Private)
|
||||
panicErr(err)
|
||||
err = json.Unmarshal([]byte(string(publicInputsFile)), &inputs.Public)
|
||||
panicErr(err)
|
||||
|
||||
// calculate wittness
|
||||
w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
|
||||
panicErr(err)
|
||||
fmt.Println("witness", w)
|
||||
|
||||
// flat code to R1CS
|
||||
a := circuit.R1CS.A
|
||||
b := circuit.R1CS.B
|
||||
c := circuit.R1CS.C
|
||||
// R1CS to QAP
|
||||
alphas, betas, gammas, _ := groth16.Utils.PF.R1CSToQAP(a, b, c)
|
||||
_, _, _, px := groth16.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||
hx := groth16.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z)
|
||||
|
||||
fmt.Println(circuit)
|
||||
fmt.Println(trustedsetup.Pk.PowersTauDelta)
|
||||
fmt.Println(hx)
|
||||
fmt.Println(w)
|
||||
proof, err := groth16.GenerateProofs(circuit, trustedsetup, w, px)
|
||||
panicErr(err)
|
||||
|
||||
fmt.Println("\n proofs:")
|
||||
fmt.Println(proof)
|
||||
|
||||
// store proofs to json
|
||||
jsonData, err := json.Marshal(proof)
|
||||
panicErr(err)
|
||||
// store proof into file
|
||||
jsonFile, err := os.Create("proofs.json")
|
||||
panicErr(err)
|
||||
defer jsonFile.Close()
|
||||
jsonFile.Write(jsonData)
|
||||
jsonFile.Close()
|
||||
fmt.Println("Proofs data written to ", jsonFile.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
func Groth16VerifyProofs(context *cli.Context) error {
|
||||
// open proofs.json
|
||||
proofsFile, err := ioutil.ReadFile("proofs.json")
|
||||
panicErr(err)
|
||||
var proof groth16.Proof
|
||||
json.Unmarshal([]byte(string(proofsFile)), &proof)
|
||||
panicErr(err)
|
||||
|
||||
// open compiledcircuit.json
|
||||
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
|
||||
panicErr(err)
|
||||
var circuit circuitcompiler.Circuit
|
||||
json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
|
||||
panicErr(err)
|
||||
|
||||
// open trustedsetup.json
|
||||
trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
|
||||
panicErr(err)
|
||||
var trustedsetup groth16.Setup
|
||||
json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
|
||||
panicErr(err)
|
||||
|
||||
// read publicInputs file
|
||||
publicInputsFile, err := ioutil.ReadFile("publicInputs.json")
|
||||
panicErr(err)
|
||||
var publicSignals []*big.Int
|
||||
err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
|
||||
panicErr(err)
|
||||
|
||||
verified := groth16.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
|
||||
if !verified {
|
||||
fmt.Println("ERROR: proofs not verified")
|
||||
} else {
|
||||
fmt.Println("Proofs verified")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
15
fields/fq.go
15
fields/fq.go
@@ -32,35 +32,30 @@ func (fq Fq) One() *big.Int {
|
||||
func (fq Fq) Add(a, b *big.Int) *big.Int {
|
||||
r := new(big.Int).Add(a, b)
|
||||
return new(big.Int).Mod(r, fq.Q)
|
||||
// return r
|
||||
}
|
||||
|
||||
// Double performs a doubling on the Fq
|
||||
func (fq Fq) Double(a *big.Int) *big.Int {
|
||||
r := new(big.Int).Add(a, a)
|
||||
return new(big.Int).Mod(r, fq.Q)
|
||||
// return r
|
||||
}
|
||||
|
||||
// Sub performs a subtraction on the Fq
|
||||
func (fq Fq) Sub(a, b *big.Int) *big.Int {
|
||||
r := new(big.Int).Sub(a, b)
|
||||
return new(big.Int).Mod(r, fq.Q)
|
||||
// return r
|
||||
}
|
||||
|
||||
// Neg performs a negation on the Fq
|
||||
func (fq Fq) Neg(a *big.Int) *big.Int {
|
||||
m := new(big.Int).Neg(a)
|
||||
return new(big.Int).Mod(m, fq.Q)
|
||||
// return m
|
||||
}
|
||||
|
||||
// Mul performs a multiplication on the Fq
|
||||
func (fq Fq) Mul(a, b *big.Int) *big.Int {
|
||||
m := new(big.Int).Mul(a, b)
|
||||
return new(big.Int).Mod(m, fq.Q)
|
||||
// return m
|
||||
}
|
||||
|
||||
func (fq Fq) MulScalar(base, e *big.Int) *big.Int {
|
||||
@@ -125,8 +120,6 @@ func (fq Fq) Rand() (*big.Int, error) {
|
||||
|
||||
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
|
||||
@@ -134,7 +127,7 @@ func (fq Fq) Rand() (*big.Int, error) {
|
||||
r := new(big.Int).SetBytes(b)
|
||||
rq := new(big.Int).Mod(r, fq.Q)
|
||||
|
||||
// return r over q, nil
|
||||
// r over q, nil
|
||||
return rq, nil
|
||||
}
|
||||
|
||||
@@ -170,3 +163,9 @@ func (fq Fq) Equal(a, b *big.Int) bool {
|
||||
bAff := fq.Affine(b)
|
||||
return bytes.Equal(aAff.Bytes(), bAff.Bytes())
|
||||
}
|
||||
|
||||
func BigIsOdd(n *big.Int) bool {
|
||||
one := big.NewInt(int64(1))
|
||||
and := new(big.Int).And(n, one)
|
||||
return bytes.Equal(and.Bytes(), big.NewInt(int64(1)).Bytes())
|
||||
}
|
||||
|
||||
@@ -136,12 +136,6 @@ func (fq12 Fq12) Square(a [2][3][2]*big.Int) [2][3][2]*big.Int {
|
||||
}
|
||||
}
|
||||
|
||||
func BigIsOdd(n *big.Int) bool {
|
||||
one := big.NewInt(int64(1))
|
||||
and := new(big.Int).And(n, one)
|
||||
return bytes.Equal(and.Bytes(), big.NewInt(int64(1)).Bytes())
|
||||
}
|
||||
|
||||
func (fq12 Fq12) Exp(base [2][3][2]*big.Int, e *big.Int) [2][3][2]*big.Int {
|
||||
// TODO fix bottleneck
|
||||
|
||||
|
||||
BIN
go-snark-cli
BIN
go-snark-cli
Binary file not shown.
302
groth16/groth16.go
Normal file
302
groth16/groth16.go
Normal file
@@ -0,0 +1,302 @@
|
||||
// implementation of https://eprint.iacr.org/2016/260.pdf
|
||||
|
||||
package groth16
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/arnaucube/go-snark/bn128"
|
||||
"github.com/arnaucube/go-snark/circuitcompiler"
|
||||
"github.com/arnaucube/go-snark/fields"
|
||||
"github.com/arnaucube/go-snark/r1csqap"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
Toxic struct {
|
||||
T *big.Int // trusted setup secret
|
||||
Kalpha *big.Int
|
||||
Kbeta *big.Int
|
||||
Kgamma *big.Int
|
||||
Kdelta *big.Int
|
||||
}
|
||||
|
||||
// public
|
||||
Pk struct { // Proving Key
|
||||
BACDelta [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to l
|
||||
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 l+1 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 l+1 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Proof contains the parameters to proof the zkSNARK
|
||||
type Proof struct {
|
||||
PiA [3]*big.Int
|
||||
PiB [3][2]*big.Int
|
||||
PiC [3]*big.Int
|
||||
}
|
||||
|
||||
type utils struct {
|
||||
Bn bn128.Bn128
|
||||
FqR fields.Fq
|
||||
PF r1csqap.PolynomialField
|
||||
}
|
||||
|
||||
// Utils is the data structure holding the BN128, FqR Finite Field over R, PolynomialField, that will be used inside the snarks operations
|
||||
var Utils = prepareUtils()
|
||||
|
||||
func prepareUtils() utils {
|
||||
bn, err := bn128.NewBn128()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// new Finite Field
|
||||
fqR := fields.NewFq(bn.R)
|
||||
// new Polynomial Field
|
||||
pf := r1csqap.NewPolynomialField(fqR)
|
||||
|
||||
return utils{
|
||||
Bn: bn,
|
||||
FqR: fqR,
|
||||
PF: pf,
|
||||
}
|
||||
}
|
||||
|
||||
// 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) (Setup, error) {
|
||||
var setup Setup
|
||||
var err error
|
||||
|
||||
// generate random t value
|
||||
setup.Toxic.T, err = Utils.FqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
|
||||
setup.Toxic.Kalpha, err = Utils.FqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
setup.Toxic.Kbeta, err = Utils.FqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
setup.Toxic.Kgamma, err = Utils.FqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
setup.Toxic.Kdelta, err = Utils.FqR.Rand()
|
||||
if err != nil {
|
||||
return Setup{}, err
|
||||
}
|
||||
|
||||
// z pol
|
||||
zpol := []*big.Int{big.NewInt(int64(1))}
|
||||
for i := 1; i < len(alphas)-1; i++ {
|
||||
zpol = Utils.PF.Mul(
|
||||
zpol,
|
||||
[]*big.Int{
|
||||
Utils.FqR.Neg(
|
||||
big.NewInt(int64(i))),
|
||||
big.NewInt(int64(1)),
|
||||
})
|
||||
}
|
||||
setup.Pk.Z = zpol
|
||||
zt := Utils.PF.Eval(zpol, setup.Toxic.T)
|
||||
invDelta := Utils.FqR.Inverse(setup.Toxic.Kdelta)
|
||||
ztinvDelta := Utils.FqR.Mul(invDelta, zt)
|
||||
|
||||
// encrypt t values with curve generators
|
||||
// powers of tau divided by delta
|
||||
var ptd [][3]*big.Int
|
||||
ini := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, ztinvDelta)
|
||||
ptd = append(ptd, ini)
|
||||
tEncr := setup.Toxic.T
|
||||
for i := 1; i < len(zpol); i++ {
|
||||
ptd = append(ptd, Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, Utils.FqR.Mul(tEncr, ztinvDelta)))
|
||||
tEncr = Utils.FqR.Mul(tEncr, setup.Toxic.T)
|
||||
}
|
||||
// powers of τ encrypted in G1 curve, divided by δ
|
||||
// (G1 * τ) / δ
|
||||
setup.Pk.PowersTauDelta = ptd
|
||||
|
||||
setup.Pk.G1.Alpha = Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, setup.Toxic.Kalpha)
|
||||
setup.Pk.G1.Beta = Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, setup.Toxic.Kbeta)
|
||||
setup.Pk.G1.Delta = Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, setup.Toxic.Kdelta)
|
||||
setup.Pk.G2.Beta = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kbeta)
|
||||
setup.Pk.G2.Delta = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kdelta)
|
||||
|
||||
setup.Vk.G1.Alpha = Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, setup.Toxic.Kalpha)
|
||||
setup.Vk.G2.Beta = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kbeta)
|
||||
setup.Vk.G2.Gamma = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kgamma)
|
||||
setup.Vk.G2.Delta = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kdelta)
|
||||
|
||||
for i := 0; i < len(circuit.Signals); i++ {
|
||||
// Pk.G1.At: {a(τ)} from 0 to m
|
||||
at := Utils.PF.Eval(alphas[i], setup.Toxic.T)
|
||||
a := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, at)
|
||||
setup.Pk.G1.At = append(setup.Pk.G1.At, a)
|
||||
|
||||
bt := Utils.PF.Eval(betas[i], setup.Toxic.T)
|
||||
g1bt := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, bt)
|
||||
g2bt := Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, bt)
|
||||
// G1.BACGamma: {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m in G1
|
||||
setup.Pk.G1.BACGamma = append(setup.Pk.G1.BACGamma, g1bt)
|
||||
// G2.BACGamma: {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m in G2
|
||||
setup.Pk.G2.BACGamma = append(setup.Pk.G2.BACGamma, g2bt)
|
||||
}
|
||||
|
||||
zero3 := [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
|
||||
for i := 0; i < circuit.NPublic+1; i++ {
|
||||
setup.Pk.BACDelta = append(setup.Pk.BACDelta, zero3)
|
||||
}
|
||||
for i := circuit.NPublic + 1; i < circuit.NVars; i++ {
|
||||
// TODO calculate all at, bt, ct outside, to avoid repeating calculations
|
||||
at := Utils.PF.Eval(alphas[i], setup.Toxic.T)
|
||||
bt := Utils.PF.Eval(betas[i], setup.Toxic.T)
|
||||
ct := Utils.PF.Eval(gammas[i], setup.Toxic.T)
|
||||
c := Utils.FqR.Mul(
|
||||
invDelta,
|
||||
Utils.FqR.Add(
|
||||
Utils.FqR.Add(
|
||||
Utils.FqR.Mul(at, setup.Toxic.Kbeta),
|
||||
Utils.FqR.Mul(bt, setup.Toxic.Kalpha),
|
||||
),
|
||||
ct,
|
||||
),
|
||||
)
|
||||
g1c := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, c)
|
||||
|
||||
// Pk.BACDelta: {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to l
|
||||
setup.Pk.BACDelta = append(setup.Pk.BACDelta, g1c)
|
||||
}
|
||||
|
||||
for i := 0; i <= circuit.NPublic; i++ {
|
||||
at := Utils.PF.Eval(alphas[i], setup.Toxic.T)
|
||||
bt := Utils.PF.Eval(betas[i], setup.Toxic.T)
|
||||
ct := Utils.PF.Eval(gammas[i], setup.Toxic.T)
|
||||
ic := Utils.FqR.Mul(
|
||||
Utils.FqR.Inverse(setup.Toxic.Kgamma),
|
||||
Utils.FqR.Add(
|
||||
Utils.FqR.Add(
|
||||
Utils.FqR.Mul(at, setup.Toxic.Kbeta),
|
||||
Utils.FqR.Mul(bt, setup.Toxic.Kalpha),
|
||||
),
|
||||
ct,
|
||||
),
|
||||
)
|
||||
g1ic := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, ic)
|
||||
// used in verifier
|
||||
setup.Vk.IC = append(setup.Vk.IC, g1ic)
|
||||
}
|
||||
|
||||
return setup, nil
|
||||
}
|
||||
|
||||
// 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) {
|
||||
var proof Proof
|
||||
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.PiC = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
|
||||
|
||||
r, err := Utils.FqR.Rand()
|
||||
if err != nil {
|
||||
return Proof{}, err
|
||||
}
|
||||
s, err := Utils.FqR.Rand()
|
||||
if err != nil {
|
||||
return Proof{}, err
|
||||
}
|
||||
|
||||
// piBG1 will hold all the same than proof.PiB but in G1 curve
|
||||
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++ {
|
||||
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]))
|
||||
}
|
||||
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]))
|
||||
}
|
||||
|
||||
// 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, deltaR)
|
||||
|
||||
// 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 * δ
|
||||
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, deltaSG1)
|
||||
deltaSG2 := Utils.Bn.G2.MulScalar(setup.Pk.G2.Delta, s)
|
||||
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
|
||||
|
||||
// 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++ {
|
||||
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(proof.PiA, s))
|
||||
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(piBG1, r))
|
||||
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))
|
||||
|
||||
return proof, nil
|
||||
}
|
||||
|
||||
// VerifyProof verifies over the BN128 the Pairings of the Proof
|
||||
func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publicSignals []*big.Int, debug bool) bool {
|
||||
|
||||
icPubl := setup.Vk.IC[0]
|
||||
for i := 0; i < len(publicSignals); i++ {
|
||||
icPubl = Utils.Bn.G1.Add(icPubl, Utils.Bn.G1.MulScalar(setup.Vk.IC[i+1], publicSignals[i]))
|
||||
}
|
||||
|
||||
if !Utils.Bn.Fq12.Equal(
|
||||
Utils.Bn.Pairing(proof.PiA, proof.PiB),
|
||||
Utils.Bn.Fq12.Mul(
|
||||
Utils.Bn.Pairing(setup.Vk.G1.Alpha, setup.Vk.G2.Beta),
|
||||
Utils.Bn.Fq12.Mul(
|
||||
Utils.Bn.Pairing(icPubl, setup.Vk.G2.Gamma),
|
||||
Utils.Bn.Pairing(proof.PiC, setup.Vk.G2.Delta)))) {
|
||||
if debug {
|
||||
fmt.Println("❌ groth16 verification not passed")
|
||||
}
|
||||
return false
|
||||
}
|
||||
if debug {
|
||||
fmt.Println("✓ groth16 verification passed")
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
107
groth16/groth16_test.go
Normal file
107
groth16/groth16_test.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package groth16
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/arnaucube/go-snark/circuitcompiler"
|
||||
"github.com/arnaucube/go-snark/r1csqap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGroth16MinimalFlow(t *testing.T) {
|
||||
fmt.Println("testing Groth16 minimal flow")
|
||||
// circuit function
|
||||
// y = x^3 + x + 5
|
||||
code := `
|
||||
func main(private s0, public s1):
|
||||
s2 = s0 * s0
|
||||
s3 = s2 * s0
|
||||
s4 = s3 + s0
|
||||
s5 = s4 + 5
|
||||
equals(s1, s5)
|
||||
out = 1 * 1
|
||||
`
|
||||
fmt.Print("\ncode of the circuit:")
|
||||
|
||||
// parse the code
|
||||
parser := circuitcompiler.NewParser(strings.NewReader(code))
|
||||
circuit, err := parser.Parse()
|
||||
assert.Nil(t, err)
|
||||
|
||||
b3 := big.NewInt(int64(3))
|
||||
privateInputs := []*big.Int{b3}
|
||||
b35 := big.NewInt(int64(35))
|
||||
publicSignals := []*big.Int{b35}
|
||||
|
||||
// wittness
|
||||
w, err := circuit.CalculateWitness(privateInputs, publicSignals)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// code to R1CS
|
||||
fmt.Println("\ngenerating R1CS from code")
|
||||
a, b, c := circuit.GenerateR1CS()
|
||||
fmt.Println("\nR1CS:")
|
||||
fmt.Println("a:", a)
|
||||
fmt.Println("b:", b)
|
||||
fmt.Println("c:", c)
|
||||
|
||||
// R1CS to QAP
|
||||
// TODO zxQAP is not used and is an old impl, TODO remove
|
||||
alphas, betas, gammas, _ := Utils.PF.R1CSToQAP(a, b, c)
|
||||
fmt.Println("qap")
|
||||
assert.Equal(t, 8, len(alphas))
|
||||
assert.Equal(t, 8, len(alphas))
|
||||
assert.Equal(t, 8, len(alphas))
|
||||
assert.True(t, !bytes.Equal(alphas[1][1].Bytes(), big.NewInt(int64(0)).Bytes()))
|
||||
|
||||
ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||
assert.Equal(t, 7, len(ax))
|
||||
assert.Equal(t, 7, len(bx))
|
||||
assert.Equal(t, 7, len(cx))
|
||||
assert.Equal(t, 13, len(px))
|
||||
|
||||
// ---
|
||||
// from here is the GROTH16
|
||||
// ---
|
||||
// calculate trusted setup
|
||||
fmt.Println("groth")
|
||||
setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas)
|
||||
assert.Nil(t, err)
|
||||
fmt.Println("\nt:", setup.Toxic.T)
|
||||
|
||||
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z)
|
||||
div, rem := Utils.PF.Div(px, setup.Pk.Z)
|
||||
assert.Equal(t, hx, div)
|
||||
assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(6))
|
||||
|
||||
// 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)
|
||||
|
||||
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("\nsignals:", circuit.Signals)
|
||||
fmt.Println("witness:", w)
|
||||
b35Verif := big.NewInt(int64(35))
|
||||
publicSignalsVerif := []*big.Int{b35Verif}
|
||||
before := time.Now()
|
||||
assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
|
||||
fmt.Println("verify proof time elapsed:", time.Since(before))
|
||||
|
||||
// check that with another public input the verification returns false
|
||||
bOtherWrongPublic := big.NewInt(int64(34))
|
||||
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
|
||||
assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, false))
|
||||
}
|
||||
18
snark.go
18
snark.go
@@ -1,3 +1,5 @@
|
||||
// implementation of https://eprint.iacr.org/2013/879.pdf
|
||||
|
||||
package snark
|
||||
|
||||
import (
|
||||
@@ -289,7 +291,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
|
||||
pairingPiaVa := Utils.Bn.Pairing(proof.PiA, setup.Vk.Vka)
|
||||
pairingPiapG2 := Utils.Bn.Pairing(proof.PiAp, Utils.Bn.G2.G)
|
||||
if !Utils.Bn.Fq12.Equal(pairingPiaVa, pairingPiapG2) {
|
||||
fmt.Println("❌ e(piA, Va) == e(piA', g2), valid knowledge commitment for A")
|
||||
if debug {
|
||||
fmt.Println("❌ e(piA, Va) == e(piA', g2), valid knowledge commitment for A")
|
||||
}
|
||||
return false
|
||||
}
|
||||
if debug {
|
||||
@@ -300,7 +304,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
|
||||
pairingVbPib := Utils.Bn.Pairing(setup.Vk.Vkb, proof.PiB)
|
||||
pairingPibpG2 := Utils.Bn.Pairing(proof.PiBp, Utils.Bn.G2.G)
|
||||
if !Utils.Bn.Fq12.Equal(pairingVbPib, pairingPibpG2) {
|
||||
fmt.Println("❌ e(Vb, piB) == e(piB', g2), valid knowledge commitment for B")
|
||||
if debug {
|
||||
fmt.Println("❌ e(Vb, piB) == e(piB', g2), valid knowledge commitment for B")
|
||||
}
|
||||
return false
|
||||
}
|
||||
if debug {
|
||||
@@ -311,7 +317,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
|
||||
pairingPicVc := Utils.Bn.Pairing(proof.PiC, setup.Vk.Vkc)
|
||||
pairingPicpG2 := Utils.Bn.Pairing(proof.PiCp, Utils.Bn.G2.G)
|
||||
if !Utils.Bn.Fq12.Equal(pairingPicVc, pairingPicpG2) {
|
||||
fmt.Println("❌ e(piC, Vc) == e(piC', g2), valid knowledge commitment for C")
|
||||
if debug {
|
||||
fmt.Println("❌ e(piC, Vc) == e(piC', g2), valid knowledge commitment for C")
|
||||
}
|
||||
return false
|
||||
}
|
||||
if debug {
|
||||
@@ -330,7 +338,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
|
||||
Utils.Bn.Fq12.Mul(
|
||||
Utils.Bn.Pairing(proof.PiH, setup.Vk.Vkz),
|
||||
Utils.Bn.Pairing(proof.PiC, Utils.Bn.G2.G))) {
|
||||
fmt.Println("❌ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked")
|
||||
if debug {
|
||||
fmt.Println("❌ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked")
|
||||
}
|
||||
return false
|
||||
}
|
||||
if debug {
|
||||
|
||||
100
snark_test.go
100
snark_test.go
@@ -9,10 +9,104 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/arnaucube/go-snark/circuitcompiler"
|
||||
"github.com/arnaucube/go-snark/groth16"
|
||||
"github.com/arnaucube/go-snark/r1csqap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGroth16MinimalFlow(t *testing.T) {
|
||||
fmt.Println("testing Groth16 minimal flow")
|
||||
// circuit function
|
||||
// y = x^3 + x + 5
|
||||
code := `
|
||||
func main(private s0, public s1):
|
||||
s2 = s0 * s0
|
||||
s3 = s2 * s0
|
||||
s4 = s3 + s0
|
||||
s5 = s4 + 5
|
||||
equals(s1, s5)
|
||||
out = 1 * 1
|
||||
`
|
||||
fmt.Print("\ncode of the circuit:")
|
||||
|
||||
// parse the code
|
||||
parser := circuitcompiler.NewParser(strings.NewReader(code))
|
||||
circuit, err := parser.Parse()
|
||||
assert.Nil(t, err)
|
||||
|
||||
b3 := big.NewInt(int64(3))
|
||||
privateInputs := []*big.Int{b3}
|
||||
b35 := big.NewInt(int64(35))
|
||||
publicSignals := []*big.Int{b35}
|
||||
|
||||
// wittness
|
||||
w, err := circuit.CalculateWitness(privateInputs, publicSignals)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// code to R1CS
|
||||
fmt.Println("\ngenerating R1CS from code")
|
||||
a, b, c := circuit.GenerateR1CS()
|
||||
fmt.Println("\nR1CS:")
|
||||
fmt.Println("a:", a)
|
||||
fmt.Println("b:", b)
|
||||
fmt.Println("c:", c)
|
||||
|
||||
// R1CS to QAP
|
||||
// TODO zxQAP is not used and is an old impl, TODO remove
|
||||
alphas, betas, gammas, _ := Utils.PF.R1CSToQAP(a, b, c)
|
||||
fmt.Println("qap")
|
||||
assert.Equal(t, 8, len(alphas))
|
||||
assert.Equal(t, 8, len(alphas))
|
||||
assert.Equal(t, 8, len(alphas))
|
||||
assert.True(t, !bytes.Equal(alphas[1][1].Bytes(), big.NewInt(int64(0)).Bytes()))
|
||||
|
||||
ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||
assert.Equal(t, 7, len(ax))
|
||||
assert.Equal(t, 7, len(bx))
|
||||
assert.Equal(t, 7, len(cx))
|
||||
assert.Equal(t, 13, len(px))
|
||||
|
||||
// ---
|
||||
// from here is the GROTH16
|
||||
// ---
|
||||
// calculate trusted setup
|
||||
fmt.Println("groth")
|
||||
setup, err := groth16.GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas)
|
||||
assert.Nil(t, err)
|
||||
fmt.Println("\nt:", setup.Toxic.T)
|
||||
|
||||
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z)
|
||||
div, rem := Utils.PF.Div(px, setup.Pk.Z)
|
||||
assert.Equal(t, hx, div)
|
||||
assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(6))
|
||||
|
||||
// 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)
|
||||
|
||||
proof, err := groth16.GenerateProofs(*circuit, setup, w, px)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// fmt.Println("\n proofs:")
|
||||
// fmt.Println(proof)
|
||||
|
||||
// fmt.Println("public signals:", proof.PublicSignals)
|
||||
fmt.Println("\nsignals:", circuit.Signals)
|
||||
fmt.Println("witness:", w)
|
||||
b35Verif := big.NewInt(int64(35))
|
||||
publicSignalsVerif := []*big.Int{b35Verif}
|
||||
before := time.Now()
|
||||
assert.True(t, groth16.VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
|
||||
fmt.Println("verify proof time elapsed:", time.Since(before))
|
||||
|
||||
// check that with another public input the verification returns false
|
||||
bOtherWrongPublic := big.NewInt(int64(34))
|
||||
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
|
||||
assert.True(t, !groth16.VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, false))
|
||||
}
|
||||
|
||||
func TestZkFromFlatCircuitCode(t *testing.T) {
|
||||
// compile circuit and get the R1CS
|
||||
|
||||
@@ -145,7 +239,7 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
||||
// check that with another public input the verification returns false
|
||||
bOtherWrongPublic := big.NewInt(int64(34))
|
||||
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
|
||||
assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, true))
|
||||
assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, false))
|
||||
}
|
||||
|
||||
func TestZkMultiplication(t *testing.T) {
|
||||
@@ -253,7 +347,7 @@ func TestZkMultiplication(t *testing.T) {
|
||||
// check that with another public input the verification returns false
|
||||
bOtherWrongPublic := big.NewInt(int64(11))
|
||||
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
|
||||
assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, true))
|
||||
assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, false))
|
||||
}
|
||||
|
||||
func TestMinimalFlow(t *testing.T) {
|
||||
@@ -342,5 +436,5 @@ func TestMinimalFlow(t *testing.T) {
|
||||
// check that with another public input the verification returns false
|
||||
bOtherWrongPublic := big.NewInt(int64(34))
|
||||
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
|
||||
assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, true))
|
||||
assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, false))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user