Browse Source

add Groth16 to cli

pull/10/head 0.0.3
arnaucube 4 years ago
parent
commit
f57599c091
3 changed files with 209 additions and 5 deletions
  1. +23
    -4
      README.md
  2. +186
    -1
      cli/main.go
  3. BIN
      go-snark-cli

+ 23
- 4
README.md

@ -5,14 +5,17 @@ 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
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark?status.svg)](https://godoc.org/github.com/arnaucube/go-snark) zkSnark
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/groth16?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/groth16) zkSnark Groth16
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/bn128?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/bn128) bn128 (more details: https://github.com/arnaucube/go-snark/tree/master/bn128)
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/fields?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/fields) Finite Fields operations
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/r1csqap?status.svg)](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
```

+ 186
- 1
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
}

BIN
go-snark-cli


Loading…
Cancel
Save