add gnark-plonky2-verifier cli

This commit is contained in:
M Alghazwi 2025-06-02 12:31:07 +02:00
parent ab1da40461
commit a56030d9ac
No known key found for this signature in database
GPG Key ID: 646E567CAD7DB607
15 changed files with 1102 additions and 0 deletions

23
gnark-wrapper/.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
gnark-ed25519
gnark.pprof
verifier
/gnark_output
# Output from pprof visualization
verifier.png
# Output from aztec ignition
data/

79
gnark-wrapper/README.md Normal file
View File

@ -0,0 +1,79 @@
# GNARK-Plonky2 Verifier CLI
This repository provides a Go-based CLI for compiling, proving, and verifying Plonky2-wrapped circuits using GNARK (either Plonk or Groth16). It automates:
- **Compilation** of the plonky2 verifier circuit (R1CS, PK, VK).
- **Proof generation** for compiled circuits.
- **Proof verification**.
---
## Prerequisites
- **Go 1.22+** installed.
---
## Installation
Clone this repository:
```bash
git clone https://github.com/codex-storage/proof-aggregation.git
cd proof-aggregation/gnark-wrapper
go mod tidy
chmod +x compile.sh prove.sh verify.sh test.sh
```
## Building the Verifier Binary
```bash
go build -o verifier .
```
## CLI Usage
The verifier binary has three modes:
`-compile`: Compiles circuit (outputs R1CS, PK, VK, Solidity contract).
`-prove`: Generates a proof for the compiled circuit.
`-verify`: Verifies an existing proof.
### Flags:
| Flag | Description | Default |
| --------------- | --------------------------------------- | ------------------ |
| `-circuit` | Directory containing Plonky2 JSON files | `./testdata/dummy` |
| `-data` | Output directory | `./gnark_output` |
| `-proof-system` | `"plonk"` or `"groth16"` | `"groth16"` |
| `-dummy` | Dummy setup (Groth16 only) | `"false"` |
| `-contract` | Generate Solidity verifier | `"true"` |
## Workflow
1. Prepare your Plonky2 JSON folder
This folder `testdata/dummy` must contain:
- `verifier_only_circuit_data.json`
- `proof_with_public_inputs.json`
- `common_circuit_data.json`
2. Compile:
```bash
./compile.sh ./testdata/dummy ./gnark_output groth16 false
```
Produces ./gnark_output/groth16/r1cs.bin, pk.bin, vk.bin, and Verifier.sol.
3. Prove:
```bash
./prove.sh ./testdata/dummy ./gnark_output groth16 false
```
Produces ./gnark_output/groth16/proof.json and public_witness.bin.
4. Verify:
```bash
./verify.sh ./testdata/dummy ./gnark_output groth16 false
```
Checks proof.json + vk.bin + public_witness.bin.
5. (Optional) Full end-to-end
```bash
./test.sh ./testdata/dummy ./gnark_output groth16 false
```
Calls compile → prove → verify in sequence.

207
gnark-wrapper/circuit.go Normal file
View File

