mirror of
https://github.com/arnaucube/go-snark-study.git
synced 2026-02-02 17:26:41 +01:00
cli
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1 +1,6 @@
|
|||||||
*.Backup
|
*.Backup
|
||||||
|
cli/compiledcircuit.json
|
||||||
|
cli/inputs.json
|
||||||
|
cli/proofs.json
|
||||||
|
cli/test.circuit
|
||||||
|
cli/trustedsetup.json
|
||||||
|
|||||||
51
README.md
51
README.md
@@ -33,6 +33,7 @@ Current implementation status:
|
|||||||
- [](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)
|
||||||
- [](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler) Circuit Compiler
|
- [](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler) Circuit Compiler
|
||||||
|
|
||||||
|
#### Library usage
|
||||||
Example:
|
Example:
|
||||||
```go
|
```go
|
||||||
// compile circuit and get the R1CS
|
// compile circuit and get the R1CS
|
||||||
@@ -104,6 +105,56 @@ assert.Nil(t, err)
|
|||||||
assert.True(t, snark.VerifyProof(circuit, setup, proof))
|
assert.True(t, snark.VerifyProof(circuit, setup, proof))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### CLI usage
|
||||||
|
|
||||||
|
##### Compile circuit
|
||||||
|
Having a circuit file `test.circuit`:
|
||||||
|
```
|
||||||
|
func test(x):
|
||||||
|
aux = x*x
|
||||||
|
y = aux*x
|
||||||
|
z = x + y
|
||||||
|
out = z + 5
|
||||||
|
```
|
||||||
|
And a inputs file `inputs.json`
|
||||||
|
```
|
||||||
|
[
|
||||||
|
3
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
In the command line, execute:
|
||||||
|
```
|
||||||
|
> go-snark compile test.circuit
|
||||||
|
```
|
||||||
|
|
||||||
|
This will output the `compiledcircuit.json` file.
|
||||||
|
|
||||||
|
##### Trusted Setup
|
||||||
|
Having the `compiledcircuit.json`, now we can generate the `TrustedSetup`:
|
||||||
|
```
|
||||||
|
> go-snark trustedsetup compiledcircuit.json
|
||||||
|
```
|
||||||
|
This will create the file `trustedsetup.json` with the TrustedSetup data, and also a `toxic.json` file, with the parameters to delete from the `Trusted Setup`.
|
||||||
|
|
||||||
|
|
||||||
|
##### Generate Proofs
|
||||||
|
Assumming that we have the `compiledcircuit.json` and the `trustedsetup.json`, we can now generate the `Proofs` with the following command:
|
||||||
|
```
|
||||||
|
> go-snark genproofs
|
||||||
|
```
|
||||||
|
|
||||||
|
This will store the file `proofs.json`, that contains all the SNARK proofs.
|
||||||
|
|
||||||
|
##### Verify Proofs
|
||||||
|
Having the `proofs.json`, `compiledcircuit.json`, `trustedsetup.json` files, we can now verify the `Pairings` of the proofs, in order to verify the proofs.
|
||||||
|
```
|
||||||
|
> go-snark verify
|
||||||
|
```
|
||||||
|
This will return a `true` if the proofs are verified, or a `false` if the proofs are not verified.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Test
|
### Test
|
||||||
```
|
```
|
||||||
go test ./... -v
|
go test ./... -v
|
||||||
|
|||||||
@@ -144,7 +144,10 @@ func grabVar(signals []string, w []*big.Int, vStr string) *big.Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CalculateWitness calculates the Witness of a Circuit based on the given inputs
|
// CalculateWitness calculates the Witness of a Circuit based on the given inputs
|
||||||
func (circ *Circuit) CalculateWitness(inputs []*big.Int) []*big.Int {
|
func (circ *Circuit) CalculateWitness(inputs []*big.Int) ([]*big.Int, error) {
|
||||||
|
if len(inputs) != len(circ.Inputs) {
|
||||||
|
return []*big.Int{}, errors.New("given inputs != circuit.Inputs")
|
||||||
|
}
|
||||||
w := r1csqap.ArrayOfBigZeros(len(circ.Signals))
|
w := r1csqap.ArrayOfBigZeros(len(circ.Signals))
|
||||||
w[0] = big.NewInt(int64(1))
|
w[0] = big.NewInt(int64(1))
|
||||||
for i, input := range inputs {
|
for i, input := range inputs {
|
||||||
@@ -162,5 +165,5 @@ func (circ *Circuit) CalculateWitness(inputs []*big.Int) []*big.Int {
|
|||||||
w[indexInArray(circ.Signals, constraint.Out)] = new(big.Int).Div(grabVar(circ.Signals, w, constraint.V1), grabVar(circ.Signals, w, constraint.V2))
|
w[indexInArray(circ.Signals, constraint.Out)] = new(big.Int).Div(grabVar(circ.Signals, w, constraint.V1), grabVar(circ.Signals, w, constraint.V2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return w
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ func TestCircuitParser(t *testing.T) {
|
|||||||
b3 := big.NewInt(int64(3))
|
b3 := big.NewInt(int64(3))
|
||||||
inputs := []*big.Int{b3}
|
inputs := []*big.Int{b3}
|
||||||
// Calculate Witness
|
// Calculate Witness
|
||||||
w := circuit.CalculateWitness(inputs)
|
w, err := circuit.CalculateWitness(inputs)
|
||||||
|
assert.Nil(t, err)
|
||||||
fmt.Println("w", w)
|
fmt.Println("w", w)
|
||||||
}
|
}
|
||||||
|
|||||||
248
cli/main.go
Normal file
248
cli/main.go
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
snark "github.com/arnaucube/go-snark"
|
||||||
|
"github.com/arnaucube/go-snark/circuitcompiler"
|
||||||
|
"github.com/arnaucube/go-snark/r1csqap"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func panicErr(err error) {
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var commands = []cli.Command{
|
||||||
|
{
|
||||||
|
Name: "compile",
|
||||||
|
Aliases: []string{},
|
||||||
|
Usage: "compile a circuit",
|
||||||
|
Action: CompileCircuit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "genproofs",
|
||||||
|
Aliases: []string{},
|
||||||
|
Usage: "generate the snark proofs",
|
||||||
|
Action: GenerateProofs,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "verify",
|
||||||
|
Aliases: []string{},
|
||||||
|
Usage: "verify the snark proofs",
|
||||||
|
Action: VerifyProofs,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := cli.NewApp()
|
||||||
|
app.Name = "go-snarks-cli"
|
||||||
|
app.Version = "0.1.0-alpha"
|
||||||
|
app.Flags = []cli.Flag{
|
||||||
|
cli.StringFlag{Name: "config"},
|
||||||
|
}
|
||||||
|
app.Commands = commands
|
||||||
|
|
||||||
|
err := app.Run(os.Args)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CompileCircuit(context *cli.Context) error {
|
||||||
|
fmt.Println("cli")
|
||||||
|
|
||||||
|
// read circuit file
|
||||||
|
circuitFile, err := os.Open("test.circuit")
|
||||||
|
panicErr(err)
|
||||||
|
|
||||||
|
// parse circuit code
|
||||||
|
parser := circuitcompiler.NewParser(bufio.NewReader(circuitFile))
|
||||||
|
circuit, err := parser.Parse()
|
||||||
|
panicErr(err)
|
||||||
|
fmt.Println("\ncircuit data:", circuit)
|
||||||
|
|
||||||
|
// read inputs file
|
||||||
|
inputsFile, err := ioutil.ReadFile("inputs.json")
|
||||||
|
panicErr(err)
|
||||||
|
|
||||||
|
// parse inputs from inputsFile
|
||||||
|
var inputs []*big.Int
|
||||||
|
json.Unmarshal([]byte(string(inputsFile)), &inputs)
|
||||||
|
panicErr(err)
|
||||||
|
|
||||||
|
// calculate wittness
|
||||||
|
w, err := circuit.CalculateWitness(inputs)
|
||||||
|
panicErr(err)
|
||||||
|
fmt.Println("\nwitness", w)
|
||||||
|
|
||||||
|
// flat code to R1CS
|
||||||
|
fmt.Println("\ngenerating R1CS from flat code")
|
||||||
|
a, b, c := circuit.GenerateR1CS()
|
||||||
|
fmt.Println("\nR1CS:")
|
||||||
|
fmt.Println("a:", a)
|
||||||
|
fmt.Println("b:", b)
|
||||||
|
fmt.Println("c:", c)
|
||||||
|
|
||||||
|
// R1CS to QAP
|
||||||
|
alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
|
||||||
|
fmt.Println("qap")
|
||||||
|
fmt.Println(alphas)
|
||||||
|
fmt.Println(betas)
|
||||||
|
fmt.Println(gammas)
|
||||||
|
|
||||||
|
ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||||
|
|
||||||
|
hx := snark.Utils.PF.DivisorPolynomial(px, zx)
|
||||||
|
|
||||||
|
// hx==px/zx so px==hx*zx
|
||||||
|
// assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
|
||||||
|
if !r1csqap.BigArraysEqual(px, snark.Utils.PF.Mul(hx, zx)) {
|
||||||
|
panic(errors.New("px != hx*zx"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
|
||||||
|
abc := snark.Utils.PF.Sub(snark.Utils.PF.Mul(ax, bx), cx)
|
||||||
|
// assert.Equal(t, abc, px)
|
||||||
|
if !r1csqap.BigArraysEqual(abc, px) {
|
||||||
|
panic(errors.New("abc != px"))
|
||||||
|
}
|
||||||
|
hz := snark.Utils.PF.Mul(hx, zx)
|
||||||
|
if !r1csqap.BigArraysEqual(abc, hz) {
|
||||||
|
panic(errors.New("abc != hz"))
|
||||||
|
}
|
||||||
|
// assert.Equal(t, abc, hz)
|
||||||
|
|
||||||
|
div, rem := snark.Utils.PF.Div(px, zx)
|
||||||
|
if !r1csqap.BigArraysEqual(hx, div) {
|
||||||
|
panic(errors.New("hx != div"))
|
||||||
|
}
|
||||||
|
// assert.Equal(t, hx, div)
|
||||||
|
// assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
|
||||||
|
for _, r := range rem {
|
||||||
|
if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) {
|
||||||
|
panic(errors.New("error:error: px/zx rem not equal to zeros"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate trusted setup
|
||||||
|
setup, err := snark.GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx)
|
||||||
|
panicErr(err)
|
||||||
|
fmt.Println("\nt:", setup.Toxic.T)
|
||||||
|
|
||||||
|
// store circuit to json
|
||||||
|
jsonData, err := json.Marshal(circuit)
|
||||||
|
panicErr(err)
|
||||||
|
// store setup into file
|
||||||
|
jsonFile, err := os.Create("compiledcircuit.json")
|
||||||
|
panicErr(err)
|
||||||
|
defer jsonFile.Close()
|
||||||
|
jsonFile.Write(jsonData)
|
||||||
|
jsonFile.Close()
|
||||||
|
fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
|
||||||
|
// store setup to json
|
||||||
|
jsonData, err = json.Marshal(setup)
|
||||||
|
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 GenerateProofs(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 snark.Setup
|
||||||
|
json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
|
||||||
|
panicErr(err)
|
||||||
|
|
||||||
|
// read inputs file
|
||||||
|
inputsFile, err := ioutil.ReadFile("inputs.json")
|
||||||
|
panicErr(err)
|
||||||
|
// parse inputs from inputsFile
|
||||||
|
var inputs []*big.Int
|
||||||
|
json.Unmarshal([]byte(string(inputsFile)), &inputs)
|
||||||
|
panicErr(err)
|
||||||
|
// calculate wittness
|
||||||
|
w, err := circuit.CalculateWitness(inputs)
|
||||||
|
panicErr(err)
|
||||||
|
fmt.Println("\nwitness", w)
|
||||||
|
|
||||||
|
// flat code to R1CS
|
||||||
|
a, b, c := circuit.GenerateR1CS()
|
||||||
|
// R1CS to QAP
|
||||||
|
alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
|
||||||
|
_, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||||
|
hx := snark.Utils.PF.DivisorPolynomial(px, zx)
|
||||||
|
|
||||||
|
proof, err := snark.GenerateProofs(circuit, trustedsetup, hx, w)
|
||||||
|
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 VerifyProofs(context *cli.Context) error {
|
||||||
|
// open proofs.json
|
||||||
|
proofsFile, err := ioutil.ReadFile("proofs.json")
|
||||||
|
panicErr(err)
|
||||||
|
var proof snark.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 snark.Setup
|
||||||
|
json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
|
||||||
|
panicErr(err)
|
||||||
|
|
||||||
|
verified := snark.VerifyProof(circuit, trustedsetup, proof, true)
|
||||||
|
if !verified {
|
||||||
|
fmt.Println("ERROR: proofs not verified")
|
||||||
|
} else {
|
||||||
|
fmt.Println("Proofs verified")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -143,10 +143,13 @@ func BigIsOdd(n *big.Int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fq12 Fq12) Exp(base [2][3][2]*big.Int, e *big.Int) [2][3][2]*big.Int {
|
func (fq12 Fq12) Exp(base [2][3][2]*big.Int, e *big.Int) [2][3][2]*big.Int {
|
||||||
|
// TODO fix bottleneck
|
||||||
|
|
||||||
res := fq12.One()
|
res := fq12.One()
|
||||||
rem := fq12.Fq2.F.Copy(e)
|
rem := fq12.Fq2.F.Copy(e)
|
||||||
exp := base
|
exp := base
|
||||||
|
|
||||||
|
// before := time.Now()
|
||||||
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
|
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
|
||||||
if BigIsOdd(rem) {
|
if BigIsOdd(rem) {
|
||||||
res = fq12.Mul(res, exp)
|
res = fq12.Mul(res, exp)
|
||||||
@@ -154,6 +157,7 @@ func (fq12 Fq12) Exp(base [2][3][2]*big.Int, e *big.Int) [2][3][2]*big.Int {
|
|||||||
exp = fq12.Square(exp)
|
exp = fq12.Square(exp)
|
||||||
rem = new(big.Int).Rsh(rem, 1)
|
rem = new(big.Int).Rsh(rem, 1)
|
||||||
}
|
}
|
||||||
|
// fmt.Println("time elapsed:", time.Since(before))
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
func (fq12 Fq12) Affine(a [2][3][2]*big.Int) [2][3][2]*big.Int {
|
func (fq12 Fq12) Affine(a [2][3][2]*big.Int) [2][3][2]*big.Int {
|
||||||
|
|||||||
1
go.mod
1
go.mod
@@ -4,4 +4,5 @@ require (
|
|||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/stretchr/testify v1.2.2
|
github.com/stretchr/testify v1.2.2
|
||||||
|
github.com/urfave/cli v1.20.0
|
||||||
)
|
)
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -4,3 +4,5 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||||
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package r1csqap
|
package r1csqap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/arnaucube/go-snark/fields"
|
"github.com/arnaucube/go-snark/fields"
|
||||||
@@ -28,6 +29,17 @@ func ArrayOfBigZeros(num int) []*big.Int {
|
|||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
func BigArraysEqual(a, b []*big.Int) bool {
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < len(a); i++ {
|
||||||
|
if !bytes.Equal(a[i].Bytes(), b[i].Bytes()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// PolynomialField is the Polynomial over a Finite Field where the polynomial operations are performed
|
// PolynomialField is the Polynomial over a Finite Field where the polynomial operations are performed
|
||||||
type PolynomialField struct {
|
type PolynomialField struct {
|
||||||
|
|||||||
22
snark.go
22
snark.go
@@ -237,14 +237,16 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, hx []*big.Int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VerifyProof verifies over the BN128 the Pairings of the Proof
|
// VerifyProof verifies over the BN128 the Pairings of the Proof
|
||||||
func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool {
|
func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, printVer 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, setup.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) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
fmt.Println("✓ e(piA, Va) == e(piA', g2), valid knowledge commitment for A")
|
if printVer {
|
||||||
|
fmt.Println("✓ e(piA, Va) == e(piA', g2), valid knowledge commitment for A")
|
||||||
|
}
|
||||||
|
|
||||||
// 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(setup.Vk.Vkb, proof.PiB)
|
||||||
@@ -252,7 +254,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool
|
|||||||
if !Utils.Bn.Fq12.Equal(pairingVbPib, pairingPibpG2) {
|
if !Utils.Bn.Fq12.Equal(pairingVbPib, pairingPibpG2) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
fmt.Println("✓ e(Vb, piB) == e(piB', g2), valid knowledge commitment for B")
|
if printVer {
|
||||||
|
fmt.Println("✓ e(Vb, piB) == e(piB', g2), valid knowledge commitment for B")
|
||||||
|
}
|
||||||
|
|
||||||
// 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, setup.Vk.Vkc)
|
||||||
@@ -260,7 +264,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool
|
|||||||
if !Utils.Bn.Fq12.Equal(pairingPicVc, pairingPicpG2) {
|
if !Utils.Bn.Fq12.Equal(pairingPicVc, pairingPicpG2) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
fmt.Println("✓ e(piC, Vc) == e(piC', g2), valid knowledge commitment for C")
|
if printVer {
|
||||||
|
fmt.Println("✓ e(piC, Vc) == e(piC', g2), valid knowledge commitment for C")
|
||||||
|
}
|
||||||
|
|
||||||
// Vkx, to then calculate Vkx+piA
|
// Vkx, to then calculate Vkx+piA
|
||||||
vkxpia := setup.Vk.A[0]
|
vkxpia := setup.Vk.A[0]
|
||||||
@@ -276,7 +282,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool
|
|||||||
Utils.Bn.Pairing(proof.PiC, Utils.Bn.G2.G))) {
|
Utils.Bn.Pairing(proof.PiC, Utils.Bn.G2.G))) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
fmt.Println("✓ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked")
|
if printVer {
|
||||||
|
fmt.Println("✓ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked")
|
||||||
|
}
|
||||||
|
|
||||||
// e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB)
|
// e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB)
|
||||||
// == e(piK, g2Kgamma)
|
// == e(piK, g2Kgamma)
|
||||||
@@ -288,7 +296,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool
|
|||||||
if !Utils.Bn.Fq12.Equal(pairingL, pairingR) {
|
if !Utils.Bn.Fq12.Equal(pairingL, pairingR) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
fmt.Println("✓ e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) == e(piK, g2Kgamma)")
|
if printVer {
|
||||||
|
fmt.Println("✓ e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) == e(piK, g2Kgamma)")
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
|||||||
b3 := big.NewInt(int64(3))
|
b3 := big.NewInt(int64(3))
|
||||||
inputs := []*big.Int{b3}
|
inputs := []*big.Int{b3}
|
||||||
// wittness
|
// wittness
|
||||||
w := circuit.CalculateWitness(inputs)
|
w, err := circuit.CalculateWitness(inputs)
|
||||||
|
assert.Nil(t, err)
|
||||||
fmt.Println("\nwitness", w)
|
fmt.Println("\nwitness", w)
|
||||||
|
|
||||||
// flat code to R1CS
|
// flat code to R1CS
|
||||||
@@ -81,7 +82,7 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
|||||||
fmt.Println("\n proofs:")
|
fmt.Println("\n proofs:")
|
||||||
fmt.Println(proof)
|
fmt.Println(proof)
|
||||||
before := time.Now()
|
before := time.Now()
|
||||||
assert.True(t, VerifyProof(*circuit, setup, proof))
|
assert.True(t, VerifyProof(*circuit, setup, proof, false))
|
||||||
fmt.Println("verify proof time elapsed:", time.Since(before))
|
fmt.Println("verify proof time elapsed:", time.Since(before))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,11 +143,64 @@ func TestZkFromHardcodedR1CS(t *testing.T) {
|
|||||||
// calculate trusted setup
|
// calculate trusted setup
|
||||||
setup, err := GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas, zx)
|
setup, err := GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas, zx)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
fmt.Println("t", setup.Toxic.T)
|
|
||||||
|
|
||||||
// piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
|
// piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
|
||||||
proof, err := GenerateProofs(circuit, setup, hx, w)
|
proof, err := GenerateProofs(circuit, setup, hx, w)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
assert.True(t, VerifyProof(circuit, setup, proof))
|
assert.True(t, VerifyProof(circuit, setup, proof, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestZkMultiplication(t *testing.T) {
|
||||||
|
|
||||||
|
// compile circuit and get the R1CS
|
||||||
|
flatCode := `
|
||||||
|
func test(a, b):
|
||||||
|
out = a * b
|
||||||
|
`
|
||||||
|
|
||||||
|
// parse the code
|
||||||
|
parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
|
||||||
|
circuit, err := parser.Parse()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
b3 := big.NewInt(int64(3))
|
||||||
|
b4 := big.NewInt(int64(4))
|
||||||
|
inputs := []*big.Int{b3, b4}
|
||||||
|
// wittness
|
||||||
|
w, err := circuit.CalculateWitness(inputs)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
// flat code to R1CS
|
||||||
|
a, b, c := circuit.GenerateR1CS()
|
||||||
|
|
||||||
|
// R1CS to QAP
|
||||||
|
alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
|
||||||
|
|
||||||
|
ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||||
|
|
||||||
|
hx := Utils.PF.DivisorPolynomial(px, zx)
|
||||||
|
|
||||||
|
// hx==px/zx so px==hx*zx
|
||||||
|
assert.Equal(t, px, Utils.PF.Mul(hx, zx))
|
||||||
|
|
||||||
|
// p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
|
||||||
|
abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
|
||||||
|
assert.Equal(t, abc, px)
|
||||||
|
hz := Utils.PF.Mul(hx, zx)
|
||||||
|
assert.Equal(t, abc, hz)
|
||||||
|
|
||||||
|
div, rem := Utils.PF.Div(px, zx)
|
||||||
|
assert.Equal(t, hx, div)
|
||||||
|
assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(1))
|
||||||
|
|
||||||
|
// calculate trusted setup
|
||||||
|
setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
// piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
|
||||||
|
proof, err := GenerateProofs(*circuit, setup, hx, w)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.True(t, VerifyProof(*circuit, setup, proof, false))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user