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