@ -0,0 +1,207 @@
package main
import (
"fmt"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/frontend/cs/r1cs"
"io"
"os"
"time"
gl "github.com/codex-storage/gnark-plonky2-verifier/goldilocks"
"github.com/codex-storage/gnark-plonky2-verifier/trusted_setup"
"github.com/codex-storage/gnark-plonky2-verifier/types"
"github.com/codex-storage/gnark-plonky2-verifier/variables"
"github.com/codex-storage/gnark-plonky2-verifier/verifier"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark-crypto/kzg"
"github.com/consensys/gnark/backend/plonk"
"github.com/consensys/gnark/constraint"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/frontend/cs/scs"
"github.com/consensys/gnark/logger"
)
type Plonky2VerifierCircuit struct {
// inputs to the circuit
PublicInputs []gl.Variable `gnark:"PublicInput,public"`
Proof variables.Proof `gnark:"-"`
VerifierData variables.VerifierOnlyCircuitData `gnark:"PublicInput,public"`
// Circuit configuration - common data
CommonCircuitData types.CommonCircuitData
}
func (c *Plonky2VerifierCircuit) Define(api frontend.API) error {
// initialize the verifier chip
verifierChip := verifier.NewVerifierChip(api, c.CommonCircuitData)
// verify the plonky2 proof
verifierChip.Verify(c.Proof, c.PublicInputs, c.VerifierData)
return nil
}
func CompileVerifierCircuitPlonk(CircuitPath string) (constraint.ConstraintSystem, plonk.ProvingKey, plonk.VerifyingKey, error) {
log := logger.Logger()
verifierOnlyCircuitData := variables.DeserializeVerifierOnlyCircuitData(
types.ReadVerifierOnlyCircuitData(CircuitPath + "/verifier_only_circuit_data.json"),
)
proofWithPis := variables.DeserializeProofWithPublicInputs(
types.ReadProofWithPublicInputs(CircuitPath + "/proof_with_public_inputs.json"),
)
commonCircuitData := types.ReadCommonCircuitData(CircuitPath + "/common_circuit_data.json")
circuit := Plonky2VerifierCircuit{
PublicInputs: proofWithPis.PublicInputs,
Proof: proofWithPis.Proof,
VerifierData: verifierOnlyCircuitData,
CommonCircuitData: commonCircuitData,
}
r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &circuit)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to compile circuit: %w", err)
}
log.Info().Msg("Successfully compiled verifier circuit")
log.Info().Msg("Loading SRS - this will take some time")
fileName := CircuitPath + "srs_setup"
if _, err := os.Stat(fileName); os.IsNotExist(err) {
trusted_setup.DownloadAndSaveAztecIgnitionSrs(174, fileName)
}
fSRS, err := os.Open(fileName)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to open srs file: %w", err)
}
var srs kzg.SRS = kzg.NewSRS(ecc.BN254)
_, err = srs.ReadFrom(fSRS)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to read srs file: %w", err)
}
fSRS.Close()
log.Info().Msg("Successfully loaded SRS")
log.Info().Msg("Running circuit setup")
start := time.Now()
pk, vk, err := plonk.Setup(r1cs, srs)
if err != nil {
return nil, nil, nil, err
}
elapsed := time.Since(start)
log.Info().Msg("Successfully ran circuit setup, time: " + elapsed.String())
return r1cs, pk, vk, nil
}
func CompileVerifierCircuitGroth16(CircuitPath string, IsDummy bool) (constraint.ConstraintSystem, groth16.ProvingKey, groth16.VerifyingKey, error) {
log := logger.Logger()
verifierOnlyCircuitData := variables.DeserializeVerifierOnlyCircuitData(
types.ReadVerifierOnlyCircuitData(CircuitPath + "/verifier_only_circuit_data.json"),
)
proofWithPis := variables.DeserializeProofWithPublicInputs(
types.ReadProofWithPublicInputs(CircuitPath + "/proof_with_public_inputs.json"),
)
commonCircuitData := types.ReadCommonCircuitData(CircuitPath + "/common_circuit_data.json")
circuit := Plonky2VerifierCircuit{
PublicInputs: proofWithPis.PublicInputs,
Proof: proofWithPis.Proof,
VerifierData: verifierOnlyCircuitData,
CommonCircuitData: commonCircuitData,
}
r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to compile circuit: %w", err)
}
log.Info().Msg("Successfully compiled verifier circuit")
var pk groth16.ProvingKey
var vk groth16.VerifyingKey
fmt.Println("Running circuit setup")
start := time.Now()
if IsDummy {
fmt.Println("Using dummy setup")
pk, err = groth16.DummySetup(r1cs)
} else {
fmt.Println("Using real setup")
pk, vk, err = groth16.Setup(r1cs)
}
if err != nil {
return nil, nil, nil, err
}
elapsed := time.Since(start)
log.Info().Msg("Successfully ran circuit setup, time: " + elapsed.String())
return r1cs, pk, vk, nil
}
type rawKeyWriter interface {
WriteRawTo(io.Writer) (int64, error)
}
// SaveVerifierCircuit will write out
// - r1cs (via WriteTo)
// - pk (via WriteRawTo)
// - vk (via WriteRawTo)
//
// It works for both Plonk and Groth16 proving/verifying keys.
func SaveVerifierCircuit[PK, VK rawKeyWriter](
path string,
r1cs constraint.ConstraintSystem,
pk PK,
vk VK,
isDummy bool,
) error {
log := logger.Logger()
// make sure directory exists
if err := os.MkdirAll(path, 0o755); err != nil {
return fmt.Errorf("mkdir %s: %w", path, err)
}
// rics constraints
log.Info().Msgf("Saving circuit constraints to %s/r1cs.bin", path)
r1csF, err := os.Create(path + "/r1cs.bin")
if err != nil {
return fmt.Errorf("create r1cs.bin: %w", err)
}
start := time.Now()
if _, err := r1cs.WriteTo(r1csF); err != nil {
r1csF.Close()
return fmt.Errorf("write r1cs: %w", err)
}
r1csF.Close()
log.Debug().Msg("Successfully saved circuit constraints, time: " + time.Since(start).String())
// proving key
log.Info().Msgf("Saving proving key to %s/pk.bin", path)
pkF, err := os.Create(path + "/pk.bin")
if err != nil {
return fmt.Errorf("create pk.bin: %w", err)
}
start = time.Now()
if _, err := pk.WriteRawTo(pkF); err != nil {
pkF.Close()
return fmt.Errorf("write pk: %w", err)
}
pkF.Close()
log.Debug().Msg("Successfully saved proving key, time: " + time.Since(start).String())
// verifying key - only saved if not using dummy setup
if !isDummy {
log.Info().Msgf("Saving verifying key to %s/vk.bin", path)
vkF, err := os.Create(path + "/vk.bin")
if err != nil {
return fmt.Errorf("create vk.bin: %w", err)
}
start = time.Now()
_, err = vk.WriteRawTo(vkF)
if err != nil {
vkF.Close()
return fmt.Errorf("write vk: %w", err)
}
vkF.Close()
log.Debug().Msg("Successfully saved verifying key, time: " + time.Since(start).String())
}
return nil
}

