2025-06-02 12:31:07 +02:00
|
|
|
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"
|
2025-06-04 11:49:29 +02:00
|
|
|
"path/filepath"
|
2025-06-02 12:31:07 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
2025-06-04 11:49:29 +02:00
|
|
|
circuitName := filepath.Base(*circuitPath)
|
|
|
|
|
log.Info().Msgf("Running gnark plonky2 verifier for %s circuit with proof system %s", circuitName, *proofSystem)
|
2025-06-02 12:31:07 +02:00
|
|
|
|
|
|
|
|
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" {
|
2025-06-04 11:49:29 +02:00
|
|
|
r1cs, pk, vk, err := CompileVerifierCircuitPlonk(circuitPath, dummySetup)
|
2025-06-02 12:31:07 +02:00
|
|
|
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().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().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")
|
|
|
|
|
}
|
|
|
|
|
}
|