gnark-plonky2-verifier/fri_benchmark.go
fri_benchmark.goRaw
1package main
2
3import (
4 "fmt"
5 . "gnark-ed25519/field"
6 . "gnark-ed25519/plonky2_verifier"
7 "gnark-ed25519/poseidon"
8 "os"
9 "time"
10
11 "github.com/consensys/gnark-crypto/ecc"
12 "github.com/consensys/gnark/backend/groth16"
13 "github.com/consensys/gnark/frontend"
14 "github.com/consensys/gnark/frontend/cs/r1cs"
15)
16
17type BenchmarkLargeDummyFriCircuit struct {
18 zeta QuadraticExtension
19 openings FriOpenings
20 friChallenges FriChallenges
21 initialMerkleCaps []MerkleCap
22 friProof FriProof
23}
24
25func (circuit *BenchmarkLargeDummyFriCircuit) Define(api frontend.API) error {
26 commonCircuitData := DeserializeCommonCircuitData("./plonky2_verifier/data/dummy_2^14_gates/common_circuit_data.json")
27
28 field := NewFieldAPI(api)
29 qeAPI := NewQuadraticExtensionAPI(field, commonCircuitData.DegreeBits)
30 poseidonChip := poseidon.NewPoseidonChip(api, field)
31 friChip := NewFriChip(api, field, qeAPI, poseidonChip, &commonCircuitData.FriParams)
32
33 friChip.VerifyFriProof(
34 commonCircuitData.GetFriInstance(qeAPI, circuit.zeta, commonCircuitData.DegreeBits),
35 circuit.openings,
36 &circuit.friChallenges,
37 circuit.initialMerkleCaps,
38 &circuit.friProof,
39 )
40
41 return nil
42}
43
44func compileCircuit() frontend.CompiledConstraintSystem {
45 fmt.Println("compiling circuit", time.Now())
46 circuit := BenchmarkLargeDummyFriCircuit{}
47
48 /*
49 commonCircuitData := DeserializeCommonCircuitData("./plonky2_verifier/data/dummy_2^14_gates/common_circuit_data.json")
50
51 circuit.zeta[0] = emulated.NewElement[EmulatedField](nil)
52 circuit.zeta[1] = emulated.NewElement[EmulatedField](nil)
53
54 fmt.Println("circuit zeta allocated")
55
56 // Batch 0 has the following openings
57 // Constants (config.num_constants + 1)
58 // Sigmas (config.num_routed_wires)
59 // Wires (config.num_wires)
60 // Plonk_Z (config.num_challenges)
61 // Partial Products (config.num_challenges * config.num_partial_products)
62 // Quotient Polynomails (config.num_challenges * config.quotient_degree_factor)
63
64 // Batch 1 has the following openings
65 // Plonk_Z_next (config.num_challenges)
66
67 circuit.openings.Batches = make([]FriOpeningBatch, 2)
68
69 batch1Size := commonCircuitData.NumConstants + 1 +
70 commonCircuitData.Config.NumRoutedWires +
71 commonCircuitData.Config.NumWires +
72 commonCircuitData.Config.NumChallenges +
73 (commonCircuitData.Config.NumChallenges * commonCircuitData.NumPartialProducts) +
74 (commonCircuitData.Config.NumChallenges * commonCircuitData.QuotientDegreeFactor)
75
76 circuit.openings.Batches[0].Values = make([]QuadraticExtension, 0)
77 for i := uint64(0); i < batch1Size; i++ {
78 circuit.openings.Batches[0].Values = append(circuit.openings.Batches[0].Values, NewEmptyQuadraticExtension())
79 }
80
81 batch2Size := commonCircuitData.Config.NumChallenges
82 circuit.openings.Batches[1].Values = make([]QuadraticExtension, 0)
83 for i := uint64(0); i < batch2Size; i++ {
84 circuit.openings.Batches[1].Values = append(circuit.openings.Batches[1].Values, NewEmptyQuadraticExtension())
85 }
86
87 fmt.Println("circuit openings allocated")
88
89 circuit.friChallenges.FriAlpha = NewEmptyQuadraticExtension()
90 circuit.friChallenges.FriPowResponse = emulated.NewElement[EmulatedField](nil)
91 circuit.friChallenges.FriBetas = make([]QuadraticExtension, 0)
92 for i := 0; i < len(commonCircuitData.FriParams.ReductionArityBits); i++ {
93 circuit.friChallenges.FriBetas = append(circuit.friChallenges.FriBetas, NewEmptyQuadraticExtension())
94 }
95 circuit.friChallenges.FriQueryIndicies = make([]F, 0)
96 for i := uint64(0); i < commonCircuitData.FriParams.Config.NumQueryRounds; i++ {
97 circuit.friChallenges.FriQueryIndicies = append(circuit.friChallenges.FriQueryIndicies, NewEmptyFieldElement())
98 }
99
100 fmt.Println("circuit challenges allocated")
101
102 // initial merkle caps is the merkle cap for
103 // the constant/sigmas, wires, partial products,
104 // and quotient composite polynomial
105 // The merkle cap size is 2**cap_height hashes
106 numMerkleCaps := 4
107 merkleCapSize := 1 << commonCircuitData.Config.FriConfig.CapHeight
108 circuit.initialMerkleCaps = make([]MerkleCap, 0)
109 for i := 0; i < numMerkleCaps; i++ {
110 merkleCap := make([]Hash, 0)
111 for j := 0; j < merkleCapSize; j++ {
112 merkleCap = append(merkleCap, NewEmptyHash())
113 }
114 circuit.initialMerkleCaps = append(circuit.initialMerkleCaps, merkleCap)
115 }
116
117 fmt.Println("circuit initialMerkleCaps allocated")
118
119 // CommitPhaseMerkleCap is number of reduction_arity_bits
120 // finalPoly has 2^(degreeBits - sum(arity_bits)) coefficients
121 numCommitPhaseMerkleCaps := len(commonCircuitData.FriParams.ReductionArityBits)
122 for i := 0; i < numCommitPhaseMerkleCaps; i++ {
123 circuit.friProof.CommitPhaseMerkleCaps = make([]MerkleCap, 0)
124 merkleCap := make([]Hash, 0)
125 for j := 0; j < merkleCapSize; j++ {
126 merkleCap = append(merkleCap, NewEmptyHash())
127 }
128 circuit.friProof.CommitPhaseMerkleCaps = append(circuit.friProof.CommitPhaseMerkleCaps, merkleCap)
129 }
130
131 fmt.Println("circuit friproof CommitPhaseMerkleCaps allocated")
132
133 friOracleInfo := commonCircuitData.FriOracles()
134 circuit.friProof.QueryRoundProofs = make([]FriQueryRound, 0)
135 for i := 0; i < int(commonCircuitData.FriParams.Config.NumQueryRounds); i++ {
136
137 evalsProof := make([]EvalProof, 0)
138 // Allocation for the initial trees proof
139 for j := 0; j < len(friOracleInfo); j++ {
140 leafSize := friOracleInfo[0].NumPolys
141 merkleProofLen := commonCircuitData.DegreeBits + commonCircuitData.Config.FriConfig.RateBits - commonCircuitData.Config.FriConfig.CapHeight
142
143 evalElements := make([]F, 0)
144 for k := uint64(0); k < leafSize; k++ {
145 evalElements = append(evalElements, NewEmptyFieldElement())
146 }
147
148 merkleProofSiblings := make([]Hash, 0)
149 for k := uint64(0); k < merkleProofLen; k++ {
150 merkleProofSiblings = append(merkleProofSiblings, NewEmptyHash())
151 }
152
153 evalsProof = append(
154 evalsProof,
155 EvalProof{
156 Elements: evalElements,
157 MerkleProof: MerkleProof{merkleProofSiblings},
158 },
159 )
160 }
161
162 // Allocation for the steps
163 steps := make([]FriQueryStep, 0)
164 codewordLenBits := commonCircuitData.DegreeBits + commonCircuitData.Config.FriConfig.RateBits
165 for j := 0; j < len(commonCircuitData.FriParams.ReductionArityBits); j++ {
166 arityBits := commonCircuitData.FriParams.ReductionArityBits[j]
167 leafSize := 1 << int(arityBits)
168 codewordLenBits -= arityBits
169 merkleProofLen := codewordLenBits - commonCircuitData.Config.FriConfig.CapHeight
170
171 evalQEs := make([]QuadraticExtension, 0)
172 for k := 0; k < leafSize; k++ {
173 evalQEs = append(evalQEs, NewEmptyQuadraticExtension())
174 }
175
176 merkleProofSiblings := make([]Hash, 0)
177 for k := uint64(0); k < merkleProofLen; k++ {
178 merkleProofSiblings = append(merkleProofSiblings, NewEmptyHash())
179 }
180
181 steps = append(
182 steps,
183 FriQueryStep{
184 Evals: evalQEs,
185 MerkleProof: MerkleProof{merkleProofSiblings},
186 },
187 )
188 }
189
190 circuit.friProof.QueryRoundProofs = append(
191 circuit.friProof.QueryRoundProofs,
192 FriQueryRound{
193 InitialTreesProof: FriInitialTreeProof{evalsProof},
194 Steps: steps,
195 },
196 )
197
198 fmt.Println("circuit friproof QueryRoundProofs allocated for round", i)
199 }
200
201 // Final poly allocation
202 finalPolyLenBit := commonCircuitData.DegreeBits
203 for _, arityBit := range commonCircuitData.FriParams.ReductionArityBits {
204 finalPolyLenBit -= arityBit
205 }
206
207 circuit.friProof.FinalPoly.Coeffs = make([]QuadraticExtension, 0)
208 for i := 0; i < (1 << finalPolyLenBit); i++ {
209 circuit.friProof.FinalPoly.Coeffs = append(circuit.friProof.FinalPoly.Coeffs, NewEmptyQuadraticExtension())
210 }
211
212 fmt.Println("circuit friproof FinalPoly allocated")
213
214 // PowWitness allocation
215 circuit.friProof.PowWitness = NewEmptyFieldElement()
216 fmt.Println("Partial witness allocation done")
217 */
218
219 proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/dummy_2^14_gates/proof_with_public_inputs.json")
220 verifierOnlyCircuitData := DeserializeVerifierOnlyCircuitData("./plonky2_verifier/data/dummy_2^14_gates/verifier_only_circuit_data.json")
221
222 zeta := QuadraticExtension{
223 NewFieldElementFromString("17377750363769967882"),
224 NewFieldElementFromString("11921191651424768462"),
225 }
226 friChallenges := FriChallenges{
227 FriAlpha: QuadraticExtension{
228 NewFieldElementFromString("16721004555774385479"),
229 NewFieldElementFromString("10688151135543754663"),
230 },
231 FriBetas: []QuadraticExtension{
232 {
233 NewFieldElementFromString("3312441922957827805"),
234 NewFieldElementFromString("15128092514958289671"),
235 },
236 {
237 NewFieldElementFromString("13630530769060141802"),
238 NewFieldElementFromString("14559883974933163008"),
239 },
240 {
241 NewFieldElementFromString("16146508250083930687"),
242 NewFieldElementFromString("5176346568444408396"),
243 },
244 },
245 FriPowResponse: NewFieldElement(4389),
246 FriQueryIndicies: []F{
247 NewFieldElementFromString("16334967868590615051"),
248 NewFieldElementFromString("2911473540496037915"),
249 NewFieldElementFromString("14887216056886344225"),
250 NewFieldElementFromString("7808811227805914295"),
251 NewFieldElementFromString("2018594961417375749"),
252 NewFieldElementFromString("3733368398777208435"),
253 NewFieldElementFromString("2623035669037055104"),
254 NewFieldElementFromString("299243030573481514"),
255 NewFieldElementFromString("7189789717962704433"),
256 NewFieldElementFromString("14566344026886816268"),
257 NewFieldElementFromString("12555390069003437453"),
258 NewFieldElementFromString("17225508403199418233"),
259 NewFieldElementFromString("5088797913879903292"),
260 NewFieldElementFromString("9715691392773433023"),
261 NewFieldElementFromString("7565836764713256165"),
262 NewFieldElementFromString("1500143546029322929"),
263 NewFieldElementFromString("1245802417104422080"),
264 NewFieldElementFromString("6831959786661245110"),
265 NewFieldElementFromString("17271054758535453780"),
266 NewFieldElementFromString("6225460404576395409"),
267 NewFieldElementFromString("15932661092896277351"),
268 NewFieldElementFromString("12452534049198240575"),
269 NewFieldElementFromString("4225199666055520177"),
270 NewFieldElementFromString("13235091290587791090"),
271 NewFieldElementFromString("2562357622728700774"),
272 NewFieldElementFromString("17676678042980201498"),
273 NewFieldElementFromString("5837067135702409874"),
274 NewFieldElementFromString("11238419549114325157"),
275 },
276 }
277
278 initialMerkleCaps := []MerkleCap{
279 verifierOnlyCircuitData.ConstantSigmasCap,
280 proofWithPis.Proof.WiresCap,
281 proofWithPis.Proof.PlonkZsPartialProductsCap,
282 proofWithPis.Proof.QuotientPolysCap,
283 }
284
285 circuit.zeta = zeta
286 circuit.openings = proofWithPis.Proof.Openings.ToFriOpenings()
287 circuit.friChallenges = friChallenges
288 circuit.initialMerkleCaps = initialMerkleCaps
289 circuit.friProof = proofWithPis.Proof.OpeningProof
290
291 r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
292 if err != nil {
293 fmt.Println("error in building circuit", err)
294 os.Exit(1)
295 }
296
297 return r1cs
298}
299
300func createProof(r1cs frontend.CompiledConstraintSystem) groth16.Proof {
301 proofWithPis := DeserializeProofWithPublicInputs("./plonky2_verifier/data/dummy_2^14_gates/proof_with_public_inputs.json")
302 verifierOnlyCircuitData := DeserializeVerifierOnlyCircuitData("./plonky2_verifier/data/dummy_2^14_gates/verifier_only_circuit_data.json")
303
304 zeta := QuadraticExtension{
305 NewFieldElementFromString("17377750363769967882"),
306 NewFieldElementFromString("11921191651424768462"),
307 }
308 friChallenges := FriChallenges{
309 FriAlpha: QuadraticExtension{
310 NewFieldElementFromString("16721004555774385479"),
311 NewFieldElementFromString("10688151135543754663"),
312 },
313 FriBetas: []QuadraticExtension{
314 {
315 NewFieldElementFromString("3312441922957827805"),
316 NewFieldElementFromString("15128092514958289671"),
317 },
318 {
319 NewFieldElementFromString("13630530769060141802"),
320 NewFieldElementFromString("14559883974933163008"),
321 },
322 {
323 NewFieldElementFromString("16146508250083930687"),
324 NewFieldElementFromString("5176346568444408396"),
325 },
326 },
327 FriPowResponse: NewFieldElement(4389),
328 FriQueryIndicies: []F{
329 NewFieldElementFromString("16334967868590615051"),
330 NewFieldElementFromString("2911473540496037915"),
331 NewFieldElementFromString("14887216056886344225"),
332 NewFieldElementFromString("7808811227805914295"),
333 NewFieldElementFromString("2018594961417375749"),
334 NewFieldElementFromString("3733368398777208435"),
335 NewFieldElementFromString("2623035669037055104"),
336 NewFieldElementFromString("299243030573481514"),
337 NewFieldElementFromString("7189789717962704433"),
338 NewFieldElementFromString("14566344026886816268"),
339 NewFieldElementFromString("12555390069003437453"),
340 NewFieldElementFromString("17225508403199418233"),
341 NewFieldElementFromString("5088797913879903292"),
342 NewFieldElementFromString("9715691392773433023"),
343 NewFieldElementFromString("7565836764713256165"),
344 NewFieldElementFromString("1500143546029322929"),
345 NewFieldElementFromString("1245802417104422080"),
346 NewFieldElementFromString("6831959786661245110"),
347 NewFieldElementFromString("17271054758535453780"),
348 NewFieldElementFromString("6225460404576395409"),
349 NewFieldElementFromString("15932661092896277351"),
350 NewFieldElementFromString("12452534049198240575"),
351 NewFieldElementFromString("4225199666055520177"),
352 NewFieldElementFromString("13235091290587791090"),
353 NewFieldElementFromString("2562357622728700774"),
354 NewFieldElementFromString("17676678042980201498"),
355 NewFieldElementFromString("5837067135702409874"),
356 NewFieldElementFromString("11238419549114325157"),
357 },
358 }
359
360 initialMerkleCaps := []MerkleCap{
361 verifierOnlyCircuitData.ConstantSigmasCap,
362 proofWithPis.Proof.WiresCap,
363 proofWithPis.Proof.PlonkZsPartialProductsCap,
364 proofWithPis.Proof.QuotientPolysCap,
365 }
366
367 // Witness
368 assignment := &BenchmarkLargeDummyFriCircuit{
369 zeta: zeta,
370 openings: proofWithPis.Proof.Openings.ToFriOpenings(),
371 friChallenges: friChallenges,
372 initialMerkleCaps: initialMerkleCaps,
373 friProof: proofWithPis.Proof.OpeningProof,
374 }
375
376 fmt.Println("Generating witness", time.Now())
377 witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
378 publicWitness, _ := witness.Public()
379 pk, vk, err := groth16.Setup(r1cs)
380 if err != nil {
381 fmt.Println(err)
382 os.Exit(1)
383 }
384
385 fmt.Println("Creating proof", time.Now())
386 proof, err := groth16.Prove(r1cs, pk, witness)
387 if err != nil {
388 fmt.Println(err)
389 os.Exit(1)
390 }
391 fmt.Println("Verifying proof", time.Now())
392 err = groth16.Verify(proof, vk, publicWitness)
393 if err != nil {
394 fmt.Println(err)
395 os.Exit(1)
396 }
397
398 return proof
399}
400
401func main() {
402 r1cs := compileCircuit()
403 fi, _ := os.Open("dummy_fri.r1cs")
404 r1cs.WriteTo(fi)
405 proof := createProof(r1cs)
406 fmt.Println(proof.CurveID(), time.Now())
407}