239
gnark-wrapper/cli.go Normal file
View File

@ -0,0 +1,239 @@
package main
import (
_ "embed"
"flag"
"fmt"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/backend/plonk"
"github.com/consensys/gnark/logger"
"github.com/rs/zerolog/log"
"os"
)
func main() {
circuitPath := flag.String("circuit", "", "circuit data directory")
dataPath := flag.String("data", "", "data directory")
proofSystem := flag.String("proof-system", "groth16", "proof system to benchmark")
dummySetup := flag.Bool("dummy", true, "use dummy setup")
proofFlag := flag.Bool("prove", false, "create a proof")
verifyFlag := flag.Bool("verify", false, "verify a proof")
compileFlag := flag.Bool("compile", false, "Compile and save the universal verifier circuit")
contractFlag := flag.Bool("contract", true, "Generate solidity contract")
flag.Parse()
log := logger.Logger()
log.Info().Msgf("Running gnark plonky2 verifier for %s circuit with proof system %s", *circuitPath, *proofSystem)
if *circuitPath == "" {
log.Info().Msg("no circuitPath flag found, please specify one")
flag.Usage()
os.Exit(1)
}
if *dataPath == "" {
log.Error().Msg("please specify a path to data dir (where the compiled gnark circuit data will be)")
flag.Usage()
os.Exit(1)
}
if *proofSystem == "plonk" {
*dataPath = *dataPath + "/plonk"
} else if *proofSystem == "groth16" {
*dataPath = *dataPath + "/groth16"
} else {
panic("Please provide a valid proof system to benchmark, we only support plonk and groth16")
}
log.Debug().Msg("Circuit path: " + *circuitPath)
log.Debug().Msg("Data path: " + *dataPath)
if *compileFlag {
CompileVerifierCircuit(*circuitPath, *dataPath, *contractFlag, *proofSystem, *dummySetup)
}
if *proofFlag {
ProveCircuit(*circuitPath, *dataPath, *proofSystem, *dummySetup)
}
if *verifyFlag {
if *dummySetup {
fmt.Println("You're using dummy setup so we skip verification of proof")
return
} else {
VerifyProof(*dataPath, *proofSystem)
}
}
}
func CompileVerifierCircuit(circuitPath string, dataPath string, contractFlag bool, proofSystem string, dummySetup bool) {
log.Info().Msg("compiling verifier circuit")
if proofSystem == "plonk" {
r1cs, pk, vk, err := CompileVerifierCircuitPlonk(circuitPath)
if err != nil {
log.Error().Msg("failed to compile verifier circuit:" + err.Error())
os.Exit(1)
}
err = SaveVerifierCircuit(dataPath, r1cs, pk, vk, dummySetup)
if err != nil {
log.Error().Msg("failed to save verifier circuit:" + err.Error())
os.Exit(1)
}
if contractFlag {
log.Info().Msg("generating solidity contract")
err := ExportIFunctionVerifierSolidity(dataPath, vk)
if err != nil {
log.Error().Msg("failed to generate solidity contract:" + err.Error())
os.Exit(1)
}
}
} else if proofSystem == "groth16" {
r1cs, pk, vk, err := CompileVerifierCircuitGroth16(circuitPath, dummySetup)
if err != nil {
log.Error().Msg("failed to compile verifier circuit:" + err.Error())
os.Exit(1)
}
err = SaveVerifierCircuit(dataPath, r1cs, pk, vk, dummySetup)
if err != nil {
log.Error().Msg("failed to save verifier circuit:" + err.Error())
os.Exit(1)
}
if contractFlag && !dummySetup {
log.Info().Msg("generating solidity contract")
err := ExportIFunctionVerifierSolidity(dataPath, vk)
if err != nil {
log.Error().Msg("failed to generate solidity contract:" + err.Error())
os.Exit(1)
}
}
} else {
panic("Please provide a valid proof system to benchmark, we only support plonk and groth16")
}
}
func ProveCircuit(circuitPath string, dataPath string, proofSystem string, isDummy bool) {
log.Info().Msg("Generating the witness")
witness, err := GetWitness(circuitPath)
if err != nil {
log.Err(err).Msg("failed to create the witness")
os.Exit(1)
}
if proofSystem == "plonk" {
log.Info().Msg("loading the plonk proving key, circuit data and verifying key")
r1cs, pk, err := LoadPlonkProverData(dataPath)
if err != nil {
log.Err(err).Msg("failed to load the verifier circuit")
os.Exit(1)
}
vk, err := LoadPlonkVerifierKey(dataPath)
if err != nil {
log.Err(err).Msg("failed to load the verifier key")
os.Exit(1)
}
log.Info().Msg("Generating the proof")
proof, err := ProvePlonk(dataPath, r1cs, pk, witness)
if err != nil {
log.Err(err).Msg("failed to create the proof")
os.Exit(1)
}
log.Info().Msg("Sanity check: verifying proof")
publicWitness, err := witness.Public()
err = plonk.Verify(proof, vk, publicWitness)
if err != nil {
log.Err(err).Msg("failed sanity check to verify proof")
os.Exit(1)
}
log.Info().Msgf("number of public input: %s", publicWitness)
log.Info().Msg("Successfully passed sanity check - proof verification")
} else if proofSystem == "groth16" {
log.Info().Msg("loading the Groth16 proving key, circuit data and verifying key")
r1cs, pk, err := LoadGroth16ProverData(dataPath)
if err != nil {
log.Err(err).Msg("failed to load the verifier circuit")
os.Exit(1)
}
var vk groth16.VerifyingKey
if !isDummy {
vk, err = LoadGroth16VerifierKey(dataPath)
if err != nil {
log.Err(err).Msg("failed to load the verifier key")
os.Exit(1)
}
}
log.Info().Msg("Generating the proof")
proof, err := ProveGroth16(dataPath, r1cs, pk, witness)
if err != nil {
log.Err(err).Msg("failed to create the proof")
os.Exit(1)
}
if !isDummy {
log.Info().Msg("Sanity check: verifying proof")
publicWitness, err := witness.Public()
err = groth16.Verify(proof, vk, publicWitness)
if err != nil {
log.Err(err).Msg("failed sanity check to verify proof")
os.Exit(1)
}
log.Info().Msgf("number of public input: %s", publicWitness)
log.Info().Msg("Successfully passed sanity check - proof verification")
}
} else {
panic("Please provide a valid proof system to benchmark, we only support plonk and groth16")
}
}
func VerifyProof(dataPath string, proofSystem string) {
log.Info().Msg("loading the proof, verifying key and public inputs")
publicWitness, err := LoadPublicWitness(dataPath)
if err != nil {
log.Err(err).Msg("failed to load the public witness")
os.Exit(1)
}
if proofSystem == "plonk" {
vk, err := LoadPlonkVerifierKey(dataPath)
if err != nil {
log.Err(err).Msg("failed to load the verifier key")
os.Exit(1)
}
proof, err := LoadPlonkProof(dataPath)
if err != nil {
log.Err(err).Msg("failed to load the proof")
os.Exit(1)
}
err = plonk.Verify(proof, vk, publicWitness)
if err != nil {
log.Err(err).Msg("failed to verify proof")
os.Exit(1)
}
log.Info().Msg("Successfully verified proof")
} else if proofSystem == "groth16" {
vk, err := LoadGroth16VerifierKey(dataPath)
if err != nil {
log.Err(err).Msg("failed to load the verifier key")
os.Exit(1)
}
proof, err := LoadGroth16Proof(dataPath)
if err != nil {
log.Err(err).Msg("failed to load the proof")
os.Exit(1)
}
err = groth16.Verify(proof, vk, publicWitness)
if err != nil {
log.Err(err).Msg("failed to verify proof")
os.Exit(1)
}
log.Info().Msg("Successfully verified proof")
} else {
panic("Please provide a valid proof system to benchmark, we only support plonk and groth16")
}
}

