mirror of
https://github.com/arnaucube/go-snark-study.git
synced 2026-02-02 17:26:41 +01:00
add Groth16 to cli
This commit is contained in:
27
README.md
27
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
|
||||
- [](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
|
||||
}
|
||||
|
||||
BIN
go-snark-cli
BIN
go-snark-cli
Binary file not shown.
Reference in New Issue
Block a user