diff --git a/book/perf/mbp/crop.md b/book/perf/mbp/crop.md index 1f127b1..5b14c7b 100644 --- a/book/perf/mbp/crop.md +++ b/book/perf/mbp/crop.md @@ -1,8 +1,13 @@ ## Crop -| Original Size | Final Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | -|---|---|---|---|---| -| 1000x1000 | 10x10 | 0.958040 | 16.992575 | 164 | -| 1000x1000 | 100x100 | 0.935300 | 21.655094 | 164 | -| 1000x1000 | 250x250 | 1.041068 | 33.970356 | 164 | -| 1000x1000 | 500x500 | 1.775267 | 65.551002 | 164 | -| 1000x1000 | 750x750 | 2.288349 | 111.907515 | 164 | +| Original Size | Final Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend | +|---|---|---|---|---|---| +| 1000x1000 | 10x10 | 0.833237 | 15.970879 | 164 | groth16 | +| 1000x1000 | 100x100 | 0.807472 | 19.188925 | 164 | groth16 | +| 1000x1000 | 250x250 | 0.885950 | 31.114879 | 164 | groth16 | +| 1000x1000 | 500x500 | 1.166375 | 58.741483 | 164 | groth16 | +| 1000x1000 | 750x750 | 1.584546 | 103.079183 | 164 | groth16 | +| 1000x1000 | 10x10 | 0.790772 | 1.330478 | 552 | plonk | +| 1000x1000 | 100x100 | 0.745351 | 6.189850 | 552 | plonk | +| 1000x1000 | 250x250 | 0.826726 | 47.114148 | 552 | plonk | +| 1000x1000 | 500x500 | 1.086315 | 204.406259 | 552 | plonk | +| 1000x1000 | 750x750 | 2.057538 | 420.913409 | 552 | plonk | diff --git a/book/perf/mbp/flip-horizontal.md b/book/perf/mbp/flip-horizontal.md index b73e650..b7a8fa6 100644 --- a/book/perf/mbp/flip-horizontal.md +++ b/book/perf/mbp/flip-horizontal.md @@ -1,8 +1,13 @@ ## Flip horizontal -| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | -|---|---|---|---| -| 10x10 | 0.001320 | 0.030627 | 164 | -| 100x100 | 0.078610 | 1.834790 | 164 | -| 250x250 | 0.238217 | 11.219355 | 164 | -| 500x500 | 0.600707 | 45.394261 | 164 | -| 750x750 | 1.425706 | 102.858330 | 164 | +| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend | +|---|---|---|---|---| +| 10x10 | 0.000339 | 0.032807 | 164 | groth16 | +| 100x100 | 0.025165 | 1.779391 | 164 | groth16 | +| 250x250 | 0.151705 | 11.252345 | 164 | groth16 | +| 500x500 | 0.573539 | 44.454817 | 164 | groth16 | +| 750x750 | 1.286226 | 97.416250 | 164 | groth16 | +| 10x10 | 0.000364 | 0.209765 | 552 | plonk | +| 100x100 | 0.024890 | 5.139028 | 552 | plonk | +| 250x250 | 0.129589 | 45.555273 | 552 | plonk | +| 500x500 | 0.529516 | 196.448008 | 552 | plonk | +| 750x750 | 1.277747 | 418.509681 | 552 | plonk | diff --git a/book/perf/mbp/flip-vertical.md b/book/perf/mbp/flip-vertical.md index fc9a45b..3a6b877 100644 --- a/book/perf/mbp/flip-vertical.md +++ b/book/perf/mbp/flip-vertical.md @@ -1,7 +1,13 @@ ## Flip vertical -| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | -|---|---|---|---| -| 10x10 | 0.000803 | 0.032929 | 164 | -| 100x100 | 0.032572 | 1.919375 | 164 | -| 250x250 | 0.189386 | 11.282747 | 164 | -| 500x500 | 0.615048 | 45.408805 | 164 | +| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend | +|---|---|---|---|---| +| 10x10 | 0.000438 | 0.032108 | 164 | groth16 | +| 100x100 | 0.025263 | 1.780565 | 164 | groth16 | +| 250x250 | 0.151733 | 11.315902 | 164 | groth16 | +| 500x500 | 0.577561 | 44.370405 | 164 | groth16 | +| 750x750 | 1.271395 | 98.629211 | 164 | groth16 | +| 10x10 | 0.000337 | 0.212584 | 552 | plonk | +| 100x100 | 0.023697 | 5.108784 | 552 | plonk | +| 250x250 | 0.128550 | 46.555842 | 552 | plonk | +| 500x500 | 0.516148 | 196.040625 | 552 | plonk | +| 750x750 | 1.302722 | 423.434726 | 552 | plonk | diff --git a/book/perf/mbp/rotate180.md b/book/perf/mbp/rotate180.md index 4a4cf3b..034244b 100644 --- a/book/perf/mbp/rotate180.md +++ b/book/perf/mbp/rotate180.md @@ -1,8 +1,13 @@ ## Rotate 180 -| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | -|---|---|---|---| -| 10x10 | 0.000402 | 0.002164 | 164 | -| 100x100 | 0.025682 | 0.057075 | 164 | -| 250x250 | 0.160375 | 0.404695 | 164 | -| 500x500 | 0.639341 | 1.382990 | 164 | -| 750x750 | 1.454608 | 2.622660 | 164 | +| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend | +|---|---|---|---|---| +| 10x10 | 0.000377 | 0.032683 | 164 | groth16| +| 100x100 | 0.025277 | 1.788267 | 164 | groth16| +| 250x250 | 0.153462 | 11.111391 | 164 | groth16| +| 500x500 | 0.580021 | 45.384939 | 164 | groth16| +| 750x750 | 1.331276 | 94.734796 | 164 | groth16| +| 10x10 | 0.000338 | 0.199782 | 552 | plonk| +| 100x100 | 0.022096 | 5.186410 | 552 | plonk| +| 250x250 | 0.130622 | 45.474365 | 552 | plonk| +| 500x500 | 0.513307 | 194.285966 | 552 | plonk| +| 750x750 | 1.142496 | 425.788482 | 552 | plonk| diff --git a/book/perf/mbp/rotate270.md b/book/perf/mbp/rotate270.md index a2a1863..756aa81 100644 --- a/book/perf/mbp/rotate270.md +++ b/book/perf/mbp/rotate270.md @@ -1,8 +1,13 @@ ## Rotate 270 -| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | -|---|---|---|---| -| 10x10 | 0.000381 | 0.043469 | 164 | -| 100x100 | 0.027019 | 2.001985 | 164 | -| 250x250 | 0.163741 | 11.755546 | 164 | -| 500x500 | 0.638988 | 52.032664 | 164 | -| 750x750 | 1.689164 | 104.419625 | 164 | +| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend | +|---|---|---|---|---| +| 10x10 | 0.000451 | 0.033596 | 164 | groth16 | +| 100x100 | 0.025271 | 1.744991 | 164 | groth16 | +| 250x250 | 0.151591 | 11.086174 | 164 | groth16 | +| 500x500 | 0.594607 | 43.656017 | 164 | groth16 | +| 750x750 | 1.334827 | 96.234792 | 164 | groth16 | +| 10x10 | 0.000254 | 0.205031 | 552 | plonk | +| 100x100 | 0.020022 | 5.238268 | 552 | plonk | +| 250x250 | 0.131477 | 45.467208 | 552 | plonk | +| 500x500 | 0.511738 | 194.538589 | 552 | plonk | +| 750x750 | 1.168737 | 409.672420 | 552 | plonk | diff --git a/book/perf/mbp/rotate90.md b/book/perf/mbp/rotate90.md index 841e9c3..acf563e 100644 --- a/book/perf/mbp/rotate90.md +++ b/book/perf/mbp/rotate90.md @@ -1,8 +1,13 @@ ## Rotate 90 -| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | -|---|---|---|---| -| 10x10 | 0.000647 | 0.036080 | 164 | -| 100x100 | 0.045029 | 1.777236 | 164 | -| 250x250 | 0.205750 | 12.221867 | 164 | -| 500x500 | 0.685251 | 46.958753 | 164 | -| 750x750 | 1.645099 | 100.396243 | 164 | +| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend | +|---|---|---|---|---| +| 10x10 | 0.000434 | 0.033605 | 164 | groth16 | +| 100x100 | 0.028184 | 1.699871 | 164 | groth16 | +| 250x250 | 0.171229 | 10.918394 | 164 | groth16 | +| 500x500 | 0.647757 | 43.215272 | 164 | groth16 | +| 750x750 | 1.421753 | 94.541931 | 164 | groth16 | +| 10x10 | 0.000247 | 0.200214 | 552 | plonk | +| 100x100 | 0.020475 | 5.128606 | 552 | plonk | +| 250x250 | 0.134876 | 45.082718 | 552 | plonk | +| 500x500 | 0.558636 | 196.608304 | 552 | plonk | +| 750x750 | 1.592956 | 421.920696 | 552 | plonk | diff --git a/cmd/brighten.go b/cmd/brighten.go index 0943e76..4f9047f 100644 --- a/cmd/brighten.go +++ b/cmd/brighten.go @@ -5,9 +5,9 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/consensys/gnark/std/math/cmp" "github.com/spf13/cobra" + "io" "os" "path" "time" @@ -27,6 +27,7 @@ type brightenConfig struct { brighteningFactor int // TODO(xenowits): Convert it to floating-point proofDir string markdownFile string + backend string } // newBrightenCmd returns a new cobra.Command for brightening an image by a brightening factor. @@ -51,6 +52,7 @@ func bindBrightenFlags(cmd *cobra.Command, conf *brightenConfig) { cmd.Flags().StringVar(&conf.finalImg, "final-image", "", "The path to the final image. Supported image formats: PNG.") cmd.Flags().StringVar(&conf.proofDir, "proof-dir", "", "The path to the proof directory.") cmd.Flags().IntVar(&conf.brighteningFactor, "brightening-factor", 2, "The factor with which image is brightened.") + cmd.Flags().StringVar(&conf.backend, "backend", "groth16", "The proving backend used for generating the proofs.") } // proveBrighten generates the zk proof of brightening an image by a brightening factor. @@ -85,7 +87,7 @@ func proveBrighten(config brightenConfig) error { return err } - proof, vk, circuitCompilationDuration, provingDuration, err := generateBrightenProof(originalPixels, finalPixels) + proof, vk, circuitCompilationDuration, provingDuration, err := generateBrightenProof(config.backend, originalPixels, finalPixels) if err != nil { return err } @@ -141,7 +143,7 @@ func proveBrighten(config brightenConfig) error { } // generateBrightenProof returns the zk proof of brightening an image by a brightening factor. -func generateBrightenProof(original, brightened [][][]uint8) (groth16.Proof, groth16.VerifyingKey, time.Duration, time.Duration, error) { +func generateBrightenProof(backend string, original, brightened [][][]uint8) (io.WriterTo, io.WriterTo, time.Duration, time.Duration, error) { var circuit brightenCircuit circuit.Original = make([][][]frontend.Variable, len(original)) // First dimension for i := range original { @@ -160,9 +162,9 @@ func generateBrightenProof(original, brightened [][][]uint8) (groth16.Proof, gro } t0 := time.Now() - cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + cs, err := compileCircuit(backend, &circuit) if err != nil { - panic(err) + return nil, nil, 0, 0, err } fmt.Println("Brighten compilation time:", time.Since(t0).Seconds()) @@ -177,12 +179,7 @@ func generateBrightenProof(original, brightened [][][]uint8) (groth16.Proof, gro return nil, nil, 0, 0, err } - pk, vk, err := groth16.Setup(cs) - if err != nil { - return nil, nil, 0, 0, err - } - - proof, err := groth16.Prove(cs, pk, witness) + proof, vk, err := generateProofByBackend(backend, cs, witness) if err != nil { return nil, nil, 0, 0, err } diff --git a/cmd/cmd.go b/cmd/cmd.go index 9b67312..88a2a8f 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,10 +1,22 @@ package cmd import ( + "errors" + "fmt" + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark/backend/groth16" + "github.com/consensys/gnark/backend/plonk" + "github.com/consensys/gnark/backend/witness" + "github.com/consensys/gnark/constraint" + "github.com/consensys/gnark/frontend" + "github.com/consensys/gnark/frontend/cs/r1cs" + "github.com/consensys/gnark/frontend/cs/scs" + "github.com/consensys/gnark/test" "github.com/spf13/cobra" + "io" ) -// New returns a new cobra command that handles stackr aggregator commands and subcommands. +// New returns a new cobra command that handles maya cli commands and subcommands. func New() *cobra.Command { return newRootCmd( newProveCmd( @@ -63,3 +75,51 @@ func newVerifyCmd(cmds ...*cobra.Command) *cobra.Command { return root } + +func compileCircuit(backend string, circuit frontend.Circuit) (constraint.ConstraintSystem, error) { + switch backend { + case "groth16": + return frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, circuit) + case "plonk": // TODO(dhruv): add plonkfri when its serialisation is supported. + return frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, circuit) + default: + return nil, errors.New(fmt.Sprintf("invalid backend, %s", backend)) + } +} + +func generateProofByBackend(backend string, cs constraint.ConstraintSystem, witness witness.Witness) (io.WriterTo, io.WriterTo, error) { + switch backend { + case "groth16": + pk, vk, err := groth16.Setup(cs) + if err != nil { + return nil, nil, err + } + + proof, err := groth16.Prove(cs, pk, witness) + if err != nil { + return nil, nil, err + } + + return proof, vk, nil + case "plonk": + // TODO(dhruv): replace this with actual trusted setup ceremony. + kzgSrs, err := test.NewKZGSRS(cs) + if err != nil { + return nil, nil, err + } + + pk, vk, err := plonk.Setup(cs, kzgSrs) + if err != nil { + return nil, nil, err + } + + proof, err := plonk.Prove(cs, pk, witness) + if err != nil { + return nil, nil, err + } + + return proof, vk, nil + default: + return nil, nil, errors.New(fmt.Sprintf("invalid backend, %s", backend)) + } +} diff --git a/cmd/crop.go b/cmd/crop.go index 9c4a1cc..8b286b7 100644 --- a/cmd/crop.go +++ b/cmd/crop.go @@ -5,7 +5,6 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/spf13/cobra" "image/png" "io" @@ -24,6 +23,7 @@ type cropConfig struct { heightStartNew int proofDir string markdownFile string + backend string } // newCropCmd returns a new cobra.Command for cropping. @@ -49,6 +49,7 @@ func bindFlags(cmd *cobra.Command, conf *cropConfig) { cmd.Flags().IntVar(&conf.widthStartNew, "width-start-new", 0, "The Original-coordinate for the top-left corner of the cropped image, relative to the original image's width.") cmd.Flags().IntVar(&conf.heightStartNew, "height-start-new", 0, "The Cropped-coordinate for the top-left corner of the cropped image, relative to the original image's height.") cmd.Flags().StringVar(&conf.proofDir, "proof-dir", "", "The path to the proof directory.") + cmd.Flags().StringVar(&conf.backend, "backend", "groth16", "The proving backend used for generating the proofs.") } // proveCrop generates the zk proof of crop transformation. @@ -82,7 +83,7 @@ func proveCrop(config cropConfig) error { return err } - proof, vk, circuitCompilationDuration, provingDuration, err := generateProof(finalPixels, originalPixels) + proof, vk, circuitCompilationDuration, provingDuration, err := generateCropProof(config.backend, finalPixels, originalPixels) if err != nil { return err } @@ -107,7 +108,7 @@ func proveCrop(config cropConfig) error { } defer mdFile.Close() - if _, err = fmt.Fprintf(mdFile, "| %s | %s | %f | %f | %d |\n", + if _, err = fmt.Fprintf(mdFile, "| %s | %s | %f | %f | %d | %s |\n", fmt.Sprintf("%dx%d", len(originalPixels), len(originalPixels[0])), fmt.Sprintf("%dx%d", len(finalPixels), @@ -115,6 +116,7 @@ func proveCrop(config cropConfig) error { circuitCompilationDuration.Seconds(), provingDuration.Seconds(), n, + config.backend, ); err != nil { return err } @@ -162,8 +164,8 @@ func convertImgToPixels(file io.Reader) ([][][]uint8, error) { return pixels, nil } -// generateProof returns the proof of crop transformation. -func generateProof(cropped, original [][][]uint8) (groth16.Proof, groth16.VerifyingKey, time.Duration, time.Duration, error) { +// generateCropProof returns the proof of crop transformation. +func generateCropProof(backend string, cropped, original [][][]uint8) (io.WriterTo, io.WriterTo, time.Duration, time.Duration, error) { var circuit CropCircuit circuit.Original = make([][][]frontend.Variable, len(original)) // First dimension for i := range original { @@ -182,7 +184,7 @@ func generateProof(cropped, original [][][]uint8) (groth16.Proof, groth16.Verify } t0 := time.Now() - cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + cs, err := compileCircuit(backend, &circuit) if err != nil { panic(err) } @@ -199,12 +201,7 @@ func generateProof(cropped, original [][][]uint8) (groth16.Proof, groth16.Verify return nil, nil, 0, 0, err } - pk, vk, err := groth16.Setup(cs) - if err != nil { - return nil, nil, 0, 0, err - } - - proof, err := groth16.Prove(cs, pk, witness) + proof, vk, err := generateProofByBackend(backend, cs, witness) if err != nil { return nil, nil, 0, 0, err } diff --git a/cmd/crop_test.go b/cmd/crop_test.go index 313702b..80acb61 100644 --- a/cmd/crop_test.go +++ b/cmd/crop_test.go @@ -20,6 +20,7 @@ func TestBenchmarkCrop(t *testing.T) { heightStartNew int widthNew int heightNew int + backend string }{ { name: "crop_xsmall", @@ -28,6 +29,7 @@ func TestBenchmarkCrop(t *testing.T) { heightStartNew: 0, widthNew: 10, heightNew: 10, + backend: "groth16", }, { name: "crop_small", @@ -36,6 +38,7 @@ func TestBenchmarkCrop(t *testing.T) { heightStartNew: 0, widthNew: 100, heightNew: 100, + backend: "groth16", }, { name: "crop_medium", @@ -44,6 +47,7 @@ func TestBenchmarkCrop(t *testing.T) { heightStartNew: 0, widthNew: 250, heightNew: 250, + backend: "groth16", }, { name: "crop_large", @@ -52,6 +56,7 @@ func TestBenchmarkCrop(t *testing.T) { heightStartNew: 0, widthNew: 500, heightNew: 500, + backend: "groth16", }, { name: "crop_xlarge", @@ -60,6 +65,52 @@ func TestBenchmarkCrop(t *testing.T) { heightStartNew: 0, widthNew: 750, heightNew: 750, + backend: "groth16", + }, + { + name: "crop_xsmall", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 10, + heightNew: 10, + backend: "plonk", + }, + { + name: "crop_small", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 100, + heightNew: 100, + backend: "plonk", + }, + { + name: "crop_medium", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 250, + heightNew: 250, + backend: "plonk", + }, + { + name: "crop_large", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 500, + heightNew: 500, + backend: "plonk", + }, + { + name: "crop_xlarge", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 750, + heightNew: 750, + backend: "plonk", }, } @@ -69,8 +120,8 @@ func TestBenchmarkCrop(t *testing.T) { fmt.Fprintln(mdFile, "## Crop") // Write the Markdown table headers - fmt.Fprintln(mdFile, "| Original Size | Final Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) |") - fmt.Fprintln(mdFile, "|---|---|---|---|---|") + fmt.Fprintln(mdFile, "| Original Size | Final Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend |") + fmt.Fprintln(mdFile, "|---|---|---|---|---|---|") mdFile.Close() for _, tt := range tests { @@ -87,6 +138,7 @@ func TestBenchmarkCrop(t *testing.T) { heightStartNew: tt.heightStartNew, proofDir: dir, markdownFile: mdFilePath, + backend: tt.backend, } err := proveCrop(conf) require.NoError(t, err) diff --git a/cmd/fliphorizontal.go b/cmd/fliphorizontal.go index 15bf919..c5a4f8a 100644 --- a/cmd/fliphorizontal.go +++ b/cmd/fliphorizontal.go @@ -5,8 +5,8 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/spf13/cobra" + "io" "os" "path" "time" @@ -18,6 +18,7 @@ type flipHorizontalConfig struct { finalImg string proofDir string markdownFile string + backend string } // newFlipHorizontalCmd returns a new cobra.Command for flipping an image horizontally. @@ -41,6 +42,7 @@ func bindFlipHorizontalFlags(cmd *cobra.Command, conf *flipHorizontalConfig) { cmd.Flags().StringVar(&conf.originalImg, "original-image", "", "The path to the original image. Supported image formats: PNG.") cmd.Flags().StringVar(&conf.finalImg, "final-image", "", "The path to the final image. Supported image formats: PNG.") cmd.Flags().StringVar(&conf.proofDir, "proof-dir", "", "The path to the proof directory.") + cmd.Flags().StringVar(&conf.backend, "backend", "groth16", "The proving backend used for generating the proofs.") } // proveFlipHorizontal generates the zk proof of flip horizontal transformation. @@ -71,7 +73,7 @@ func proveFlipHorizontal(config flipHorizontalConfig) error { return err } - proof, vk, circuitCompilationDuration, provingDuration, err := generateFlipHorizontalProof(originalPixels, finalPixels) + proof, vk, circuitCompilationDuration, provingDuration, err := generateFlipHorizontalProof(config.backend, originalPixels, finalPixels) if err != nil { return err } @@ -112,12 +114,13 @@ func proveFlipHorizontal(config flipHorizontalConfig) error { } defer mdFile.Close() - if _, err = fmt.Fprintf(mdFile, "| %s | %f | %f | %d |\n", + if _, err = fmt.Fprintf(mdFile, "| %s | %f | %f | %d | %s |\n", fmt.Sprintf("%dx%d", len(finalPixels), len(finalPixels[0])), circuitCompilationDuration.Seconds(), provingDuration.Seconds(), n, + config.backend, ); err != nil { return err } @@ -127,7 +130,7 @@ func proveFlipHorizontal(config flipHorizontalConfig) error { } // generateFlipHorizontalProof returns the proof of flipHorizontal transformation. -func generateFlipHorizontalProof(original, flipped [][][]uint8) (groth16.Proof, groth16.VerifyingKey, time.Duration, time.Duration, error) { +func generateFlipHorizontalProof(backend string, original, flipped [][][]uint8) (io.WriterTo, io.WriterTo, time.Duration, time.Duration, error) { var circuit FlipHorizontalCircuit circuit.Original = make([][][]frontend.Variable, len(original)) // First dimension for i := range original { @@ -146,9 +149,9 @@ func generateFlipHorizontalProof(original, flipped [][][]uint8) (groth16.Proof, } t0 := time.Now() - cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + cs, err := compileCircuit(backend, &circuit) if err != nil { - panic(err) + return nil, nil, 0, 0, err } fmt.Println("Flip Horizontal compilation time:", time.Since(t0).Seconds()) @@ -163,12 +166,7 @@ func generateFlipHorizontalProof(original, flipped [][][]uint8) (groth16.Proof, return nil, nil, 0, 0, err } - pk, vk, err := groth16.Setup(cs) - if err != nil { - return nil, nil, 0, 0, err - } - - proof, err := groth16.Prove(cs, pk, witness) + proof, vk, err := generateProofByBackend(backend, cs, witness) if err != nil { return nil, nil, 0, 0, err } @@ -186,8 +184,7 @@ type FlipHorizontalCircuit struct { } func (c *FlipHorizontalCircuit) Define(api frontend.API) error { - api.AssertIsDifferent(len(c.Original), 0) - api.AssertIsDifferent(len(c.Flipped), 0) + // TODO(dhruv): Add AssertIsDifferent to compare len(Original) with 0. api.AssertIsEqual(len(c.Original), len(c.Flipped)) api.AssertIsEqual(len(c.Original[0]), len(c.Flipped[0])) diff --git a/cmd/fliphorizontal_test.go b/cmd/fliphorizontal_test.go index c5cf753..2f2344f 100644 --- a/cmd/fliphorizontal_test.go +++ b/cmd/fliphorizontal_test.go @@ -19,6 +19,7 @@ func TestBenchmarkFlipHorizontal(t *testing.T) { heightStartNew int widthNew int heightNew int + backend string }{ { name: "flip_horizontal_xsmall", @@ -27,6 +28,7 @@ func TestBenchmarkFlipHorizontal(t *testing.T) { heightStartNew: 0, widthNew: 10, heightNew: 10, + backend: "groth16", }, { name: "flip_horizontal_small", @@ -35,6 +37,7 @@ func TestBenchmarkFlipHorizontal(t *testing.T) { heightStartNew: 0, widthNew: 100, heightNew: 100, + backend: "groth16", }, { name: "flip_horizontal_medium", @@ -43,6 +46,7 @@ func TestBenchmarkFlipHorizontal(t *testing.T) { heightStartNew: 0, widthNew: 250, heightNew: 250, + backend: "groth16", }, { name: "flip_horizontal_large", @@ -51,6 +55,7 @@ func TestBenchmarkFlipHorizontal(t *testing.T) { heightStartNew: 0, widthNew: 500, heightNew: 500, + backend: "groth16", }, { name: "flip_horizontal_xlarge", @@ -59,6 +64,52 @@ func TestBenchmarkFlipHorizontal(t *testing.T) { heightStartNew: 0, widthNew: 750, heightNew: 750, + backend: "groth16", + }, + { + name: "flip_horizontal_xsmall", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 10, + heightNew: 10, + backend: "plonk", + }, + { + name: "flip_horizontal_small", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 100, + heightNew: 100, + backend: "plonk", + }, + { + name: "flip_horizontal_medium", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 250, + heightNew: 250, + backend: "plonk", + }, + { + name: "flip_horizontal_large", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 500, + heightNew: 500, + backend: "plonk", + }, + { + name: "flip_horizontal_xlarge", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 750, + heightNew: 750, + backend: "plonk", }, } @@ -68,8 +119,8 @@ func TestBenchmarkFlipHorizontal(t *testing.T) { fmt.Fprintln(mdFile, "## Flip horizontal") // Write the Markdown table headers - fmt.Fprintln(mdFile, "| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) |") - fmt.Fprintln(mdFile, "|---|---|---|---|") + fmt.Fprintln(mdFile, "| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend |") + fmt.Fprintln(mdFile, "|---|---|---|---|---|") mdFile.Close() for _, tt := range tests { @@ -87,6 +138,7 @@ func TestBenchmarkFlipHorizontal(t *testing.T) { finalImg: finalImg, proofDir: dir, markdownFile: mdFilePath, + backend: tt.backend, } err = proveFlipHorizontal(conf) require.NoError(t, err) diff --git a/cmd/flipvertical.go b/cmd/flipvertical.go index 9aaecff..8e4f065 100644 --- a/cmd/flipvertical.go +++ b/cmd/flipvertical.go @@ -5,8 +5,8 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/spf13/cobra" + "io" "os" "path" "time" @@ -18,6 +18,7 @@ type flipVerticalConfig struct { finalImg string proofDir string markdownFile string + backend string } // newFlipVerticalCmd returns a new cobra.Command for flipping an image vertically. @@ -41,6 +42,7 @@ func bindFlipVerticalFlags(cmd *cobra.Command, conf *flipVerticalConfig) { cmd.Flags().StringVar(&conf.originalImg, "original-image", "", "The path to the original image. Supported image formats: PNG.") cmd.Flags().StringVar(&conf.finalImg, "final-image", "", "The path to the final image. Supported image formats: PNG.") cmd.Flags().StringVar(&conf.proofDir, "proof-dir", "", "The path to the proof directory.") + cmd.Flags().StringVar(&conf.backend, "backend", "groth16", "The proving backend used for generating the proofs.") } // proveFlipVertical generates the zk proof of flip vertical transformation. @@ -71,7 +73,7 @@ func proveFlipVertical(config flipVerticalConfig) error { return err } - proof, vk, circuitCompilationDuration, provingDuration, err := generateFlipVerticalProof(originalPixels, finalPixels) + proof, vk, circuitCompilationDuration, provingDuration, err := generateFlipVerticalProof(config.backend, originalPixels, finalPixels) if err != nil { return err } @@ -112,12 +114,13 @@ func proveFlipVertical(config flipVerticalConfig) error { } defer mdFile.Close() - if _, err = fmt.Fprintf(mdFile, "| %s | %f | %f | %d |\n", + if _, err = fmt.Fprintf(mdFile, "| %s | %f | %f | %d | %s |\n", fmt.Sprintf("%dx%d", len(finalPixels), len(finalPixels[0])), circuitCompilationDuration.Seconds(), provingDuration.Seconds(), n, + config.backend, ); err != nil { return err } @@ -127,7 +130,7 @@ func proveFlipVertical(config flipVerticalConfig) error { } // generateFlipVerticalProof returns the proof of flipVertical transformation. -func generateFlipVerticalProof(original, flipped [][][]uint8) (groth16.Proof, groth16.VerifyingKey, time.Duration, time.Duration, error) { +func generateFlipVerticalProof(backend string, original, flipped [][][]uint8) (io.WriterTo, io.WriterTo, time.Duration, time.Duration, error) { var circuit FlipVerticalCircuit circuit.Original = make([][][]frontend.Variable, len(original)) // First dimension for i := range original { @@ -146,9 +149,9 @@ func generateFlipVerticalProof(original, flipped [][][]uint8) (groth16.Proof, gr } t0 := time.Now() - cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + cs, err := compileCircuit(backend, &circuit) if err != nil { - panic(err) + return nil, nil, 0, 0, err } fmt.Println("Flip vertical compilation time:", time.Since(t0).Seconds()) @@ -163,12 +166,7 @@ func generateFlipVerticalProof(original, flipped [][][]uint8) (groth16.Proof, gr return nil, nil, 0, 0, err } - pk, vk, err := groth16.Setup(cs) - if err != nil { - return nil, nil, 0, 0, err - } - - proof, err := groth16.Prove(cs, pk, witness) + proof, vk, err := generateProofByBackend(backend, cs, witness) if err != nil { return nil, nil, 0, 0, err } @@ -186,8 +184,7 @@ type FlipVerticalCircuit struct { } func (c *FlipVerticalCircuit) Define(api frontend.API) error { - api.AssertIsDifferent(len(c.Original), 0) - api.AssertIsDifferent(len(c.Flipped), 0) + // TODO(dhruv): Add AssertIsDifferent to compare len(Original) with 0. api.AssertIsEqual(len(c.Original), len(c.Flipped)) api.AssertIsEqual(len(c.Original[0]), len(c.Flipped[0])) diff --git a/cmd/flipvertical_test.go b/cmd/flipvertical_test.go index 31af88a..ec17655 100644 --- a/cmd/flipvertical_test.go +++ b/cmd/flipvertical_test.go @@ -19,6 +19,7 @@ func TestBenchmarkFlipVertical(t *testing.T) { heightStartNew int widthNew int heightNew int + backend string }{ { name: "flip_vertical_xsmall", @@ -27,6 +28,7 @@ func TestBenchmarkFlipVertical(t *testing.T) { heightStartNew: 0, widthNew: 10, heightNew: 10, + backend: "groth16", }, { name: "flip_vertical_small", @@ -35,6 +37,7 @@ func TestBenchmarkFlipVertical(t *testing.T) { heightStartNew: 0, widthNew: 100, heightNew: 100, + backend: "groth16", }, { name: "flip_vertical_medium", @@ -43,6 +46,7 @@ func TestBenchmarkFlipVertical(t *testing.T) { heightStartNew: 0, widthNew: 250, heightNew: 250, + backend: "groth16", }, { name: "flip_vertical_large", @@ -51,6 +55,7 @@ func TestBenchmarkFlipVertical(t *testing.T) { heightStartNew: 0, widthNew: 500, heightNew: 500, + backend: "groth16", }, { name: "flip_vertical_xlarge", @@ -59,6 +64,52 @@ func TestBenchmarkFlipVertical(t *testing.T) { heightStartNew: 0, widthNew: 750, heightNew: 750, + backend: "groth16", + }, + { + name: "flip_vertical_xsmall", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 10, + heightNew: 10, + backend: "plonk", + }, + { + name: "flip_vertical_small", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 100, + heightNew: 100, + backend: "plonk", + }, + { + name: "flip_vertical_medium", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 250, + heightNew: 250, + backend: "plonk", + }, + { + name: "flip_vertical_large", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 500, + heightNew: 500, + backend: "plonk", + }, + { + name: "flip_vertical_xlarge", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 750, + heightNew: 750, + backend: "plonk", }, } @@ -68,8 +119,8 @@ func TestBenchmarkFlipVertical(t *testing.T) { fmt.Fprintln(mdFile, "## Flip vertical") // Write the Markdown table headers - fmt.Fprintln(mdFile, "| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) |") - fmt.Fprintln(mdFile, "|---|---|---|---|") + fmt.Fprintln(mdFile, "| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend |") + fmt.Fprintln(mdFile, "|---|---|---|---|---|") mdFile.Close() for _, tt := range tests { @@ -87,6 +138,7 @@ func TestBenchmarkFlipVertical(t *testing.T) { finalImg: finalImg, proofDir: dir, markdownFile: mdFilePath, + backend: tt.backend, } err := proveFlipVertical(conf) require.NoError(t, err) diff --git a/cmd/rotate180.go b/cmd/rotate180.go index 18107d1..bd1d09a 100644 --- a/cmd/rotate180.go +++ b/cmd/rotate180.go @@ -5,8 +5,8 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/spf13/cobra" + "io" "os" "path" "time" @@ -18,6 +18,7 @@ type rotate180Config struct { finalImg string proofDir string markdownFile string + backend string } // newRotate180Cmd returns a new cobra.Command for rotating an image by 180 degrees. @@ -41,6 +42,7 @@ func bindRotate180Flags(cmd *cobra.Command, conf *rotate180Config) { cmd.Flags().StringVar(&conf.originalImg, "original-image", "", "The path to the original image. Supported image formats: PNG.") cmd.Flags().StringVar(&conf.finalImg, "final-image", "", "The path to the final image. Supported image formats: PNG.") cmd.Flags().StringVar(&conf.proofDir, "proof-dir", "", "The path to the proof directory.") + cmd.Flags().StringVar(&conf.backend, "backend", "groth16", "The proving backend used for generating the proofs.") } // proveRotate180 generates the zk proof of rotated transformation 180. @@ -71,7 +73,7 @@ func proveRotate180(config rotate180Config) error { return err } - proof, vk, circuitCompilationDuration, provingDuration, err := generateRotate180Proof(originalPixels, finalPixels) + proof, vk, circuitCompilationDuration, provingDuration, err := generateRotate180Proof(config.backend, originalPixels, finalPixels) if err != nil { return err } @@ -112,12 +114,13 @@ func proveRotate180(config rotate180Config) error { } defer mdFile.Close() - if _, err = fmt.Fprintf(mdFile, "| %s | %f | %f | %d |\n", + if _, err = fmt.Fprintf(mdFile, "| %s | %f | %f | %d | %s|\n", fmt.Sprintf("%dx%d", len(finalPixels), len(finalPixels[0])), circuitCompilationDuration.Seconds(), provingDuration.Seconds(), n, + config.backend, ); err != nil { return err } @@ -127,7 +130,7 @@ func proveRotate180(config rotate180Config) error { } // generateRotate180Proof returns the proof of rotate180 transformation. -func generateRotate180Proof(original, rotated [][][]uint8) (groth16.Proof, groth16.VerifyingKey, time.Duration, time.Duration, error) { +func generateRotate180Proof(backend string, original, rotated [][][]uint8) (io.WriterTo, io.WriterTo, time.Duration, time.Duration, error) { var circuit Rotate180Circuit circuit.Original = make([][][]frontend.Variable, len(original)) // First dimension for i := range original { @@ -146,9 +149,9 @@ func generateRotate180Proof(original, rotated [][][]uint8) (groth16.Proof, groth } t0 := time.Now() - cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + cs, err := compileCircuit(backend, &circuit) if err != nil { - panic(err) + return nil, nil, 0, 0, err } fmt.Println("Rotate180 compilation time:", time.Since(t0).Seconds()) @@ -163,13 +166,7 @@ func generateRotate180Proof(original, rotated [][][]uint8) (groth16.Proof, groth return nil, nil, 0, 0, err } - pk, vk, err := groth16.Setup(cs) - if err != nil { - return nil, nil, 0, 0, err - } - - t0 = time.Now() - proof, err := groth16.Prove(cs, pk, witness) + proof, vk, err := generateProofByBackend(backend, cs, witness) if err != nil { return nil, nil, 0, 0, err } @@ -187,8 +184,7 @@ type Rotate180Circuit struct { } func (c *Rotate180Circuit) Define(api frontend.API) error { - api.AssertIsDifferent(len(c.Original), 0) - api.AssertIsDifferent(len(c.Rotated), 0) + // TODO(dhruv): Add AssertIsDifferent to compare len(Original) with 0. api.AssertIsEqual(len(c.Original), len(c.Rotated[0])) api.AssertIsEqual(len(c.Original[0]), len(c.Rotated)) diff --git a/cmd/rotate180_test.go b/cmd/rotate180_test.go index a2c02d5..41dc00a 100644 --- a/cmd/rotate180_test.go +++ b/cmd/rotate180_test.go @@ -19,6 +19,7 @@ func TestBenchmarkRotate180(t *testing.T) { heightStartNew int widthNew int heightNew int + backend string }{ { name: "rotate180_xsmall", @@ -27,6 +28,7 @@ func TestBenchmarkRotate180(t *testing.T) { heightStartNew: 0, widthNew: 10, heightNew: 10, + backend: "groth16", }, { name: "rotate180_small", @@ -35,6 +37,7 @@ func TestBenchmarkRotate180(t *testing.T) { heightStartNew: 0, widthNew: 100, heightNew: 100, + backend: "groth16", }, { name: "rotate180_medium", @@ -43,6 +46,7 @@ func TestBenchmarkRotate180(t *testing.T) { heightStartNew: 0, widthNew: 250, heightNew: 250, + backend: "groth16", }, { name: "rotate180_large", @@ -51,6 +55,7 @@ func TestBenchmarkRotate180(t *testing.T) { heightStartNew: 0, widthNew: 500, heightNew: 500, + backend: "groth16", }, { name: "rotate180_xlarge", @@ -59,6 +64,52 @@ func TestBenchmarkRotate180(t *testing.T) { heightStartNew: 0, widthNew: 750, heightNew: 750, + backend: "groth16", + }, + { + name: "rotate180_xsmall", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 10, + heightNew: 10, + backend: "plonk", + }, + { + name: "rotate180_small", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 100, + heightNew: 100, + backend: "plonk", + }, + { + name: "rotate180_medium", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 250, + heightNew: 250, + backend: "plonk", + }, + { + name: "rotate180_large", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 500, + heightNew: 500, + backend: "plonk", + }, + { + name: "rotate180_xlarge", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 750, + heightNew: 750, + backend: "plonk", }, } @@ -68,8 +119,8 @@ func TestBenchmarkRotate180(t *testing.T) { fmt.Fprintln(mdFile, "## Rotate 180") // Write the Markdown table headers - fmt.Fprintln(mdFile, "| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) |") - fmt.Fprintln(mdFile, "|---|---|---|---|") + fmt.Fprintln(mdFile, "| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend |") + fmt.Fprintln(mdFile, "|---|---|---|---|---|") mdFile.Close() for _, tt := range tests { @@ -87,6 +138,7 @@ func TestBenchmarkRotate180(t *testing.T) { finalImg: finalImg, proofDir: dir, markdownFile: mdFilePath, + backend: tt.backend, } err := proveRotate180(conf) require.NoError(t, err) diff --git a/cmd/rotate270.go b/cmd/rotate270.go index 436b28a..3282691 100644 --- a/cmd/rotate270.go +++ b/cmd/rotate270.go @@ -5,8 +5,8 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/spf13/cobra" + "io" "os" "path" "time" @@ -18,6 +18,7 @@ type rotate270Config struct { finalImg string proofDir string markdownFile string + backend string } // newRotate270Cmd returns a new cobra.Command for rotating an image by 270 degrees. @@ -71,7 +72,7 @@ func proveRotate270(config rotate270Config) error { return err } - proof, vk, circuitCompilationDuration, provingDuration, err := generateRotate270Proof(originalPixels, finalPixels) + proof, vk, circuitCompilationDuration, provingDuration, err := generateRotate270Proof(config.backend, originalPixels, finalPixels) if err != nil { return err } @@ -112,12 +113,13 @@ func proveRotate270(config rotate270Config) error { } defer mdFile.Close() - if _, err = fmt.Fprintf(mdFile, "| %s | %f | %f | %d |\n", + if _, err = fmt.Fprintf(mdFile, "| %s | %f | %f | %d | %s |\n", fmt.Sprintf("%dx%d", len(finalPixels), len(finalPixels[0])), circuitCompilationDuration.Seconds(), provingDuration.Seconds(), n, + config.backend, ); err != nil { return err } @@ -127,7 +129,7 @@ func proveRotate270(config rotate270Config) error { } // generateRotate270Proof returns the proof of rotate270 transformation. -func generateRotate270Proof(original, rotated [][][]uint8) (groth16.Proof, groth16.VerifyingKey, time.Duration, time.Duration, error) { +func generateRotate270Proof(backend string, original, rotated [][][]uint8) (io.WriterTo, io.WriterTo, time.Duration, time.Duration, error) { var circuit Rotate270Circuit circuit.Original = make([][][]frontend.Variable, len(original)) // First dimension for i := range original { @@ -146,9 +148,9 @@ func generateRotate270Proof(original, rotated [][][]uint8) (groth16.Proof, groth } t0 := time.Now() - cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + cs, err := compileCircuit(backend, &circuit) if err != nil { - panic(err) + return nil, nil, 0, 0, err } fmt.Println("Rotate270Circuit compilation time:", time.Since(t0).Seconds()) @@ -163,12 +165,7 @@ func generateRotate270Proof(original, rotated [][][]uint8) (groth16.Proof, groth return nil, nil, 0, 0, err } - pk, vk, err := groth16.Setup(cs) - if err != nil { - return nil, nil, 0, 0, err - } - - proof, err := groth16.Prove(cs, pk, witness) + proof, vk, err := generateProofByBackend(backend, cs, witness) if err != nil { return nil, nil, 0, 0, err } @@ -186,8 +183,7 @@ type Rotate270Circuit struct { } func (c *Rotate270Circuit) Define(api frontend.API) error { - api.AssertIsDifferent(len(c.Original), 0) - api.AssertIsDifferent(len(c.Rotated), 0) + // TODO(dhruv): Add AssertIsDifferent to compare len(Original) with 0. api.AssertIsEqual(len(c.Original[0]), len(c.Rotated)) api.AssertIsEqual(len(c.Original), len(c.Rotated[0])) diff --git a/cmd/rotate270_test.go b/cmd/rotate270_test.go index 6a7b449..faadad4 100644 --- a/cmd/rotate270_test.go +++ b/cmd/rotate270_test.go @@ -19,6 +19,7 @@ func TestBenchmarkRotate270(t *testing.T) { heightStartNew int widthNew int heightNew int + backend string }{ { name: "rotate270_xsmall", @@ -27,6 +28,7 @@ func TestBenchmarkRotate270(t *testing.T) { heightStartNew: 0, widthNew: 10, heightNew: 10, + backend: "groth16", }, { name: "rotate270_small", @@ -35,6 +37,7 @@ func TestBenchmarkRotate270(t *testing.T) { heightStartNew: 0, widthNew: 100, heightNew: 100, + backend: "groth16", }, { name: "rotate270_medium", @@ -43,6 +46,7 @@ func TestBenchmarkRotate270(t *testing.T) { heightStartNew: 0, widthNew: 250, heightNew: 250, + backend: "groth16", }, { name: "rotate270_large", @@ -51,6 +55,7 @@ func TestBenchmarkRotate270(t *testing.T) { heightStartNew: 0, widthNew: 500, heightNew: 500, + backend: "groth16", }, { name: "rotate270_xlarge", @@ -59,6 +64,52 @@ func TestBenchmarkRotate270(t *testing.T) { heightStartNew: 0, widthNew: 750, heightNew: 750, + backend: "groth16", + }, + { + name: "rotate270_xsmall", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 10, + heightNew: 10, + backend: "plonk", + }, + { + name: "rotate270_small", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 100, + heightNew: 100, + backend: "plonk", + }, + { + name: "rotate270_medium", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 250, + heightNew: 250, + backend: "plonk", + }, + { + name: "rotate270_large", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 500, + heightNew: 500, + backend: "plonk", + }, + { + name: "rotate270_xlarge", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 750, + heightNew: 750, + backend: "plonk", }, } @@ -68,8 +119,8 @@ func TestBenchmarkRotate270(t *testing.T) { fmt.Fprintln(mdFile, "## Rotate 270") // Write the Markdown table headers - fmt.Fprintln(mdFile, "| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) |") - fmt.Fprintln(mdFile, "|---|---|---|---|") + fmt.Fprintln(mdFile, "| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend |") + fmt.Fprintln(mdFile, "|---|---|---|---|---|") mdFile.Close() for _, tt := range tests { @@ -87,6 +138,7 @@ func TestBenchmarkRotate270(t *testing.T) { finalImg: finalImg, proofDir: dir, markdownFile: mdFilePath, + backend: tt.backend, } err := proveRotate270(conf) require.NoError(t, err) diff --git a/cmd/rotate90.go b/cmd/rotate90.go index c88deaf..bce0e9b 100644 --- a/cmd/rotate90.go +++ b/cmd/rotate90.go @@ -5,8 +5,8 @@ import ( "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/spf13/cobra" + "io" "os" "path" "time" @@ -18,6 +18,7 @@ type rotate90Config struct { finalImg string proofDir string markdownFile string + backend string } // newRotate90Cmd returns a new cobra.Command for rotating an image by 90 degrees. @@ -41,6 +42,7 @@ func bindRotate90Flags(cmd *cobra.Command, conf *rotate90Config) { cmd.Flags().StringVar(&conf.originalImg, "original-image", "", "The path to the original image. Supported image formats: PNG.") cmd.Flags().StringVar(&conf.finalImg, "final-image", "", "The path to the final image. Supported image formats: PNG.") cmd.Flags().StringVar(&conf.proofDir, "proof-dir", "", "The path to the proof directory.") + cmd.Flags().StringVar(&conf.backend, "backend", "groth16", "The proving backend used for generating the proofs.") } // proveRotate90 generates the zk proof of rotate 90 transformation. @@ -71,7 +73,7 @@ func proveRotate90(config rotate90Config) error { return err } - proof, vk, circuitCompilationDuration, provingDuration, err := generateRotate90Proof(originalPixels, finalPixels) + proof, vk, circuitCompilationDuration, provingDuration, err := generateRotate90Proof(config.backend, originalPixels, finalPixels) if err != nil { return err } @@ -101,12 +103,13 @@ func proveRotate90(config rotate90Config) error { } defer mdFile.Close() - if _, err = fmt.Fprintf(mdFile, "| %s | %f | %f | %d |\n", + if _, err = fmt.Fprintf(mdFile, "| %s | %f | %f | %d | %s |\n", fmt.Sprintf("%dx%d", len(finalPixels), len(finalPixels[0])), circuitCompilationDuration.Seconds(), provingDuration.Seconds(), n, + config.backend, ); err != nil { return err } @@ -127,7 +130,7 @@ func proveRotate90(config rotate90Config) error { } // generateRotate90Proof returns the proof of rotate90 transformation. -func generateRotate90Proof(original, rotated [][][]uint8) (groth16.Proof, groth16.VerifyingKey, time.Duration, time.Duration, error) { +func generateRotate90Proof(backend string, original, rotated [][][]uint8) (io.WriterTo, io.WriterTo, time.Duration, time.Duration, error) { var circuit Rotate90Circuit circuit.Original = make([][][]frontend.Variable, len(original)) // First dimension for i := range original { @@ -146,9 +149,9 @@ func generateRotate90Proof(original, rotated [][][]uint8) (groth16.Proof, groth1 } t0 := time.Now() - cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + cs, err := compileCircuit(backend, &circuit) if err != nil { - panic(err) + return nil, nil, 0, 0, err } fmt.Println("Rotate90 compilation time:", time.Since(t0).Seconds()) @@ -163,12 +166,7 @@ func generateRotate90Proof(original, rotated [][][]uint8) (groth16.Proof, groth1 return nil, nil, 0, 0, err } - pk, vk, err := groth16.Setup(cs) - if err != nil { - return nil, nil, 0, 0, err - } - - proof, err := groth16.Prove(cs, pk, witness) + proof, vk, err := generateProofByBackend(backend, cs, witness) if err != nil { return nil, nil, 0, 0, err } @@ -186,8 +184,7 @@ type Rotate90Circuit struct { } func (c *Rotate90Circuit) Define(api frontend.API) error { - api.AssertIsDifferent(len(c.Original), 0) - api.AssertIsDifferent(len(c.Rotated), 0) + // TODO(dhruv): Add AssertIsDifferent to compare len(Original) with 0. api.AssertIsEqual(len(c.Original), len(c.Rotated[0])) api.AssertIsEqual(len(c.Original[0]), len(c.Rotated)) diff --git a/cmd/rotate90_test.go b/cmd/rotate90_test.go index 8dadc8d..76f83b4 100644 --- a/cmd/rotate90_test.go +++ b/cmd/rotate90_test.go @@ -19,6 +19,7 @@ func TestBenchmarkRotate90(t *testing.T) { heightStartNew int widthNew int heightNew int + backend string }{ { name: "rotate90_xsmall", @@ -27,6 +28,7 @@ func TestBenchmarkRotate90(t *testing.T) { heightStartNew: 0, widthNew: 10, heightNew: 10, + backend: "groth16", }, { name: "rotate90_small", @@ -35,6 +37,7 @@ func TestBenchmarkRotate90(t *testing.T) { heightStartNew: 0, widthNew: 100, heightNew: 100, + backend: "groth16", }, { name: "rotate90_medium", @@ -43,6 +46,7 @@ func TestBenchmarkRotate90(t *testing.T) { heightStartNew: 0, widthNew: 250, heightNew: 250, + backend: "groth16", }, { name: "rotate90_large", @@ -51,6 +55,7 @@ func TestBenchmarkRotate90(t *testing.T) { heightStartNew: 0, widthNew: 500, heightNew: 500, + backend: "groth16", }, { name: "rotate90_xlarge", @@ -59,6 +64,52 @@ func TestBenchmarkRotate90(t *testing.T) { heightStartNew: 0, widthNew: 750, heightNew: 750, + backend: "groth16", + }, + { + name: "rotate90_xsmall", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 10, + heightNew: 10, + backend: "plonk", + }, + { + name: "rotate90_small", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 100, + heightNew: 100, + backend: "plonk", + }, + { + name: "rotate90_medium", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 250, + heightNew: 250, + backend: "plonk", + }, + { + name: "rotate90_large", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 500, + heightNew: 500, + backend: "plonk", + }, + { + name: "rotate90_xlarge", + originalImg: "../sample/original-1000x1000.png", + widthStartNew: 0, + heightStartNew: 0, + widthNew: 750, + heightNew: 750, + backend: "plonk", }, } @@ -68,8 +119,8 @@ func TestBenchmarkRotate90(t *testing.T) { fmt.Fprintln(mdFile, "## Rotate 90") // Write the Markdown table headers - fmt.Fprintln(mdFile, "| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) |") - fmt.Fprintln(mdFile, "|---|---|---|---|") + fmt.Fprintln(mdFile, "| Original Size | Circuit compilation (s) | Proving time (s) | Proof size (bytes) | Backend |") + fmt.Fprintln(mdFile, "|---|---|---|---|---|") mdFile.Close() for _, tt := range tests { @@ -87,6 +138,7 @@ func TestBenchmarkRotate90(t *testing.T) { finalImg: finalImg, proofDir: dir, markdownFile: mdFilePath, + backend: tt.backend, } err := proveRotate90(conf) require.NoError(t, err) diff --git a/sample/original2.png b/sample/original2.png deleted file mode 100644 index 3e1abdc..0000000 Binary files a/sample/original2.png and /dev/null differ diff --git a/sample/rotated2.png b/sample/rotated2.png deleted file mode 100644 index e4df1fb..0000000 Binary files a/sample/rotated2.png and /dev/null differ