arnaucube
arnaucube/gnark-plonky2-verifierPublic Self-hosted repository
gnark-plonky2-verifier/benchmark.go
benchmark.goRaw
  1package main
  2
  3import (
  4	"bytes"
  5	"flag"
  6	"fmt"
  7	"math/big"
  8	"os"
  9	"time"
 10
 11	gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
 12	"github.com/succinctlabs/gnark-plonky2-verifier/variables"
 13	"github.com/succinctlabs/gnark-plonky2-verifier/verifier"
 14
 15	"github.com/consensys/gnark-crypto/ecc"
 16	"github.com/consensys/gnark/backend/groth16"
 17	"github.com/consensys/gnark/constraint"
 18	"github.com/consensys/gnark/frontend"
 19	"github.com/consensys/gnark/frontend/cs/r1cs"
 20	"github.com/consensys/gnark/profile"
 21)
 22
 23type BenchmarkPlonky2VerifierCircuit struct {
 24	Proof        variables.Proof
 25	PublicInputs []gl.Variable `gnark:",public"`
 26
 27	verifierChip       *verifier.VerifierChip `gnark:"-"`
 28	plonky2CircuitName string                 `gnark:"-"`
 29}
 30
 31func (circuit *BenchmarkPlonky2VerifierCircuit) Define(api frontend.API) error {
 32	circuitDirname := "./verifier/data/" + circuit.plonky2CircuitName + "/"
 33	commonCircuitData := verifier.DeserializeCommonCircuitData(circuitDirname + "common_circuit_data.json")
 34	verifierOnlyCircuitData := verifier.DeserializeVerifierOnlyCircuitData(circuitDirname + "verifier_only_circuit_data.json")
 35
 36	circuit.verifierChip = verifier.NewVerifierChip(api, commonCircuitData)
 37
 38	circuit.verifierChip.Verify(circuit.Proof, circuit.PublicInputs, verifierOnlyCircuitData, commonCircuitData)
 39
 40	return nil
 41}
 42
 43func compileCircuit(plonky2Circuit string, profileCircuit bool, serialize bool, outputSolidity bool, dummy bool) (constraint.ConstraintSystem, groth16.ProvingKey, groth16.VerifyingKey) {
 44	circuit := BenchmarkPlonky2VerifierCircuit{
 45		plonky2CircuitName: plonky2Circuit,
 46	}
 47	proofWithPis := verifier.DeserializeProofWithPublicInputs("./verifier/data/" + plonky2Circuit + "/proof_with_public_inputs.json")
 48	circuit.Proof = proofWithPis.Proof
 49	circuit.PublicInputs = proofWithPis.PublicInputs
 50
 51	var p *profile.Profile
 52	if profileCircuit {
 53		p = profile.Start()
 54	}
 55	r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
 56	if err != nil {
 57		fmt.Println("error in building circuit", err)
 58		os.Exit(1)
 59	}
 60
 61	if profileCircuit {
 62		p.Stop()
 63		p.Top()
 64		println("r1cs.GetNbCoefficients(): ", r1cs.GetNbCoefficients())
 65		println("r1cs.GetNbConstraints(): ", r1cs.GetNbConstraints())
 66		println("r1cs.GetNbSecretVariables(): ", r1cs.GetNbSecretVariables())
 67		println("r1cs.GetNbPublicVariables(): ", r1cs.GetNbPublicVariables())
 68		println("r1cs.GetNbInternalVariables(): ", r1cs.GetNbInternalVariables())
 69	}
 70
 71	// Don't serialize the circuit for now, since it takes up too much memory
 72	/*
 73		if serialize {
 74			fR1CS, _ := os.Create("circuit")
 75			r1cs.WriteTo(fR1CS)
 76			fR1CS.Close()
 77		}
 78	*/
 79	var pk groth16.ProvingKey
 80	var vk groth16.VerifyingKey
 81
 82	fmt.Println("Running circuit setup", time.Now())
 83	if dummy {
 84		fmt.Println("Using dummy setup")
 85		pk, err = groth16.DummySetup(r1cs)
 86	} else {
 87		fmt.Println("Using real setup")
 88		pk, vk, err = groth16.Setup(r1cs)
 89	}
 90	if err != nil {
 91		fmt.Println(err)
 92		os.Exit(1)
 93	}
 94
 95	if serialize {
 96		fPK, _ := os.Create("proving.key")
 97		pk.WriteTo(fPK)
 98		fPK.Close()
 99
100		fVK, _ := os.Create("verifying.key")
101		vk.WriteTo(fVK)
102		fVK.Close()
103	}
104
105	if outputSolidity {
106		fSolidity, _ := os.Create("proof.sol")
107		err = vk.ExportSolidity(fSolidity)
108	}
109
110	return r1cs, pk, vk
111}
112
113func createProof(plonky2Circuit string, r1cs constraint.ConstraintSystem, pk groth16.ProvingKey, vk groth16.VerifyingKey, serialize bool) groth16.Proof {
114	proofWithPis := verifier.DeserializeProofWithPublicInputs("./verifier/data/" + plonky2Circuit + "/proof_with_public_inputs.json")
115
116	// Witness
117	assignment := &BenchmarkPlonky2VerifierCircuit{
118		Proof:        proofWithPis.Proof,
119		PublicInputs: proofWithPis.PublicInputs,
120	}
121
122	fmt.Println("Generating witness", time.Now())
123	witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
124	publicWitness, _ := witness.Public()
125	if serialize {
126		fWitness, _ := os.Create("witness")
127		witness.WriteTo(fWitness)
128		fWitness.Close()
129	}
130
131	fmt.Println("Creating proof", time.Now())
132	proof, err := groth16.Prove(r1cs, pk, witness)
133	if err != nil {
134		fmt.Println(err)
135		os.Exit(1)
136	}
137	if serialize {
138		fProof, _ := os.Create("proof.proof")
139		proof.WriteTo(fProof)
140		fProof.Close()
141	}
142
143	if vk == nil {
144		fmt.Println("vk is nil, means you're using dummy setup and we skip verification step")
145		return proof
146	}
147
148	fmt.Println("Verifying proof", time.Now())
149	err = groth16.Verify(proof, vk, publicWitness)
150	if err != nil {
151		fmt.Println(err)
152		os.Exit(1)
153	}
154
155	const fpSize = 4 * 8
156	var buf bytes.Buffer
157	proof.WriteRawTo(&buf)
158	proofBytes := buf.Bytes()
159
160	var (
161		a [2]*big.Int
162		b [2][2]*big.Int
163		c [2]*big.Int
164	)
165
166	// proof.Ar, proof.Bs, proof.Krs
167	a[0] = new(big.Int).SetBytes(proofBytes[fpSize*0 : fpSize*1])
168	a[1] = new(big.Int).SetBytes(proofBytes[fpSize*1 : fpSize*2])
169	b[0][0] = new(big.Int).SetBytes(proofBytes[fpSize*2 : fpSize*3])
170	b[0][1] = new(big.Int).SetBytes(proofBytes[fpSize*3 : fpSize*4])
171	b[1][0] = new(big.Int).SetBytes(proofBytes[fpSize*4 : fpSize*5])
172	b[1][1] = new(big.Int).SetBytes(proofBytes[fpSize*5 : fpSize*6])
173	c[0] = new(big.Int).SetBytes(proofBytes[fpSize*6 : fpSize*7])
174	c[1] = new(big.Int).SetBytes(proofBytes[fpSize*7 : fpSize*8])
175
176	println("a[0] is ", a[0].String())
177	println("a[1] is ", a[1].String())
178
179	println("b[0][0] is ", b[0][0].String())
180	println("b[0][1] is ", b[0][1].String())
181	println("b[1][0] is ", b[1][0].String())
182	println("b[1][1] is ", b[1][1].String())
183
184	println("c[0] is ", c[0].String())
185	println("c[1] is ", c[1].String())
186
187	return proof
188}
189
190func main() {
191	plonky2Circuit := flag.String("plonky2-circuit", "", "plonky2 circuit to benchmark")
192	profileCircuit := flag.Bool("profile", false, "profile the circuit")
193	serialize := flag.Bool("serialize", false, "serialize the circuit")
194	outputSolidity := flag.Bool("solidity", false, "output solidity code for the circuit")
195
196	flag.Parse()
197
198	if plonky2Circuit == nil || *plonky2Circuit == "" {
199		fmt.Println("Please provide a plonky2 circuit to benchmark")
200		os.Exit(1)
201	}
202
203	r1cs, pk, vk := compileCircuit(*plonky2Circuit, *profileCircuit, *serialize, *outputSolidity, true)
204	createProof(*plonky2Circuit, r1cs, pk, vk, *serialize)
205}