19
gnark-wrapper/compile.sh Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail
# Usage: ./compile.sh <circuit_dir> <data_dir> <proof_system> <dummy_setup>
CIRCUIT_DIR=${1:-"$PWD/testdata/dummy"} # path to your Plonky2 JSON folder
DATA_DIR=${2:-"$PWD/gnark_output"} # where to save gnark outputs
PROOF_SYSTEM=${3:-"groth16"} # "plonk" or "groth16"
DUMMY=${4:-"false"} # only used for groth16 dummy setup
echo "Building verifier binary..."
go build -o verifier .
echo "Compiling circuit ($PROOF_SYSTEM)…"
./verifier \
-circuit "${CIRCUIT_DIR}" \
-data "${DATA_DIR}" \
-proof-system "${PROOF_SYSTEM}" \
-dummy="${DUMMY}" \
-compile

32
gnark-wrapper/go.mod Normal file
View File

@ -0,0 +1,32 @@
module github.com/codex-storage/proof-aggregation/gnark-wrapper
go 1.20
require (
github.com/codex-storage/gnark-plonky2-verifier v0.0.0-20250527085145-0fde8cf39b5f
github.com/consensys/gnark v0.9.1
github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb
github.com/rs/zerolog v1.31.0
)
require (
github.com/bits-and-blooms/bitset v1.20.0 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/consensys/bavard v0.1.27 // indirect
github.com/consensys/gnark-ignition-verifier v0.0.0-20230527014722-10693546ab33 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
github.com/x448/float16 v0.8.4 // indirect
golang.org/x/crypto v0.35.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
)

65
gnark-wrapper/go.sum Normal file
View File

