diff --git a/README.md b/README.md index dbb979b..31fe644 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,14 @@ Current implementation status: - [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/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) - [![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: ```go // compile circuit and get the R1CS @@ -105,9 +105,9 @@ assert.Nil(t, err) assert.True(t, snark.VerifyProof(circuit, setup, proof)) ``` -#### CLI usage +### CLI usage -##### Compile circuit +#### Compile circuit Having a circuit file `test.circuit`: ``` func test(x): @@ -125,37 +125,37 @@ And a inputs file `inputs.json` In the command line, execute: ``` -> go-snark compile test.circuit +> go-snark-cli compile test.circuit ``` This will output the `compiledcircuit.json` file. -##### Trusted Setup +#### Trusted Setup 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`. -##### 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: ``` -> go-snark genproofs +> go-snark-cli genproofs ``` 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. ``` -> 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. -### Test +## Test ``` go test ./... -v ``` diff --git a/circuitcompiler/circuit.go b/circuitcompiler/circuit.go index 501364c..8c6d9f8 100644 --- a/circuitcompiler/circuit.go +++ b/circuitcompiler/circuit.go @@ -10,14 +10,15 @@ import ( // Circuit is the data structure of the compiled circuit 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 B [][]*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[0] = big.NewInt(int64(1)) for i, input := range inputs { - w[i+1] = input + w[i+2] = input } for _, constraint := range circ.Constraints { if constraint.Op == "in" { diff --git a/circuitcompiler/circuit_test.go b/circuitcompiler/circuit_test.go index 6f4e49d..3d882e0 100644 --- a/circuitcompiler/circuit_test.go +++ b/circuitcompiler/circuit_test.go @@ -50,14 +50,14 @@ func TestCircuitParser(t *testing.T) { b1 := big.NewInt(int64(1)) b5 := big.NewInt(int64(5)) 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, b1, b0, b0, b1, b0}, + []*big.Int{b0, b0, b1, b0, b1, b0}, []*big.Int{b5, b0, b0, b0, b0, b1}, } 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}, } @@ -65,7 +65,7 @@ func TestCircuitParser(t *testing.T) { []*big.Int{b0, b0, b0, b1, b0, b0}, []*big.Int{b0, b0, b0, b0, b1, b0}, []*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) diff --git a/circuitcompiler/parser.go b/circuitcompiler/parser.go index 584d511..73d126c 100644 --- a/circuitcompiler/parser.go +++ b/circuitcompiler/parser.go @@ -147,14 +147,16 @@ func (p *Parser) Parse() (*Circuit, error) { circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V2) } 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) { signalsCopy := copyArray(circuit.Signals) var auxSignals []string - auxSignals = append(auxSignals, signalsCopy[0:nInputs+1]...) + auxSignals = append(auxSignals, signalsCopy[0]) auxSignals = append(auxSignals, constraint.Out) - auxSignals = append(auxSignals, signalsCopy[nInputs+1:]...) + auxSignals = append(auxSignals, signalsCopy[1:]...) circuit.Signals = auxSignals + circuit.PublicSignals = append(circuit.PublicSignals, constraint.Out) + circuit.NPublic++ } } else { circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.Out) @@ -162,7 +164,6 @@ func (p *Parser) Parse() (*Circuit, error) { } circuit.NVars = len(circuit.Signals) circuit.NSignals = len(circuit.Signals) - circuit.NPublic = 0 return circuit, nil } func copyArray(in []string) []string { // tmp diff --git a/cli/go-snark-cli b/cli/go-snark-cli new file mode 100755 index 0000000..7798b74 Binary files /dev/null and b/cli/go-snark-cli differ diff --git a/cli/main.go b/cli/main.go index 8905a0c..6768620 100644 --- a/cli/main.go +++ b/cli/main.go @@ -62,8 +62,10 @@ func main() { func CompileCircuit(context *cli.Context) error { fmt.Println("cli") + circuitPath := context.Args().Get(0) + // read circuit file - circuitFile, err := os.Open("test.circuit") + circuitFile, err := os.Open(circuitPath) panicErr(err) // parse circuit code @@ -150,8 +152,16 @@ func CompileCircuit(context *cli.Context) error { jsonFile.Write(jsonData) jsonFile.Close() 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 - jsonData, err = json.Marshal(setup) + jsonData, err = json.Marshal(tsetup) panicErr(err) // store setup into file jsonFile, err = os.Create("trustedsetup.json") @@ -202,6 +212,7 @@ func GenerateProofs(context *cli.Context) error { fmt.Println("\n proofs:") fmt.Println(proof) + fmt.Println("public signals:", proof.PublicSignals) // store proofs to json jsonData, err := json.Marshal(proof) diff --git a/snark.go b/snark.go index fb54f1e..a4449e3 100644 --- a/snark.go +++ b/snark.go @@ -231,7 +231,7 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, hx []*big.Int, 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.PublicSignals = w[1 : circuit.NPublic+1] + proof.PublicSignals = w[1:2] // out signal return proof, nil } @@ -270,7 +270,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, prin // Vkx, to then calculate Vkx+piA 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])) } diff --git a/snark_test.go b/snark_test.go index c11c68f..ef53444 100644 --- a/snark_test.go +++ b/snark_test.go @@ -81,13 +81,13 @@ func TestZkFromFlatCircuitCode(t *testing.T) { fmt.Println("\n proofs:") fmt.Println(proof) + fmt.Println("public signals:", proof.PublicSignals) 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)) } func TestZkFromHardcodedR1CS(t *testing.T) { - b0 := big.NewInt(int64(0)) b1 := big.NewInt(int64(1)) b3 := big.NewInt(int64(3)) @@ -97,14 +97,14 @@ func TestZkFromHardcodedR1CS(t *testing.T) { b30 := big.NewInt(int64(30)) b35 := big.NewInt(int64(35)) 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, b1, b0, b0, b1, b0}, + []*big.Int{b0, b0, b1, b0, b1, b0}, []*big.Int{b5, b0, b0, b0, b0, b1}, } 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}, } @@ -112,15 +112,15 @@ func TestZkFromHardcodedR1CS(t *testing.T) { []*big.Int{b0, b0, b0, b1, b0, b0}, []*big.Int{b0, b0, b0, b0, b1, b0}, []*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) - // 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{ NVars: 6, - NPublic: 0, + NPublic: 1, NSignals: len(w), } ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)