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
|
- `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
|
- `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
|
## 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.
|
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) :
|
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) :
|
||||||
1. compile circuuit
|
|
||||||
|
0. write circuit
|
||||||
|
1. compile circuit
|
||||||
2. generate trusted setup
|
2. generate trusted setup
|
||||||
3. calculate witness
|
3. calculate witness
|
||||||
4. generate proofs
|
4. generate proofs
|
||||||
@@ -35,12 +38,13 @@ Improvements from the minimal implementation:
|
|||||||
- [x] allow `import` in circuits language
|
- [x] allow `import` in circuits language
|
||||||
- [ ] allow `for` in circuits language
|
- [ ] allow `for` in circuits language
|
||||||
- [ ] move witness values calculation outside the setup phase
|
- [ ] move witness values calculation outside the setup phase
|
||||||
- [ ] Groth16
|
- [x] Groth16
|
||||||
- [ ] multiple optimizations
|
- [ ] multiple optimizations
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
- [](https://godoc.org/github.com/arnaucube/go-snark) zkSnark
|
- [](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/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/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)
|
- [](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.
|
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
|
### 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
|
## Test
|
||||||
```
|
```
|
||||||
|
|||||||
187
cli/main.go
187
cli/main.go
@@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
snark "github.com/arnaucube/go-snark"
|
snark "github.com/arnaucube/go-snark"
|
||||||
"github.com/arnaucube/go-snark/circuitcompiler"
|
"github.com/arnaucube/go-snark/circuitcompiler"
|
||||||
|
"github.com/arnaucube/go-snark/groth16"
|
||||||
"github.com/arnaucube/go-snark/r1csqap"
|
"github.com/arnaucube/go-snark/r1csqap"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
@@ -48,12 +49,37 @@ var commands = []cli.Command{
|
|||||||
Usage: "verify the snark proofs",
|
Usage: "verify the snark proofs",
|
||||||
Action: VerifyProofs,
|
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() {
|
func main() {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "go-snarks-cli"
|
app.Name = "go-snarks-cli"
|
||||||
app.Version = "0.0.1-alpha"
|
app.Version = "0.0.3-alpha"
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
cli.StringFlag{Name: "config"},
|
cli.StringFlag{Name: "config"},
|
||||||
}
|
}
|
||||||
@@ -322,3 +348,162 @@ func VerifyProofs(context *cli.Context) error {
|
|||||||
}
|
}
|
||||||
return nil
|
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