@ -0,0 +1,65 @@
github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU=
github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/codex-storage/gnark-plonky2-verifier v0.0.0-20250527085145-0fde8cf39b5f h1:Ryvf7so/6s3/gXu+qufX4KnibgSvyX45rKYvVXWkv08=
github.com/codex-storage/gnark-plonky2-verifier v0.0.0-20250527085145-0fde8cf39b5f/go.mod h1:cPuoiO7TeRAULGcyJhWiVbFHJzAbHYY1tcRhi6ucrE4=
github.com/consensys/bavard v0.1.27 h1:j6hKUrGAy/H+gpNrpLU3I26n1yc+VMGmd6ID5+gAhOs=
github.com/consensys/bavard v0.1.27/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs=
github.com/consensys/gnark v0.9.1 h1:aTwBp5469MY/2jNrf4ABrqHRW3+JytfkADdw4ZBY7T0=
github.com/consensys/gnark v0.9.1/go.mod h1:udWvWGXnfBE7mn7BsNoGAvZDnUhcONBEtNijvVjfY80=
github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb h1:f0BMgIjhZy4lSRHCXFbQst85f5agZAjtDMixQqBWNpc=
github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
github.com/consensys/gnark-ignition-verifier v0.0.0-20230527014722-10693546ab33 h1:z42ewLaLxoTYeQ17arcF4WExZc/eSaN3YVlF7eEaPt4=
github.com/consensys/gnark-ignition-verifier v0.0.0-20230527014722-10693546ab33/go.mod h1:JdKor28c/KR4BbznP88bz8AAvnCgovzrB3KWsiR7lwk=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE=
github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ=
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU=
github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=

16
gnark-wrapper/prove.sh Normal file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
# Usage: ./prove.sh <circuit_dir> <data_dir> [proof_system]
CIRCUIT_DIR=${1:-"$PWD/testdata/dummy"}
DATA_DIR=${2:-"$PWD/gnark_output"}
PROOF_SYSTEM=${3:-"groth16"}
DUMMY=${4:-"false"}
echo "Generating proof ($PROOF_SYSTEM)…"
./verifier \
-circuit "${CIRCUIT_DIR}" \
-data "${DATA_DIR}" \
-proof-system "${PROOF_SYSTEM}" \
-dummy="${DUMMY}" \
-prove

244
gnark-wrapper/prover.go Normal file
View File

