From 5b77df54b7df9b16d20e2235523b87f007005f7a Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sun, 26 Apr 2020 21:20:41 +0200 Subject: [PATCH 1/2] Update proof sync.WaitGroup scooped variables & Add time prints in cli proof generation --- cli/cli.go | 7 +++++++ prover/prover.go | 40 ++++++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/cli/cli.go b/cli/cli.go index 816e510..2dd0258 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -5,6 +5,7 @@ import ( "flag" "fmt" "io/ioutil" + "time" "github.com/iden3/go-circom-prover-verifier/parsers" "github.com/iden3/go-circom-prover-verifier/prover" @@ -46,6 +47,8 @@ func main() { func cmdProve(provingKeyPath, witnessPath, proofPath, publicPath string) error { fmt.Println("zkSNARK Groth16 prover") + + fmt.Println("Reading proving key file:", provingKeyPath) provingKeyJson, err := ioutil.ReadFile(provingKeyPath) if err != nil { return err @@ -55,6 +58,7 @@ func cmdProve(provingKeyPath, witnessPath, proofPath, publicPath string) error { return err } + fmt.Println("Reading witness file:", witnessPath) witnessJson, err := ioutil.ReadFile(witnessPath) if err != nil { return err @@ -64,10 +68,13 @@ func cmdProve(provingKeyPath, witnessPath, proofPath, publicPath string) error { return err } + fmt.Println("Generating the proof") + beforeT := time.Now() proof, pubSignals, err := prover.GenerateProof(pk, w) if err != nil { return err } + fmt.Println("proof generation time elapsed:", time.Since(beforeT)) proofStr, err := parsers.ProofToJson(proof) if err != nil { diff --git a/prover/prover.go b/prover/prover.go index 8142167..a4c0d3b 100644 --- a/prover/prover.go +++ b/prover/prover.go @@ -73,39 +73,39 @@ func GenerateProof(pk *types.Pk, w types.Witness) (*types.Proof, []*big.Int, err proof.C = new(bn256.G1).ScalarBaseMult(big.NewInt(0)) proofBG1 := new(bn256.G1).ScalarBaseMult(big.NewInt(0)) - var waitGroup sync.WaitGroup - waitGroup.Add(4) - go func(wg *sync.WaitGroup) { + var wg sync.WaitGroup + wg.Add(4) + go func() { for i := 0; i < pk.NVars; i++ { proof.A = new(bn256.G1).Add(proof.A, new(bn256.G1).ScalarMult(pk.A[i], w[i])) } wg.Done() - }(&waitGroup) - go func(wg *sync.WaitGroup) { + }() + go func() { for i := 0; i < pk.NVars; i++ { proof.B = new(bn256.G2).Add(proof.B, new(bn256.G2).ScalarMult(pk.B2[i], w[i])) } wg.Done() - }(&waitGroup) - go func(wg *sync.WaitGroup) { + }() + go func() { for i := 0; i < pk.NVars; i++ { proofBG1 = new(bn256.G1).Add(proofBG1, new(bn256.G1).ScalarMult(pk.B1[i], w[i])) } wg.Done() - }(&waitGroup) - go func(wg *sync.WaitGroup) { + }() + go func() { for i := pk.NPublic + 1; i < pk.NVars; i++ { proof.C = new(bn256.G1).Add(proof.C, new(bn256.G1).ScalarMult(pk.C[i], w[i])) } wg.Done() - }(&waitGroup) - waitGroup.Wait() + }() + wg.Wait() h := calculateH(pk, w) - var waitGroup2 sync.WaitGroup - waitGroup2.Add(2) - go func(wg *sync.WaitGroup) { + var wg2 sync.WaitGroup + wg2.Add(2) + go func() { proof.A = new(bn256.G1).Add(proof.A, pk.VkAlpha1) proof.A = new(bn256.G1).Add(proof.A, new(bn256.G1).ScalarMult(pk.VkDelta1, r)) @@ -114,15 +114,15 @@ func GenerateProof(pk *types.Pk, w types.Witness) (*types.Proof, []*big.Int, err proofBG1 = new(bn256.G1).Add(proofBG1, pk.VkBeta1) proofBG1 = new(bn256.G1).Add(proofBG1, new(bn256.G1).ScalarMult(pk.VkDelta1, s)) - wg.Done() - }(&waitGroup2) - go func(wg *sync.WaitGroup) { + wg2.Done() + }() + go func() { for i := 0; i < len(h); i++ { proof.C = new(bn256.G1).Add(proof.C, new(bn256.G1).ScalarMult(pk.HExps[i], h[i])) } - wg.Done() - }(&waitGroup2) - waitGroup2.Wait() + wg2.Done() + }() + wg2.Wait() proof.C = new(bn256.G1).Add(proof.C, new(bn256.G1).ScalarMult(proof.A, s)) proof.C = new(bn256.G1).Add(proof.C, new(bn256.G1).ScalarMult(proofBG1, r)) From d3f43ce1a0b59d9eb3f66222104694bbe4cf50ba Mon Sep 17 00:00:00 2001 From: arnaucube Date: Sun, 26 Apr 2020 21:22:56 +0200 Subject: [PATCH 2/2] Refactor circuits, update prover & verifier tests --- .github/workflows/main.yml | 6 +- .gitignore | 2 +- compile-circuits.sh | 21 ---- prover/prover_test.go | 111 +++----------------- testdata/big/input.json | 1 - testdata/{big => circuit10k}/circuit.circom | 4 +- testdata/circuit10k/inputs.json | 1 + testdata/circuit1k/circuit.circom | 14 +++ testdata/circuit1k/inputs.json | 1 + testdata/circuit20k/circuit.circom | 14 +++ testdata/circuit20k/inputs.json | 1 + testdata/circuit5k/circuit.circom | 14 +++ testdata/circuit5k/inputs.json | 1 + testdata/clean-gereated-files.sh | 9 ++ testdata/compile-circuits.sh | 42 ++++++++ testdata/small/circuit.circom | 9 -- testdata/small/input.json | 1 - verifier/verifier_test.go | 22 ++-- 18 files changed, 133 insertions(+), 141 deletions(-) delete mode 100755 compile-circuits.sh delete mode 100644 testdata/big/input.json rename testdata/{big => circuit10k}/circuit.circom (69%) create mode 100644 testdata/circuit10k/inputs.json create mode 100644 testdata/circuit1k/circuit.circom create mode 100644 testdata/circuit1k/inputs.json create mode 100644 testdata/circuit20k/circuit.circom create mode 100644 testdata/circuit20k/inputs.json create mode 100644 testdata/circuit5k/circuit.circom create mode 100644 testdata/circuit5k/inputs.json create mode 100755 testdata/clean-gereated-files.sh create mode 100755 testdata/compile-circuits.sh delete mode 100644 testdata/small/circuit.circom delete mode 100644 testdata/small/input.json diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cc3850a..db19ea4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@v2 - name: Compile circuits and execute Go tests run: | - sh ./compile-circuits.sh - go run cli/cli.go -prove -provingkey=testdata/small/proving_key.json -witness=testdata/small/witness.json -proof=testdata/small/proof.json -public=testdata/small/public.json - go run cli/cli.go -prove -provingkey=testdata/big/proving_key.json -witness=testdata/big/witness.json -proof=testdata/big/proof.json -public=testdata/big/public.json + cd testdata && sh ./compile-circuits.sh && cd .. + go run cli/cli.go -prove -provingkey=testdata/circuit1k/proving_key.json -witness=testdata/circuit1k/witness.json -proof=testdata/circuit1k/proof.json -public=testdata/circuit1k/public.json + go run cli/cli.go -prove -provingkey=testdata/circuit5k/proving_key.json -witness=testdata/circuit5k/witness.json -proof=testdata/circuit5k/proof.json -public=testdata/circuit5k/public.json go test ./... diff --git a/.gitignore b/.gitignore index 3bd47b7..30ff9bd 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,5 @@ testdata/*/*.cpp testdata/*/*.sym testdata/*/*.r1cs testdata/*/*.sol -!testdata/*/input.json +!testdata/*/inputs.json cli/*.json diff --git a/compile-circuits.sh b/compile-circuits.sh deleted file mode 100755 index 405534a..0000000 --- a/compile-circuits.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -echo "testdata/small/circuit.circom" -cd testdata/small -echo "compiling circuit" -circom circuit.circom -r1cs --wasm --sym -echo "generating setup" -snarkjs setup -sed -i 's/null/["0","0","0"]/g' proving_key.json -echo "calculating witness" -snarkjs calculatewitness --wasm circuit.wasm --input input.json --witness witness.json - -echo "\ntestdata/big/circuit.circom" -cd ../big -echo "compiling circuit" -circom circuit.circom -r1cs --wasm --sym -echo "generating setup" -snarkjs setup -sed -i 's/null/["0","0","0"]/g' proving_key.json -echo "calculating witness" -snarkjs calculatewitness --wasm circuit.wasm --input input.json --witness witness.json diff --git a/prover/prover_test.go b/prover/prover_test.go index 7e9a5f4..386950f 100644 --- a/prover/prover_test.go +++ b/prover/prover_test.go @@ -4,65 +4,29 @@ import ( "encoding/json" "fmt" "io/ioutil" - "math/big" "testing" "time" "github.com/iden3/go-circom-prover-verifier/parsers" - "github.com/iden3/go-circom-prover-verifier/types" "github.com/iden3/go-circom-prover-verifier/verifier" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func TestSmallCircuitGenerateProof(t *testing.T) { - provingKeyJson, err := ioutil.ReadFile("../testdata/small/proving_key.json") - require.Nil(t, err) - pk, err := parsers.ParsePk(provingKeyJson) - require.Nil(t, err) - - witnessJson, err := ioutil.ReadFile("../testdata/small/witness.json") - require.Nil(t, err) - w, err := parsers.ParseWitness(witnessJson) - require.Nil(t, err) - - assert.Equal(t, types.Witness{big.NewInt(1), big.NewInt(33), big.NewInt(3), big.NewInt(11)}, w) - - beforeT := time.Now() - proof, pubSignals, err := GenerateProof(pk, w) - assert.Nil(t, err) - fmt.Println("proof generation time elapsed:", time.Since(beforeT)) - - proofStr, err := parsers.ProofToJson(proof) - assert.Nil(t, err) - - err = ioutil.WriteFile("../testdata/small/proof.json", proofStr, 0644) - assert.Nil(t, err) - publicStr, err := json.Marshal(parsers.ArrayBigIntToString(pubSignals)) - assert.Nil(t, err) - err = ioutil.WriteFile("../testdata/small/public.json", publicStr, 0644) - assert.Nil(t, err) - - // verify the proof - vkJson, err := ioutil.ReadFile("../testdata/small/verification_key.json") - require.Nil(t, err) - vk, err := parsers.ParseVk(vkJson) - require.Nil(t, err) - - v := verifier.Verify(vk, proof, pubSignals) - assert.True(t, v) - - // to verify the proof with snarkjs: - // snarkjs verify --vk testdata/small/verification_key.json -p testdata/small/proof.json --pub testdata/small/public.json +func TestCircuitsGenerateProof(t *testing.T) { + testCircuitGenerateProof(t, "circuit1k") // 1000 constraints + testCircuitGenerateProof(t, "circuit5k") // 5000 constraints + // testCircuitGenerateProof(t, "circuit10k") // 10000 constraints + // testCircuitGenerateProof(t, "circuit20k") // 20000 constraints } -func TestBigCircuitGenerateProof(t *testing.T) { - provingKeyJson, err := ioutil.ReadFile("../testdata/big/proving_key.json") +func testCircuitGenerateProof(t *testing.T, circuit string) { + provingKeyJson, err := ioutil.ReadFile("../testdata/" + circuit + "/proving_key.json") require.Nil(t, err) pk, err := parsers.ParsePk(provingKeyJson) require.Nil(t, err) - witnessJson, err := ioutil.ReadFile("../testdata/big/witness.json") + witnessJson, err := ioutil.ReadFile("../testdata/" + circuit + "/witness.json") require.Nil(t, err) w, err := parsers.ParseWitness(witnessJson) require.Nil(t, err) @@ -75,15 +39,15 @@ func TestBigCircuitGenerateProof(t *testing.T) { proofStr, err := parsers.ProofToJson(proof) assert.Nil(t, err) - err = ioutil.WriteFile("../testdata/big/proof.json", proofStr, 0644) + err = ioutil.WriteFile("../testdata/"+circuit+"/proof.json", proofStr, 0644) assert.Nil(t, err) publicStr, err := json.Marshal(parsers.ArrayBigIntToString(pubSignals)) assert.Nil(t, err) - err = ioutil.WriteFile("../testdata/big/public.json", publicStr, 0644) + err = ioutil.WriteFile("../testdata/"+circuit+"/public.json", publicStr, 0644) assert.Nil(t, err) // verify the proof - vkJson, err := ioutil.ReadFile("../testdata/big/verification_key.json") + vkJson, err := ioutil.ReadFile("../testdata/" + circuit + "/verification_key.json") require.Nil(t, err) vk, err := parsers.ParseVk(vkJson) require.Nil(t, err) @@ -92,62 +56,17 @@ func TestBigCircuitGenerateProof(t *testing.T) { assert.True(t, v) // to verify the proof with snarkjs: - // snarkjs verify --vk testdata/big/verification_key.json -p testdata/big/proof.json --pub testdata/big/public.json -} - -func TestIdStateCircuitGenerateProof(t *testing.T) { - // this test is to execute the proof generation for a bigger circuit - // (arround 22500 constraints) - // - // to see the time needed to execute this - // test Will need the ../testdata/idstate-circuit compiled & - // trustedsetup files (generated in - // https://github.com/iden3/go-zksnark-full-flow-example) - if false { - fmt.Println("\nTestIdStateCircuitGenerateProof activated") - provingKeyJson, err := ioutil.ReadFile("../testdata/idstate-circuit/proving_key.json") - require.Nil(t, err) - pk, err := parsers.ParsePk(provingKeyJson) - require.Nil(t, err) - - witnessJson, err := ioutil.ReadFile("../testdata/idstate-circuit/witness.json") - require.Nil(t, err) - w, err := parsers.ParseWitness(witnessJson) - require.Nil(t, err) - - beforeT := time.Now() - proof, pubSignals, err := GenerateProof(pk, w) - assert.Nil(t, err) - fmt.Println("proof generation time elapsed:", time.Since(beforeT)) - - proofStr, err := parsers.ProofToJson(proof) - assert.Nil(t, err) - - err = ioutil.WriteFile("../testdata/idstate-circuit/proof.json", proofStr, 0644) - assert.Nil(t, err) - publicStr, err := json.Marshal(parsers.ArrayBigIntToString(pubSignals)) - assert.Nil(t, err) - err = ioutil.WriteFile("../testdata/idstate-circuit/public.json", publicStr, 0644) - assert.Nil(t, err) - - // verify the proof - vkJson, err := ioutil.ReadFile("../testdata/idstate-circuit/verification_key.json") - require.Nil(t, err) - vk, err := parsers.ParseVk(vkJson) - require.Nil(t, err) - - v := verifier.Verify(vk, proof, pubSignals) - assert.True(t, v) - } + // snarkjs verify --vk testdata/circuitX/verification_key.json -p testdata/circuitX/proof.json --pub testdata/circuitX/public.json } func BenchmarkGenerateProof(b *testing.B) { - provingKeyJson, err := ioutil.ReadFile("../testdata/big/proving_key.json") + // benchmark with a circuit of 10000 constraints + provingKeyJson, err := ioutil.ReadFile("../testdata/circuit1/proving_key.json") require.Nil(b, err) pk, err := parsers.ParsePk(provingKeyJson) require.Nil(b, err) - witnessJson, err := ioutil.ReadFile("../testdata/big/witness.json") + witnessJson, err := ioutil.ReadFile("../testdata/circuit1/witness.json") require.Nil(b, err) w, err := parsers.ParseWitness(witnessJson) require.Nil(b, err) diff --git a/testdata/big/input.json b/testdata/big/input.json deleted file mode 100644 index fa95f40..0000000 --- a/testdata/big/input.json +++ /dev/null @@ -1 +0,0 @@ -{ "in": 1} diff --git a/testdata/big/circuit.circom b/testdata/circuit10k/circuit.circom similarity index 69% rename from testdata/big/circuit.circom rename to testdata/circuit10k/circuit.circom index 365dacf..39c637f 100644 --- a/testdata/big/circuit.circom +++ b/testdata/circuit10k/circuit.circom @@ -1,4 +1,4 @@ -template A(n) { +template TestConstraints(n) { signal input in; signal output out; @@ -11,4 +11,4 @@ template A(n) { out <== intermediate[n-1]; } -component main = A(1000); // bigger takes too much time on generating trusted setup +component main = TestConstraints(10000); diff --git a/testdata/circuit10k/inputs.json b/testdata/circuit10k/inputs.json new file mode 100644 index 0000000..d4d3fe7 --- /dev/null +++ b/testdata/circuit10k/inputs.json @@ -0,0 +1 @@ +{"in":"1"} diff --git a/testdata/circuit1k/circuit.circom b/testdata/circuit1k/circuit.circom new file mode 100644 index 0000000..5571bd1 --- /dev/null +++ b/testdata/circuit1k/circuit.circom @@ -0,0 +1,14 @@ +template TestConstraints(n) { + signal input in; + signal output out; + + signal intermediate[n]; + + intermediate[0] <== in; + for (var i=1; i