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	"github.com/succinctlabs/gnark-plonky2-verifier/types"
 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/backend/plonk"
 18	"github.com/consensys/gnark/constraint"
 19	"github.com/consensys/gnark/frontend"
 20	"github.com/consensys/gnark/frontend/cs/r1cs"
 21	"github.com/consensys/gnark/frontend/cs/scs"
 22	"github.com/consensys/gnark/profile"
 23	"github.com/consensys/gnark/test"
 24)
 25
 26func runBenchmark(plonky2Circuit string, proofSystem string, profileCircuit bool, dummy bool, saveArtifacts bool) {
 27	commonCircuitData := types.DeserializeCommonCircuitData("testdata/" + plonky2Circuit + "/common_circuit_data.json")
 28
 29	proofWithPis := variables.DeserializeProofWithPublicInputs(types.ReadProofWithPublicInputs("testdata/" + plonky2Circuit + "/proof_with_public_inputs.json"))
 30	verifierOnlyCircuitData := variables.DeserializeVerifierOnlyCircuitData(types.ReadVerifierOnlyCircuitData("testdata/" + plonky2Circuit + "/verifier_only_circuit_data.json"))
 31
 32	circuit := verifier.ExampleVerifierCircuit{
 33		Proof:                   proofWithPis.Proof,
 34		PublicInputs:            proofWithPis.PublicInputs,
 35		VerifierOnlyCircuitData: verifierOnlyCircuitData,
 36		CommonCircuitData:       commonCircuitData,
 37	}
 38
 39	var p *profile.Profile
 40	if profileCircuit {
 41		p = profile.Start()
 42	}
 43
 44	var builder frontend.NewBuilder
 45	if proofSystem == "plonk" {
 46		builder = scs.NewBuilder
 47	} else if proofSystem == "groth16" {
 48		builder = r1cs.NewBuilder
 49	} else {
 50		fmt.Println("Please provide a valid proof system to benchmark, we only support plonk and groth16")
 51		os.Exit(1)
 52	}
 53
 54	r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), builder, &circuit)
 55	if err != nil {
 56		fmt.Println("error in building circuit", err)
 57		os.Exit(1)
 58	}
 59
 60	if profileCircuit {
 61		p.Stop()
 62		p.Top()
 63		println("r1cs.GetNbCoefficients(): ", r1cs.GetNbCoefficients())
 64		println("r1cs.GetNbConstraints(): ", r1cs.GetNbConstraints())
 65		println("r1cs.GetNbSecretVariables(): ", r1cs.GetNbSecretVariables())
 66		println("r1cs.GetNbPublicVariables(): ", r1cs.GetNbPublicVariables())
 67		println("r1cs.GetNbInternalVariables(): ", r1cs.GetNbInternalVariables())
 68	}
 69
 70	witness := verifier.ExampleVerifierCircuit{
 71		Proof:                   proofWithPis.Proof,
 72		PublicInputs:            proofWithPis.PublicInputs,
 73		VerifierOnlyCircuitData: verifierOnlyCircuitData,
 74		CommonCircuitData:       commonCircuitData,
 75	}
 76
 77	if proofSystem == "plonk" {
 78		plonkProof(r1cs, witness, dummy, saveArtifacts)
 79	} else if proofSystem == "groth16" {
 80		groth16Proof(r1cs, witness, dummy, saveArtifacts)
 81	} else {
 82		panic("Please provide a valid proof system to benchmark, we only support plonk and groth16")
 83	}
 84}
 85
 86func plonkProof(r1cs constraint.ConstraintSystem, assignment verifier.ExampleVerifierCircuit, dummy bool, saveArtifacts bool) {
 87	var pk plonk.ProvingKey
 88	var vk plonk.VerifyingKey
 89	var err error
 90
 91	// Don't serialize the circuit for now, since it takes up too much memory
 92	// if saveArtifacts {
 93	// 	fR1CS, _ := os.Create("circuit")
 94	// 	r1cs.WriteTo(fR1CS)
 95	// 	fR1CS.Close()
 96	// }
 97
 98	fmt.Println("Running circuit setup", time.Now())
 99	if dummy {
100		panic("dummy setup not supported for plonk")
101	} else {
102		fmt.Println("Using real setup")
103		srs, err := test.NewKZGSRS(r1cs)
104		if err != nil {
105			panic(err)
106		}
107		pk, vk, err = plonk.Setup(r1cs, srs)
108	}
109	if err != nil {
110		fmt.Println(err)
111		os.Exit(1)
112	}
113
114	if saveArtifacts {
115		fPK, _ := os.Create("proving.key")
116		pk.WriteTo(fPK)
117		fPK.Close()
118
119		if vk != nil {
120			fVK, _ := os.Create("verifying.key")
121			vk.WriteTo(fVK)
122			fVK.Close()
123		}
124
125		fSolidity, _ := os.Create("proof.sol")
126		err = vk.ExportSolidity(fSolidity)
127	}
128
129	fmt.Println("Generating witness", time.Now())
130	witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField())
131	publicWitness, _ := witness.Public()
132	if saveArtifacts {
133		fWitness, _ := os.Create("witness")
134		witness.WriteTo(fWitness)
135		fWitness.Close()
136	}
137
138	fmt.Println("Creating proof", time.Now())
139	proof, err := plonk.Prove(r1cs, pk, witness)
140	if err != nil {
141		fmt.Println(err)
142		os.Exit(1)
143	}
144	if saveArtifacts {
145		fProof, _ := os.Create("proof.proof")
146		proof.WriteTo(fProof)
147		fProof.Close()
148	}
149
150	if vk == nil {
151		fmt.Println("vk is nil, means you're using dummy setup and we skip verification of proof")
152		return
153	}
154
155	fmt.Println("Verifying proof", time.Now())
156	err = plonk.Verify(proof, vk, publicWitness)
157	if err != nil {
158		fmt.Println(err)
159		os.Exit(1)
160	}
161
162	const fpSize = 4 * 8
163	var buf bytes.Buffer
164	proof.WriteRawTo(&buf)
165	proofBytes := buf.Bytes()
166	fmt.Printf("proofBytes: %v\n", proofBytes)
167}
168
169func groth16Proof(r1cs constraint.ConstraintSystem, assignment verifier.ExampleVerifierCircuit, dummy bool, saveArtifacts bool) {
170	var pk groth16.ProvingKey
171	var vk groth16.VerifyingKey
172	var err error
173
174	// Don't serialize the circuit for now, since it takes up too much memory
175	// if saveArtifacts {
176	// 	fR1CS, _ := os.Create("circuit")
177	// 	r1cs.WriteTo(fR1CS)
178	// 	fR1CS.Close()
179	// }
180
181	fmt.Println("Running circuit setup", time.Now())
182	if dummy {
183		fmt.Println("Using dummy setup")
184		pk, err = groth16.DummySetup(r1cs)
185	} else {
186		fmt.Println("Using real setup")
187		pk, vk, err = groth16.Setup(r1cs)
188	}
189	if err != nil {
190		fmt.Println(err)
191		os.Exit(1)
192	}
193
194	if saveArtifacts {
195		fPK, _ := os.Create("proving.key")
196		pk.WriteTo(fPK)
197		fPK.Close()
198
199		if vk != nil {
200			fVK, _ := os.Create("verifying.key")
201			vk.WriteTo(fVK)
202			fVK.Close()
203		}
204
205		fSolidity, _ := os.Create("proof.sol")
206		err = vk.ExportSolidity(fSolidity)
207	}
208
209	fmt.Println("Generating witness", time.Now())
210	witness, _ := frontend.NewWitness(&assignment, ecc.BN254.ScalarField())
211	publicWitness, _ := witness.Public()
212	if saveArtifacts {
213		fWitness, _ := os.Create("witness")
214		witness.WriteTo(fWitness)
215		fWitness.Close()
216	}
217
218	fmt.Println("Creating proof", time.Now())
219	proof, err := groth16.Prove(r1cs, pk, witness)
220	if err != nil {
221		fmt.Println(err)
222		os.Exit(1)
223	}
224	if saveArtifacts {
225		fProof, _ := os.Create("proof.proof")
226		proof.WriteTo(fProof)
227		fProof.Close()
228	}
229
230	if vk == nil {
231		fmt.Println("vk is nil, means you're using dummy setup and we skip verification of proof")
232		return
233	}
234
235	fmt.Println("Verifying proof", time.Now())
236	err = groth16.Verify(proof, vk, publicWitness)
237	if err != nil {
238		fmt.Println(err)
239		os.Exit(1)
240	}
241
242	const fpSize = 4 * 8
243	var buf bytes.Buffer
244	proof.WriteRawTo(&buf)
245	proofBytes := buf.Bytes()
246
247	var (
248		a [2]*big.Int
249		b [2][2]*big.Int
250		c [2]*big.Int
251	)
252
253	// proof.Ar, proof.Bs, proof.Krs
254	a[0] = new(big.Int).SetBytes(proofBytes[fpSize*0 : fpSize*1])
255	a[1] = new(big.Int).SetBytes(proofBytes[fpSize*1 : fpSize*2])
256	b[0][0] = new(big.Int).SetBytes(proofBytes[fpSize*2 : fpSize*3])
257	b[0][1] = new(big.Int).SetBytes(proofBytes[fpSize*3 : fpSize*4])
258	b[1][0] = new(big.Int).SetBytes(proofBytes[fpSize*4 : fpSize*5])
259	b[1][1] = new(big.Int).SetBytes(proofBytes[fpSize*5 : fpSize*6])
260	c[0] = new(big.Int).SetBytes(proofBytes[fpSize*6 : fpSize*7])
261	c[1] = new(big.Int).SetBytes(proofBytes[fpSize*7 : fpSize*8])
262
263	println("a[0] is ", a[0].String())
264	println("a[1] is ", a[1].String())
265
266	println("b[0][0] is ", b[0][0].String())
267	println("b[0][1] is ", b[0][1].String())
268	println("b[1][0] is ", b[1][0].String())
269	println("b[1][1] is ", b[1][1].String())
270
271	println("c[0] is ", c[0].String())
272	println("c[1] is ", c[1].String())
273
274}
275
276func main() {
277	plonky2Circuit := flag.String("plonky2-circuit", "", "plonky2 circuit to benchmark")
278	proofSystem := flag.String("proof-system", "groth16", "proof system to benchmark")
279	profileCircuit := flag.Bool("profile", true, "profile the circuit")
280	dummySetup := flag.Bool("dummy", true, "use dummy setup")
281	saveArtifacts := flag.Bool("save", false, "save circuit artifacts")
282
283	flag.Parse()
284
285	if plonky2Circuit == nil || *plonky2Circuit == "" {
286		fmt.Println("Please provide a plonky2 circuit to benchmark")
287		os.Exit(1)
288	}
289
290	if *proofSystem == "plonk" {
291		*dummySetup = false
292	}
293
294	fmt.Printf("Running benchmark for %s circuit with proof system %s\n", *plonky2Circuit, *proofSystem)
295	fmt.Printf("Profiling: %t, DummySetup: %t, SaveArtifacts: %t\n", *profileCircuit, *dummySetup, *saveArtifacts)
296
297	runBenchmark(*plonky2Circuit, *proofSystem, *profileCircuit, *dummySetup, *saveArtifacts)
298}