@ -0,0 +1,244 @@
package main
import (
"bufio"
"encoding/json"
"fmt"
"github.com/consensys/gnark/backend/groth16"
groth16_bn254 "github.com/consensys/gnark/backend/groth16/bn254"
plonk_bn254 "github.com/consensys/gnark/backend/plonk/bn254"
"os"
"time"
gnark_verifier_types "github.com/codex-storage/gnark-plonky2-verifier/types"
"github.com/codex-storage/gnark-plonky2-verifier/variables"
"github.com/consensys/gnark-crypto/ecc"
"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/logger"
)
func loadR1CS(path string) (constraint.ConstraintSystem, error) {
log := logger.Logger()
r1csFile, err := os.Open(path + "/r1cs.bin")
if err != nil {
return nil, fmt.Errorf("failed to open r1cs file: %w", err)
}
r1cs := plonk.NewCS(ecc.BN254)
start := time.Now()
r1csReader := bufio.NewReader(r1csFile)
_, err = r1cs.ReadFrom(r1csReader)
if err != nil {
return nil, fmt.Errorf("failed to read r1cs file: %w", err)
}
r1csFile.Close()
elapsed := time.Since(start)
log.Debug().Msg("Successfully loaded constraint system, time: " + elapsed.String())
return r1cs, nil
}
func LoadPlonkProverData(path string) (constraint.ConstraintSystem, plonk.ProvingKey, error) {
log := logger.Logger()
r1cs, err := loadR1CS(path)
if err != nil {
return nil, nil, fmt.Errorf("failed to load r1cs file: %w", err)
}
pkFile, err := os.Open(path + "/pk.bin")
if err != nil {
return nil, nil, fmt.Errorf("failed to open pk file: %w", err)
}
pk := plonk.NewProvingKey(ecc.BN254)
start := time.Now()
pkReader := bufio.NewReader(pkFile)
_, err = pk.ReadFrom(pkReader)
if err != nil {
return nil, nil, fmt.Errorf("failed to read pk file: %w", err)
}
pkFile.Close()
elapsed := time.Since(start)
log.Debug().Msg("Successfully loaded proving key, time: " + elapsed.String())
return r1cs, pk, nil
}
func LoadGroth16ProverData(path string) (constraint.ConstraintSystem, groth16.ProvingKey, error) {
log := logger.Logger()
r1cs, err := loadR1CS(path)
if err != nil {
return nil, nil, fmt.Errorf("failed to load r1cs file: %w", err)
}
pkFile, err := os.Open(path + "/pk.bin")
if err != nil {
return nil, nil, fmt.Errorf("failed to open pk file: %w", err)
}
pk := groth16.NewProvingKey(ecc.BN254)
start := time.Now()
pkReader := bufio.NewReader(pkFile)
_, err = pk.ReadFrom(pkReader)
if err != nil {
return nil, nil, fmt.Errorf("failed to read pk file: %w", err)
}
pkFile.Close()
elapsed := time.Since(start)
log.Debug().Msg("Successfully loaded proving key, time: " + elapsed.String())
return r1cs, pk, nil
}
func GetWitness(circuitPath string) (witness.Witness, error) {
log := logger.Logger()
verifierOnlyCircuitData := variables.DeserializeVerifierOnlyCircuitData(
gnark_verifier_types.ReadVerifierOnlyCircuitData(circuitPath + "/verifier_only_circuit_data.json"),
)
proofWithPis := gnark_verifier_types.ReadProofWithPublicInputs(circuitPath + "/proof_with_public_inputs.json")
proofWithPisVariable := variables.DeserializeProofWithPublicInputs(proofWithPis)
// Circuit assignment
assignment := &Plonky2VerifierCircuit{
Proof: proofWithPisVariable.Proof,
PublicInputs: proofWithPisVariable.PublicInputs,
VerifierData: verifierOnlyCircuitData,
}
log.Debug().Msg("Generating witness")
start := time.Now()
witness, err := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
if err != nil {
return nil, fmt.Errorf("failed to generate witness: %w", err)
}
elapsed := time.Since(start)
log.Debug().Msg("Successfully generated witness, time: " + elapsed.String())
return witness, nil
}
func ProvePlonk(dataPath string, r1cs constraint.ConstraintSystem, pk plonk.ProvingKey, witness witness.Witness) (plonk.Proof, error) {
log := logger.Logger()
log.Debug().Msg("Creating proof")
start := time.Now()
proof, err := plonk.Prove(r1cs, pk, witness)
if err != nil {
return nil, fmt.Errorf("failed to create proof: %w", err)
}
elapsed := time.Since(start)
log.Info().Msg("Successfully created proof, time: " + elapsed.String())
// export proof
err = ExportPlonkProof(dataPath, proof)
if err != nil {
return nil, err
}
// export witness
publicWitness, err := witness.Public()
err = ExportWitness(dataPath, publicWitness)
if err != nil {
return nil, err
}
return proof, nil
}
func ProveGroth16(dataPath string, r1cs constraint.ConstraintSystem, pk groth16.ProvingKey, witness witness.Witness) (groth16.Proof, error) {
log := logger.Logger()
log.Debug().Msg("Creating proof")
start := time.Now()
proof, err := groth16.Prove(r1cs, pk, witness)
if err != nil {
return nil, fmt.Errorf("failed to create proof: %w", err)
}
elapsed := time.Since(start)
log.Info().Msg("Successfully created proof, time: " + elapsed.String())
// export proof
err = ExportGroth16Proof(dataPath, proof)
if err != nil {
return nil, err
}
// export witness
publicWitness, err := witness.Public()
err = ExportWitness(dataPath, publicWitness)
if err != nil {
return nil, err
}
return proof, nil
}
func ExportWitness(circuitPath string, witness witness.Witness) error {
log := logger.Logger()
publicWitness, err := witness.Public()
if err != nil {
return fmt.Errorf("failed to get public witness: %w", err)
}
log.Info().Msg("Saving public witness to public_witness.bin")
witnessFile, err := os.Create(circuitPath + "/public_witness.bin")
if err != nil {
return fmt.Errorf("failed to create public witness file: %w", err)
}
_, err = publicWitness.WriteTo(witnessFile)
if err != nil {
return fmt.Errorf("failed to write public witness file: %w", err)
}
witnessFile.Close()
log.Info().Msg("Successfully saved public witness")
return nil
}
func ExportPlonkProof(circuitPath string, proof plonk.Proof) error {
log := logger.Logger()
_proof := proof.(*plonk_bn254.Proof)
log.Info().Msg("Saving proof to proof.json")
jsonProof, err := json.Marshal(_proof.MarshalSolidity())
if err != nil {
return fmt.Errorf("failed to marshal proof: %w", err)
}
proofFile, err := os.Create(circuitPath + "/proof.json")
if err != nil {
return fmt.Errorf("failed to create proof file: %w", err)
}
_, err = proofFile.Write(jsonProof)
if err != nil {
return fmt.Errorf("failed to write proof file: %w", err)
}
proofFile.Close()
log.Info().Msg("Successfully saved proof")
return nil
}
func ExportGroth16Proof(circuitPath string, proof groth16.Proof) error {
log := logger.Logger()
_proof := proof.(*groth16_bn254.Proof)
log.Info().Msg("Saving proof to proof.json")
jsonProof, err := json.Marshal(_proof)
if err != nil {
return fmt.Errorf("failed to marshal proof: %w", err)
}
proofFile, err := os.Create(circuitPath + "/proof.json")
if err != nil {
return fmt.Errorf("failed to create proof file: %w", err)
}
_, err = proofFile.Write(jsonProof)
if err != nil {
return fmt.Errorf("failed to write proof file: %w", err)
}
proofFile.Close()
log.Info().Msg("Successfully saved proof")
return nil
}

14
gnark-wrapper/test.sh Normal file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail
# Usage: ./test.sh <circuit_dir> <data_dir> <proof_system> <dummy_setup>
CIRCUIT_DIR=${1:-"$PWD/testdata/dummy"} # path to your Plonky2 JSON folder
DATA_DIR=${2:-"$PWD/gnark_output"} # where to save gnark outputs
PROOF_SYSTEM=${3:-"groth16"} # "plonk" or "groth16"
DUMMY=${4:-"false"} # only used for groth16 dummy setup
echo "Running full test: compile → prove → verify"
./compile.sh "${CIRCUIT_DIR}" "${DATA_DIR}" "${PROOF_SYSTEM}" "${DUMMY}"
./prove.sh "${CIRCUIT_DIR}" "${DATA_DIR}" "${PROOF_SYSTEM}" "${DUMMY}"
./verify.sh "${CIRCUIT_DIR}" "${DATA_DIR}" "${PROOF_SYSTEM}" "${DUMMY}"

