mirror of
https://github.com/logos-storage/proof-aggregation.git
synced 2026-01-02 13:53:13 +00:00
add gnark-plonky2-verifier cli
This commit is contained in:
parent
ab1da40461
commit
a56030d9ac
23
gnark-wrapper/.gitignore
vendored
Normal file
23
gnark-wrapper/.gitignore
vendored
Normal 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
79
gnark-wrapper/README.md
Normal 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
207
gnark-wrapper/circuit.go
Normal 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
239
gnark-wrapper/cli.go
Normal 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
19
gnark-wrapper/compile.sh
Executable 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
32
gnark-wrapper/go.mod
Normal 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
65
gnark-wrapper/go.sum
Normal 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
16
gnark-wrapper/prove.sh
Normal 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
244
gnark-wrapper/prover.go
Normal 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
14
gnark-wrapper/test.sh
Normal 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}"
|
||||
1
gnark-wrapper/testdata/dummy/common_circuit_data.json
vendored
Normal file
1
gnark-wrapper/testdata/dummy/common_circuit_data.json
vendored
Normal 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":[]}
|
||||
1
gnark-wrapper/testdata/dummy/proof_with_public_inputs.json
vendored
Normal file
1
gnark-wrapper/testdata/dummy/proof_with_public_inputs.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
gnark-wrapper/testdata/dummy/verifier_only_circuit_data.json
vendored
Normal file
1
gnark-wrapper/testdata/dummy/verifier_only_circuit_data.json
vendored
Normal 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
145
gnark-wrapper/verifier.go
Normal 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
16
gnark-wrapper/verify.sh
Normal 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
|
||||
Loading…
x
Reference in New Issue
Block a user