Browse Source

circuit output in proof.PublicSignals for proof verification

pull/5/head
arnaucube 5 years ago
parent
commit
a7454213a0
8 changed files with 57 additions and 44 deletions
  1. +12
    -12
      README.md
  2. +10
    -9
      circuitcompiler/circuit.go
  3. +5
    -5
      circuitcompiler/circuit_test.go
  4. +5
    -4
      circuitcompiler/parser.go
  5. BIN
      cli/go-snark-cli
  6. +13
    -2
      cli/main.go
  7. +2
    -2
      snark.go
  8. +10
    -10
      snark_test.go

+ 12
- 12
README.md

@ -26,14 +26,14 @@ Current implementation status:
- [x] verify proofs with BN128 pairing - [x] verify proofs with BN128 pairing
### Usage
## 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?status.svg)](https://godoc.org/github.com/arnaucube/go-snark) zkSnark
- [![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/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/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) - [![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)
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler) Circuit Compiler - [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler) Circuit Compiler
#### Library usage
### Library usage
Example: Example:
```go ```go
// compile circuit and get the R1CS // compile circuit and get the R1CS
@ -105,9 +105,9 @@ assert.Nil(t, err)
assert.True(t, snark.VerifyProof(circuit, setup, proof)) assert.True(t, snark.VerifyProof(circuit, setup, proof))
``` ```
#### CLI usage
### CLI usage
##### Compile circuit
#### Compile circuit
Having a circuit file `test.circuit`: Having a circuit file `test.circuit`:
``` ```
func test(x): func test(x):
@ -125,37 +125,37 @@ And a inputs file `inputs.json`
In the command line, execute: In the command line, execute:
``` ```
> go-snark compile test.circuit
> go-snark-cli compile test.circuit
``` ```
This will output the `compiledcircuit.json` file. This will output the `compiledcircuit.json` file.
##### Trusted Setup
#### Trusted Setup
Having the `compiledcircuit.json`, now we can generate the `TrustedSetup`: Having the `compiledcircuit.json`, now we can generate the `TrustedSetup`:
``` ```
> go-snark trustedsetup compiledcircuit.json
> go-snark-cli trustedsetup
``` ```
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`. 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
#### Generate Proofs
Assumming that we have the `compiledcircuit.json` and the `trustedsetup.json`, we can now generate the `Proofs` with the following command: Assumming that we have the `compiledcircuit.json` and the `trustedsetup.json`, we can now generate the `Proofs` with the following command:
``` ```
> go-snark genproofs
> go-snark-cli genproofs
``` ```
This will store the file `proofs.json`, that contains all the SNARK proofs. This will store the file `proofs.json`, that contains all the SNARK proofs.
##### Verify 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. 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
> go-snark-cli verify
``` ```
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.
### Test
## Test
``` ```
go test ./... -v go test ./... -v
``` ```

+ 10
- 9
circuitcompiler/circuit.go

@ -10,14 +10,15 @@ import (
// Circuit is the data structure of the compiled circuit // Circuit is the data structure of the compiled circuit
type Circuit struct { type Circuit struct {
NVars int
NPublic int
NSignals int
Inputs []string
Signals []string
Witness []*big.Int
Constraints []Constraint
R1CS struct {
NVars int
NPublic int
NSignals int
Inputs []string
Signals []string
PublicSignals []string
Witness []*big.Int
Constraints []Constraint
R1CS struct {
A [][]*big.Int A [][]*big.Int
B [][]*big.Int B [][]*big.Int
C [][]*big.Int C [][]*big.Int
@ -151,7 +152,7 @@ func (circ *Circuit) CalculateWitness(inputs []*big.Int) ([]*big.Int, error) {
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 {
w[i+1] = input
w[i+2] = input
} }
for _, constraint := range circ.Constraints { for _, constraint := range circ.Constraints {
if constraint.Op == "in" { if constraint.Op == "in" {

+ 5
- 5
circuitcompiler/circuit_test.go

@ -50,14 +50,14 @@ func TestCircuitParser(t *testing.T) {
b1 := big.NewInt(int64(1)) b1 := big.NewInt(int64(1))
b5 := big.NewInt(int64(5)) b5 := big.NewInt(int64(5))
aExpected := [][]*big.Int{ aExpected := [][]*big.Int{
[]*big.Int{b0, b1, b0, b0, b0, b0},
[]*big.Int{b0, b0, b1, b0, b0, b0},
[]*big.Int{b0, b0, b0, b1, b0, b0}, []*big.Int{b0, b0, b0, b1, b0, b0},
[]*big.Int{b0, b1, b0, b0, b1, b0},
[]*big.Int{b0, b0, b1, b0, b1, b0},
[]*big.Int{b5, b0, b0, b0, b0, b1}, []*big.Int{b5, b0, b0, b0, b0, b1},
} }
bExpected := [][]*big.Int{ bExpected := [][]*big.Int{
[]*big.Int{b0, b1, b0, b0, b0, b0},
[]*big.Int{b0, b1, b0, b0, b0, b0},
[]*big.Int{b0, b0, b1, b0, b0, b0},
[]*big.Int{b0, b0, b1, b0, b0, b0},
[]*big.Int{b1, b0, b0, b0, b0, b0}, []*big.Int{b1, b0, b0, b0, b0, b0},
[]*big.Int{b1, b0, b0, b0, b0, b0}, []*big.Int{b1, b0, b0, b0, b0, b0},
} }
@ -65,7 +65,7 @@ func TestCircuitParser(t *testing.T) {
[]*big.Int{b0, b0, b0, b1, b0, b0}, []*big.Int{b0, b0, b0, b1, b0, b0},
[]*big.Int{b0, b0, b0, b0, b1, b0}, []*big.Int{b0, b0, b0, b0, b1, b0},
[]*big.Int{b0, b0, b0, b0, b0, b1}, []*big.Int{b0, b0, b0, b0, b0, b1},
[]*big.Int{b0, b0, b1, b0, b0, b0},
[]*big.Int{b0, b1, b0, b0, b0, b0},
} }
assert.Equal(t, aExpected, a) assert.Equal(t, aExpected, a)

+ 5
- 4
circuitcompiler/parser.go

@ -147,14 +147,16 @@ func (p *Parser) Parse() (*Circuit, error) {
circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V2) circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V2)
} }
if constraint.Out == "out" { if constraint.Out == "out" {
// if Out is "out", put it after the inputs
// if Out is "out", put it after first value (one) and before the inputs
if !existInArray(circuit.Signals, constraint.Out) { if !existInArray(circuit.Signals, constraint.Out) {
signalsCopy := copyArray(circuit.Signals) signalsCopy := copyArray(circuit.Signals)
var auxSignals []string var auxSignals []string
auxSignals = append(auxSignals, signalsCopy[0:nInputs+1]...)
auxSignals = append(auxSignals, signalsCopy[0])
auxSignals = append(auxSignals, constraint.Out) auxSignals = append(auxSignals, constraint.Out)
auxSignals = append(auxSignals, signalsCopy[nInputs+1:]...)
auxSignals = append(auxSignals, signalsCopy[1:]...)
circuit.Signals = auxSignals circuit.Signals = auxSignals
circuit.PublicSignals = append(circuit.PublicSignals, constraint.Out)
circuit.NPublic++
} }
} else { } else {
circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.Out) circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.Out)
@ -162,7 +164,6 @@ func (p *Parser) Parse() (*Circuit, error) {
} }
circuit.NVars = len(circuit.Signals) circuit.NVars = len(circuit.Signals)
circuit.NSignals = len(circuit.Signals) circuit.NSignals = len(circuit.Signals)
circuit.NPublic = 0
return circuit, nil return circuit, nil
} }
func copyArray(in []string) []string { // tmp func copyArray(in []string) []string { // tmp

BIN
cli/go-snark-cli


+ 13
- 2
cli/main.go

@ -62,8 +62,10 @@ func main() {
func CompileCircuit(context *cli.Context) error { func CompileCircuit(context *cli.Context) error {
fmt.Println("cli") fmt.Println("cli")
circuitPath := context.Args().Get(0)
// read circuit file // read circuit file
circuitFile, err := os.Open("test.circuit")
circuitFile, err := os.Open(circuitPath)
panicErr(err) panicErr(err)
// parse circuit code // parse circuit code
@ -150,8 +152,16 @@ func CompileCircuit(context *cli.Context) error {
jsonFile.Write(jsonData) jsonFile.Write(jsonData)
jsonFile.Close() jsonFile.Close()
fmt.Println("Compiled Circuit data written to ", jsonFile.Name()) fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
// remove setup.Toxic
var tsetup snark.Setup
tsetup.Pk = setup.Pk
tsetup.Vk = setup.Vk
tsetup.G1T = setup.G1T
tsetup.G2T = setup.G2T
// store setup to json // store setup to json
jsonData, err = json.Marshal(setup)
jsonData, err = json.Marshal(tsetup)
panicErr(err) panicErr(err)
// store setup into file // store setup into file
jsonFile, err = os.Create("trustedsetup.json") jsonFile, err = os.Create("trustedsetup.json")
@ -202,6 +212,7 @@ func GenerateProofs(context *cli.Context) error {
fmt.Println("\n proofs:") fmt.Println("\n proofs:")
fmt.Println(proof) fmt.Println(proof)
fmt.Println("public signals:", proof.PublicSignals)
// store proofs to json // store proofs to json
jsonData, err := json.Marshal(proof) jsonData, err := json.Marshal(proof)

+ 2
- 2
snark.go

@ -231,7 +231,7 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, hx []*big.Int,
for i := 0; i < len(hx); i++ { for i := 0; i < len(hx); i++ {
proof.PiH = Utils.Bn.G1.Add(proof.PiH, Utils.Bn.G1.MulScalar(setup.G1T[i], hx[i])) proof.PiH = Utils.Bn.G1.Add(proof.PiH, Utils.Bn.G1.MulScalar(setup.G1T[i], hx[i]))
} }
proof.PublicSignals = w[1 : circuit.NPublic+1]
proof.PublicSignals = w[1:2] // out signal
return proof, nil return proof, nil
} }
@ -270,7 +270,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, prin
// Vkx, to then calculate Vkx+piA // Vkx, to then calculate Vkx+piA
vkxpia := setup.Vk.A[0] vkxpia := setup.Vk.A[0]
for i := 0; i < circuit.NPublic; i++ {
for i := 0; i < len(proof.PublicSignals); i++ {
vkxpia = Utils.Bn.G1.Add(vkxpia, Utils.Bn.G1.MulScalar(setup.Vk.A[i+1], proof.PublicSignals[i])) vkxpia = Utils.Bn.G1.Add(vkxpia, Utils.Bn.G1.MulScalar(setup.Vk.A[i+1], proof.PublicSignals[i]))
} }

+ 10
- 10
snark_test.go

@ -81,13 +81,13 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
fmt.Println("\n proofs:") fmt.Println("\n proofs:")
fmt.Println(proof) fmt.Println(proof)
fmt.Println("public signals:", proof.PublicSignals)
before := time.Now() before := time.Now()
assert.True(t, VerifyProof(*circuit, setup, proof, false))
assert.True(t, VerifyProof(*circuit, setup, proof, true))
fmt.Println("verify proof time elapsed:", time.Since(before)) fmt.Println("verify proof time elapsed:", time.Since(before))
} }
func TestZkFromHardcodedR1CS(t *testing.T) { func TestZkFromHardcodedR1CS(t *testing.T) {
b0 := big.NewInt(int64(0)) b0 := big.NewInt(int64(0))
b1 := big.NewInt(int64(1)) b1 := big.NewInt(int64(1))
b3 := big.NewInt(int64(3)) b3 := big.NewInt(int64(3))
@ -97,14 +97,14 @@ func TestZkFromHardcodedR1CS(t *testing.T) {
b30 := big.NewInt(int64(30)) b30 := big.NewInt(int64(30))
b35 := big.NewInt(int64(35)) b35 := big.NewInt(int64(35))
a := [][]*big.Int{ a := [][]*big.Int{
[]*big.Int{b0, b1, b0, b0, b0, b0},
[]*big.Int{b0, b0, b1, b0, b0, b0},
[]*big.Int{b0, b0, b0, b1, b0, b0}, []*big.Int{b0, b0, b0, b1, b0, b0},
[]*big.Int{b0, b1, b0, b0, b1, b0},
[]*big.Int{b0, b0, b1, b0, b1, b0},
[]*big.Int{b5, b0, b0, b0, b0, b1}, []*big.Int{b5, b0, b0, b0, b0, b1},
} }
b := [][]*big.Int{ b := [][]*big.Int{
[]*big.Int{b0, b1, b0, b0, b0, b0},
[]*big.Int{b0, b1, b0, b0, b0, b0},
[]*big.Int{b0, b0, b1, b0, b0, b0},
[]*big.Int{b0, b0, b1, b0, b0, b0},
[]*big.Int{b1, b0, b0, b0, b0, b0}, []*big.Int{b1, b0, b0, b0, b0, b0},
[]*big.Int{b1, b0, b0, b0, b0, b0}, []*big.Int{b1, b0, b0, b0, b0, b0},
} }
@ -112,15 +112,15 @@ func TestZkFromHardcodedR1CS(t *testing.T) {
[]*big.Int{b0, b0, b0, b1, b0, b0}, []*big.Int{b0, b0, b0, b1, b0, b0},
[]*big.Int{b0, b0, b0, b0, b1, b0}, []*big.Int{b0, b0, b0, b0, b1, b0},
[]*big.Int{b0, b0, b0, b0, b0, b1}, []*big.Int{b0, b0, b0, b0, b0, b1},
[]*big.Int{b0, b0, b1, b0, b0, b0},
[]*big.Int{b0, b1, b0, b0, b0, b0},
} }
alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c) alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
// wittness = 1, 3, 35, 9, 27, 30
w := []*big.Int{b1, b3, b35, b9, b27, b30}
// wittness = 1, 35, 3, 9, 27, 30
w := []*big.Int{b1, b35, b3, b9, b27, b30}
circuit := circuitcompiler.Circuit{ circuit := circuitcompiler.Circuit{
NVars: 6, NVars: 6,
NPublic: 0,
NPublic: 1,
NSignals: len(w), NSignals: len(w),
} }
ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas) ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)

Loading…
Cancel
Save