View File

@ -0,0 +1 @@
{"config":{"num_wires":135,"num_routed_wires":80,"num_constants":2,"use_base_arithmetic_gate":true,"security_bits":100,"num_challenges":2,"zero_knowledge":false,"max_quotient_degree_factor":8,"fri_config":{"rate_bits":3,"cap_height":4,"proof_of_work_bits":16,"reduction_strategy":{"ConstantArityBits":[4,5]},"num_query_rounds":28}},"fri_params":{"config":{"rate_bits":3,"cap_height":4,"proof_of_work_bits":16,"reduction_strategy":{"ConstantArityBits":[4,5]},"num_query_rounds":28},"hiding":false,"degree_bits":11,"reduction_arity_bits":[4,4]},"gates":["NoopGate","ConstantGate { num_consts: 2 }","PoseidonMdsGate(PhantomData<plonky2_field::goldilocks_field::GoldilocksField>)<WIDTH=12>","PublicInputGate","BaseSumGate { num_limbs: 63 } + Base: 2","ReducingExtensionGate { num_coeffs: 32 }","ReducingGate { num_coeffs: 43 }","ArithmeticExtensionGate { num_ops: 10 }","ArithmeticGate { num_ops: 20 }","MulExtensionGate { num_ops: 13 }","RandomAccessGate { bits: 4, num_copies: 4, num_extra_constants: 2, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>","PoseidonGate(PhantomData<plonky2_field::goldilocks_field::GoldilocksField>)<WIDTH=12>"],"selectors_info":{"selector_indices":[0,0,0,0,0,0,0,1,1,1,1,2],"groups":[{"start":0,"end":7},{"start":7,"end":11},{"start":11,"end":12}]},"quotient_degree_factor":8,"num_gate_constraints":123,"num_constants":5,"num_public_inputs":3,"k_is":[1,14293326489335486720,4700049436776250445,3541557213422017946,18196947516708736925,15817657382918473249,13907817722130613464,10952810625341944941,6203009912824666656,3300053643433736875,6744005316595460895,15739729861593455007,261242591546957104,15971894691377196519,16201670926897260089,8415742645426514154,11796957557555108937,16294407261451109534,5598800393413128961,15563455834725815206,1764867128134410509,7162174829468034425,3755871071604584538,4342271783305288164,12880969007487790240,10677306222450711949,6504175050764636243,5111390403385516632,13022173847108028602,13993386182188331211,17852688572278391749,13748656795736045903,1633629184600895140,4529011729897082393,4906629816328734350,12354457273844909068,11030994060168315240,5132927100884704451,1903334112240650810,11300350282455140548,12947495166068534688,7280050037032595918,2325750220496619057,9863469300860708700,5927058137232203163,18296775548535963806,16027760200278862284,3198226309374699824,17159143107915980371,4742102661775960192,5942453867077433164,12359909013026785218,12296487080408661428,14401603032726340600,18340875264408803468,8906999085452790476,11753455510941625388,3159781736502437645,3690235712498808163,16869124931580068791,7948505852798141842,4267625380418386787,10384476522904372165,8329181427250703158,4330207543506945610,833510845038654548,8836109905071273552,17461172238536664200,7507668114706621706,10436382014321953781,8399564173061725609,5202025295353182265,7131181789704110196,2721005760266608278,16098153662796521606,2994147549514928958,2352027076596130080,11017795050405368910,10381049954328279003,3834749477258943827],"num_partial_products":9,"num_lookup_polys":0,"num_lookup_selectors":0,"luts":[]}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"constants_sigmas_cap":["3860843344312357158629162235696507333724655140520047374410709542079942661449","11059275859379882385198542655553771596758733622131948714280002458318411971968","13932860775123048924282444895054133302030914512710287154901830116399081782095","12235866858084303863190979273488001538484919460938849648570638209640356860994","13311458094206048824270186806857871826615866511838728084268513512054371726092","21516907149586609430174018465063037990154472766278707173910165755312953625841","12581227743917758092987158814317447583402551825562423060076728599869474088832","19824905645972422700366296038955761619344054155038388748683108788180322079402","17761586161853949567683247480661828923520427518333341188670689544167726041111","15236056691195692818954727613543799525866401499970092666747842772203320578205","1135391502606579346937503302827236285954671119740130132463037527053707572155","14963561062760353287825407212867495391369201237377858522382244386241234351797","9184090315024407717617456668851098589252413203544747864280777716905449088830","13874990004190821165615096476634764705627668718578342178360710219932196693355","19695069180067444826219598133482860893718829150651381979041730465932254679567","14175687768011232455245695325744714907909584255230055555569522806817601752638"],"circuit_digest":"4150816487958351387716953124848926237482315252503823641816597524258333367110"}

145
gnark-wrapper/verifier.go Normal file
View File

@ -0,0 +1,145 @@
package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"github.com/consensys/gnark/backend/groth16"
"io"
"os"
"time"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend/plonk"
"github.com/consensys/gnark/backend/witness"
"github.com/consensys/gnark/logger"
)
func LoadPlonkVerifierKey(path string) (plonk.VerifyingKey, error) {
log := logger.Logger()
vkFile, err := os.Open(path + "/vk.bin")
if err != nil {
return nil, fmt.Errorf("failed to open vk file: %w", err)
}
vk := plonk.NewVerifyingKey(ecc.BN254)
start := time.Now()
_, err = vk.ReadFrom(vkFile)
if err != nil {
return nil, fmt.Errorf("failed to read vk file: %w", err)
}
vkFile.Close()
elapsed := time.Since(start)
log.Debug().Msg("Successfully loaded verifying key, time: " + elapsed.String())
return vk, nil
}
func LoadGroth16VerifierKey(path string) (groth16.VerifyingKey, error) {
log := logger.Logger()
vkFile, err := os.Open(path + "/vk.bin")
if err != nil {
return nil, fmt.Errorf("failed to open vk file: %w", err)
}
vk := groth16.NewVerifyingKey(ecc.BN254)
start := time.Now()
_, err = vk.ReadFrom(vkFile)
if err != nil {
return nil, fmt.Errorf("failed to read vk file: %w", err)
}
vkFile.Close()
elapsed := time.Since(start)
log.Debug().Msg("Successfully loaded verifying key, time: " + elapsed.String())
return vk, nil
}
func LoadPublicWitness(dataPath string) (witness.Witness, error) {
log := logger.Logger()
witnessFile, err := os.Open(dataPath + "/public_witness.bin")
if err != nil {
return nil, fmt.Errorf("failed to open public witness file: %w", err)
}
publicWitness, err := witness.New(ecc.BN254.ScalarField())
if err != nil {
return nil, fmt.Errorf("failed to create public witness: %w", err)
}
publicWitness.ReadFrom(witnessFile)
witnessFile.Close()
log.Debug().Msg("Successfully loaded public witness")
return publicWitness, nil
}
func LoadPlonkProof(dataPath string) (plonk.Proof, error) {
log := logger.Logger()
proofFile, err := os.Open(dataPath + "/proof.json")
if err != nil {
return nil, fmt.Errorf("failed to open proof file: %w", err)
}
proof := plonk.NewProof(ecc.BN254)
jsonProof, err := io.ReadAll(proofFile)
if err != nil {
return nil, fmt.Errorf("failed to read proof file: %w", err)
}
err = json.Unmarshal(jsonProof, proof)
if err != nil {
return nil, fmt.Errorf("failed to read proof file: %w", err)
}
proofFile.Close()
log.Debug().Msg("Successfully loaded proof")
return proof, nil
}
func LoadGroth16Proof(dataPath string) (groth16.Proof, error) {
log := logger.Logger()
proofFile, err := os.Open(dataPath + "/proof.json")
if err != nil {
return nil, fmt.Errorf("failed to open proof file: %w", err)
}
proof := groth16.NewProof(ecc.BN254)
jsonProof, err := io.ReadAll(proofFile)
if err != nil {
return nil, fmt.Errorf("failed to read proof file: %w", err)
}
err = json.Unmarshal(jsonProof, proof)
if err != nil {
return nil, fmt.Errorf("failed to read proof file: %w", err)
}
proofFile.Close()
log.Debug().Msg("Successfully loaded proof")
return proof, nil
}
type solidityExporter interface {
ExportSolidity(w io.Writer) error
}
func ExportIFunctionVerifierSolidity(path string, vk solidityExporter) error {
log := logger.Logger()
// Create a new buffer and export the VerifyingKey into it as a Solidity contract and
// convert the buffer content to a string for further manipulation.
buf := new(bytes.Buffer)
err := vk.ExportSolidity(buf)
if err != nil {
log.Err(err).Msg("failed to export verifying key to solidity")
return err
}
content := buf.String()
contractFile, err := os.Create(path + "/Verifier.sol")
if err != nil {
return err
}
w := bufio.NewWriter(contractFile)
// write the new content to the writer
_, err = w.Write([]byte(content))
if err != nil {
return err
}
contractFile.Close()
return err
}

16
gnark-wrapper/verify.sh Normal file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
# Usage: ./verify.sh <circuit_dir> <data_dir> [proof_system]
CIRCUIT_DIR=${1:-"$PWD/testdata/dummy"}
DATA_DIR=${2:-"$PWD/gnark_output"}
PROOF_SYSTEM=${3:-"groth16"}
DUMMY=${4:-"false"}
echo "Verifying proof ($PROOF_SYSTEM)…"
./verifier \
-circuit "${CIRCUIT_DIR}" \
-data "${DATA_DIR}" \
-proof-system "${PROOF_SYSTEM}" \
-dummy="${DUMMY}" \
-verify