1use crate::pairing::ff::{Field, PrimeField};
2use crate::pairing::{Engine};
3
4use crate::{SynthesisError};
5use std::marker::PhantomData;
6
7use crate::plonk::cs::gates::*;
8use crate::plonk::cs::*;
9
10use crate::worker::*;
11use super::polynomials::*;
12use super::domains::*;
13use crate::plonk::commitments::*;
14use crate::plonk::commitments::transcript::*;
15use crate::plonk::utils::*;
16use crate::plonk::generator::*;
17use crate::plonk::prover::*;
18
19fn evaluate_inverse_vanishing_poly<E: Engine>(vahisning_size: usize, point: E::Fr) -> E::Fr {
20 assert!(vahisning_size.is_power_of_two());
21
22 let domain = Domain::<E::Fr>::new_for_size(vahisning_size as u64).expect("should fit");
27 let n_domain_omega = domain.generator;
28 let root = n_domain_omega.pow([(vahisning_size - 1) as u64]);
29
30 let mut numerator = point;
31 numerator.sub_assign(&root);
32
33 let mut denominator = point.pow([vahisning_size as u64]);
34 denominator.sub_assign(&E::Fr::one());
35
36 let denominator = denominator.inverse().expect("must exist");
37
38 numerator.mul_assign(&denominator);
39
40 numerator
41}
42
43fn evaluate_lagrange_poly<E: Engine>(vahisning_size:usize, poly_number: usize, at: E::Fr) -> E::Fr {
44 assert!(vahisning_size.is_power_of_two());
45
46 let mut repr = E::Fr::zero().into_repr();
47 repr.as_mut()[0] = vahisning_size as u64;
48
49 let size_fe = E::Fr::from_repr(repr).expect("is a valid representation");
50 let domain = Domain::<E::Fr>::new_for_size(vahisning_size as u64).expect("domain of this size should exist");
56 let omega = domain.generator;
57
58 let omega_inv = omega.inverse().expect("must exist");
59
60 let argument_multiplier = omega_inv.pow([poly_number as u64]);
61 let mut argument = at;
62 argument.mul_assign(&argument_multiplier);
63
64 let mut numerator = argument.pow([vahisning_size as u64]);
65 numerator.sub_assign(&E::Fr::one());
66
67 let mut denom = argument;
68 denom.sub_assign(&E::Fr::one());
69 denom.mul_assign(&size_fe);
70
71 let denom_inv = denom.inverse().expect("must exist");
72
73 numerator.mul_assign(&denom_inv);
74
75 numerator
76}
77
78pub fn verify_nonhomomorphic<E: Engine, S: CommitmentScheme<E::Fr, Prng = T>, T: Transcript<E::Fr, Input = S::Commitment>>(
79 setup: &PlonkSetup<E, S>,
80 proof: &PlonkNonhomomorphicProof<E, S>,
81 meta: S::Meta,
82 large_meta: S::Meta
83) -> Result<bool, SynthesisError> {
84 assert!(S::IS_HOMOMORPHIC == false);
85
86 let num_gates = setup.n;
87
88 let committer = S::new_for_size(num_gates.next_power_of_two(), meta);
89 let large_committer = S::new_for_size(4 * num_gates.next_power_of_two(), large_meta);
90
91 let mut transcript = T::new();
92
93 let required_domain_size = setup.n + 1;
95 assert!(required_domain_size.is_power_of_two());
96
97 transcript.commit_input(&proof.a_commitment);
98 transcript.commit_input(&proof.b_commitment);
99 transcript.commit_input(&proof.c_commitment);
100
101 let beta = transcript.get_challenge();
102 let gamma = transcript.get_challenge();
103
104 transcript.commit_input(&proof.z_1_commitment);
105 transcript.commit_input(&proof.z_2_commitment);
106
107 let n_fe = E::Fr::from_str(&setup.n.to_string()).expect("must be valid field element");
110 let mut two_n_fe = n_fe;
111 two_n_fe.double();
112
113 let alpha = transcript.get_challenge();
114
115 transcript.commit_input(&proof.t_commitment);
116
117 let z = transcript.get_challenge();
118
119 let a_at_z = proof.a_opening_value;
122 let b_at_z = proof.b_opening_value;
123 let c_at_z = proof.c_opening_value;
124
125 let q_l_at_z = proof.q_l_opening_value;
126 let q_r_at_z = proof.q_r_opening_value;
127 let q_o_at_z = proof.q_o_opening_value;
128 let q_m_at_z = proof.q_m_opening_value;
129 let q_c_at_z = proof.q_c_opening_value;
130
131 let s_id_at_z = proof.s_id_opening_value;
132 let sigma_1_at_z = proof.sigma_1_opening_value;
133 let sigma_2_at_z = proof.sigma_2_opening_value;
134 let sigma_3_at_z = proof.sigma_3_opening_value;
135
136 let mut inverse_vanishing_at_z = evaluate_inverse_vanishing_poly::<E>(required_domain_size.next_power_of_two(), z);
137
138 let z_1_at_z = proof.z_1_unshifted_opening_value;
139 let z_2_at_z = proof.z_2_unshifted_opening_value;
140
141 let z_1_shifted_at_z = proof.z_1_shifted_opening_value;
142 let z_2_shifted_at_z = proof.z_2_shifted_opening_value;
143
144 let l_0_at_z = evaluate_lagrange_poly::<E>(required_domain_size.next_power_of_two(), 0, z);
145 let l_n_minus_one_at_z = evaluate_lagrange_poly::<E>(required_domain_size.next_power_of_two(), setup.n - 1, z);
146
147 let t_at_z = proof.t_opening_value;
148
149 {
150 transcript.commit_field_element(&a_at_z);
151 transcript.commit_field_element(&b_at_z);
152 transcript.commit_field_element(&c_at_z);
153
154 transcript.commit_field_element(&q_l_at_z);
155 transcript.commit_field_element(&q_r_at_z);
156 transcript.commit_field_element(&q_o_at_z);
157 transcript.commit_field_element(&q_m_at_z);
158 transcript.commit_field_element(&q_c_at_z);
159
160 transcript.commit_field_element(&s_id_at_z);
161 transcript.commit_field_element(&sigma_1_at_z);
162 transcript.commit_field_element(&sigma_2_at_z);
163 transcript.commit_field_element(&sigma_3_at_z);
164
165 transcript.commit_field_element(&t_at_z);
166
167 transcript.commit_field_element(&z_1_at_z);
168 transcript.commit_field_element(&z_2_at_z);
169
170 transcript.commit_field_element(&z_1_shifted_at_z);
171 transcript.commit_field_element(&z_2_shifted_at_z);
172 }
173
174 let aggregation_challenge = transcript.get_challenge();
175
176 let mut t_1 = {
182 let mut res = q_c_at_z;
183
184 let mut tmp = q_l_at_z;
185 tmp.mul_assign(&a_at_z);
186 res.add_assign(&tmp);
187
188 let mut tmp = q_r_at_z;
189 tmp.mul_assign(&b_at_z);
190 res.add_assign(&tmp);
191
192 let mut tmp = q_o_at_z;
193 tmp.mul_assign(&c_at_z);
194 res.add_assign(&tmp);
195
196 let mut tmp = q_m_at_z;
197 tmp.mul_assign(&a_at_z);
198 tmp.mul_assign(&b_at_z);
199 res.add_assign(&tmp);
200
201 inverse_vanishing_at_z.mul_assign(&alpha);
202
203 res.mul_assign(&inverse_vanishing_at_z);
204
205 res
206 };
207
208 {
209 let mut res = z_1_at_z;
210
211 let mut tmp = s_id_at_z;
212 tmp.mul_assign(&beta);
213 tmp.add_assign(&a_at_z);
214 tmp.add_assign(&gamma);
215 res.mul_assign(&tmp);
216
217 let mut tmp = s_id_at_z;
218 tmp.add_assign(&n_fe);
219 tmp.mul_assign(&beta);
220 tmp.add_assign(&b_at_z);
221 tmp.add_assign(&gamma);
222 res.mul_assign(&tmp);
223
224 let mut tmp = s_id_at_z;
225 tmp.add_assign(&two_n_fe);
226 tmp.mul_assign(&beta);
227 tmp.add_assign(&c_at_z);
228 tmp.add_assign(&gamma);
229 res.mul_assign(&tmp);
230
231 res.sub_assign(&z_1_shifted_at_z);
232
233 inverse_vanishing_at_z.mul_assign(&alpha);
234
235 res.mul_assign(&inverse_vanishing_at_z);
236
237 t_1.add_assign(&res);
238 }
239
240 {
241 let mut res = z_2_at_z;
242
243 let mut tmp = sigma_1_at_z;
244 tmp.mul_assign(&beta);
245 tmp.add_assign(&a_at_z);
246 tmp.add_assign(&gamma);
247 res.mul_assign(&tmp);
248
249 let mut tmp = sigma_2_at_z;
250 tmp.mul_assign(&beta);
251 tmp.add_assign(&b_at_z);
252 tmp.add_assign(&gamma);
253 res.mul_assign(&tmp);
254
255 let mut tmp = sigma_3_at_z;
256 tmp.mul_assign(&beta);
257 tmp.add_assign(&c_at_z);
258 tmp.add_assign(&gamma);
259 res.mul_assign(&tmp);
260
261 res.sub_assign(&z_2_shifted_at_z);
262
263 inverse_vanishing_at_z.mul_assign(&alpha);
264
265 res.mul_assign(&inverse_vanishing_at_z);
266
267 t_1.add_assign(&res);
268 }
269
270 {
271 let mut res = z_1_shifted_at_z;
272 res.sub_assign(&z_2_shifted_at_z);
273 res.mul_assign(&l_n_minus_one_at_z);
274
275 inverse_vanishing_at_z.mul_assign(&alpha);
276
277 res.mul_assign(&inverse_vanishing_at_z);
278
279 t_1.add_assign(&res);
280 }
281
282 {
283 let mut res = z_1_at_z;
284 res.sub_assign(&z_2_at_z);
285 res.mul_assign(&l_0_at_z);
286
287 inverse_vanishing_at_z.mul_assign(&alpha);
288
289 res.mul_assign(&inverse_vanishing_at_z);
290
291 t_1.add_assign(&res);
292 }
293
294 let domain = Domain::<E::Fr>::new_for_size(required_domain_size as u64)?;
295
296 let mut z_by_omega = z;
297 z_by_omega.mul_assign(&domain.generator);
298
299 let commitments = vec![
300 &proof.a_commitment,
301 &proof.b_commitment,
302 &proof.c_commitment,
303 &setup.q_l,
304 &setup.q_r,
305 &setup.q_o,
306 &setup.q_m,
307 &setup.q_c,
308 &setup.s_id,
309 &setup.sigma_1,
310 &setup.sigma_2,
311 &setup.sigma_3,
312 &proof.z_1_commitment,
313 &proof.z_2_commitment,
314 &proof.z_1_commitment,
315 &proof.z_2_commitment,
316 ];
317
318 let claimed_values = vec![
319 a_at_z,
320 b_at_z,
321 c_at_z,
322 q_l_at_z,
323 q_r_at_z,
324 q_o_at_z,
325 q_m_at_z,
326 q_c_at_z,
327 s_id_at_z,
328 sigma_1_at_z,
329 sigma_2_at_z,
330 sigma_3_at_z,
331 z_1_at_z,
332 z_2_at_z,
333 z_1_shifted_at_z,
334 z_2_shifted_at_z,
335 ];
336
337 let opening_points = vec![
338 z,
339 z,
340 z,
341
342 z,
343 z,
344 z,
345 z,
346 z,
347
348 z,
349 z,
350 z,
351 z,
352
353 z,
354 z,
355
356 z_by_omega,
357 z_by_omega
358 ];
359
360 if t_1 != t_at_z {
361 println!("Recalculated t(z) is not equal to the provided value");
362 return Ok(false);
363 }
364
365 let valid = committer.verify_multiple_openings(commitments, opening_points, &claimed_values, aggregation_challenge, &proof.openings_proof, &mut transcript);
366
367 if !valid {
368 println!("Multiopening is invalid");
369 return Ok(false);
370 }
371
372 let valid = large_committer.verify_single(&proof.t_commitment, z, proof.t_opening_value, &proof.t_opening_proof, &mut transcript);
373
374 if !valid {
375 println!("T commitment opening is invalid");
376 return Ok(false);
377 }
378
379
380
381 Ok(valid)
397}
398
399#[track_caller]
400pub fn verify_nonhomomorphic_chunked<E: Engine, S: CommitmentScheme<E::Fr, Prng = T>, T: Transcript<E::Fr, Input = S::Commitment>>(
401 setup: &PlonkSetup<E, S>,
402 proof: &PlonkChunkedNonhomomorphicProof<E, S>,
403 meta: S::Meta
404) -> Result<bool, SynthesisError> {
405 assert!(S::IS_HOMOMORPHIC == false);
406
407 let num_gates = setup.n;
408
409 let t = std::time::Instant::now();
410 let committer = S::new_for_size(num_gates.next_power_of_two(), meta);
411 println!("Committer creation taken {:?}", t.elapsed());
412
413 let t0 = std::time::Instant::now();
414
415 let mut transcript = T::new();
416
417 let t = std::time::Instant::now();
418
419 let required_domain_size = setup.n + 1;
421 assert!(required_domain_size.is_power_of_two());
422
423 transcript.commit_input(&proof.a_commitment);
424 transcript.commit_input(&proof.b_commitment);
425 transcript.commit_input(&proof.c_commitment);
426
427 let beta = transcript.get_challenge();
428 let gamma = transcript.get_challenge();
429
430 transcript.commit_input(&proof.z_1_commitment);
431 transcript.commit_input(&proof.z_2_commitment);
432
433 let n_fe = E::Fr::from_str(&setup.n.to_string()).expect("must be valid field element");
436 let mut two_n_fe = n_fe;
437 two_n_fe.double();
438
439 let alpha = transcript.get_challenge();
440
441 transcript.commit_input(&proof.t_low_commitment);
442 transcript.commit_input(&proof.t_mid_commitment);
443 transcript.commit_input(&proof.t_high_commitment);
444
445 let z = transcript.get_challenge();
446
447 let a_at_z = proof.a_opening_value;
450 let b_at_z = proof.b_opening_value;
451 let c_at_z = proof.c_opening_value;
452
453 let q_l_at_z = proof.q_l_opening_value;
454 let q_r_at_z = proof.q_r_opening_value;
455 let q_o_at_z = proof.q_o_opening_value;
456 let q_m_at_z = proof.q_m_opening_value;
457 let q_c_at_z = proof.q_c_opening_value;
458
459 let s_id_at_z = proof.s_id_opening_value;
460 let sigma_1_at_z = proof.sigma_1_opening_value;
461 let sigma_2_at_z = proof.sigma_2_opening_value;
462 let sigma_3_at_z = proof.sigma_3_opening_value;
463
464 let mut inverse_vanishing_at_z = evaluate_inverse_vanishing_poly::<E>(required_domain_size, z);
465
466 let z_1_at_z = proof.z_1_unshifted_opening_value;
467 let z_2_at_z = proof.z_2_unshifted_opening_value;
468
469 let z_1_shifted_at_z = proof.z_1_shifted_opening_value;
470 let z_2_shifted_at_z = proof.z_2_shifted_opening_value;
471
472 let l_0_at_z = evaluate_lagrange_poly::<E>(required_domain_size, 0, z);
473 let l_n_minus_one_at_z = evaluate_lagrange_poly::<E>(required_domain_size, setup.n - 1, z);
474
475 let t_low_at_z = proof.t_low_opening_value;
476 let t_mid_at_z = proof.t_mid_opening_value;
477 let t_high_at_z = proof.t_high_opening_value;
478
479 let z_in_pow_of_domain_size = z.pow([required_domain_size as u64]);
480
481 let mut t_at_z = E::Fr::zero();
482 t_at_z.add_assign(&t_low_at_z);
483
484 let mut tmp = z_in_pow_of_domain_size;
485 tmp.mul_assign(&t_mid_at_z);
486 t_at_z.add_assign(&tmp);
487
488 let mut tmp = z_in_pow_of_domain_size;
489 tmp.mul_assign(&z_in_pow_of_domain_size);
490 tmp.mul_assign(&t_high_at_z);
491 t_at_z.add_assign(&tmp);
492
493 {
494 transcript.commit_field_element(&a_at_z);
495 transcript.commit_field_element(&b_at_z);
496 transcript.commit_field_element(&c_at_z);
497
498 transcript.commit_field_element(&q_l_at_z);
499 transcript.commit_field_element(&q_r_at_z);
500 transcript.commit_field_element(&q_o_at_z);
501 transcript.commit_field_element(&q_m_at_z);
502 transcript.commit_field_element(&q_c_at_z);
503
504 transcript.commit_field_element(&s_id_at_z);
505 transcript.commit_field_element(&sigma_1_at_z);
506 transcript.commit_field_element(&sigma_2_at_z);
507 transcript.commit_field_element(&sigma_3_at_z);
508
509 transcript.commit_field_element(&t_low_at_z);
510 transcript.commit_field_element(&t_mid_at_z);
511 transcript.commit_field_element(&t_high_at_z);
512
513 transcript.commit_field_element(&z_1_at_z);
514 transcript.commit_field_element(&z_2_at_z);
515
516 transcript.commit_field_element(&z_1_shifted_at_z);
517 transcript.commit_field_element(&z_2_shifted_at_z);
518 }
519
520 let aggregation_challenge = transcript.get_challenge();
521
522 let mut t_1 = {
526 let mut res = q_c_at_z;
527
528 let mut tmp = q_l_at_z;
529 tmp.mul_assign(&a_at_z);
530 res.add_assign(&tmp);
531
532 let mut tmp = q_r_at_z;
533 tmp.mul_assign(&b_at_z);
534 res.add_assign(&tmp);
535
536 let mut tmp = q_o_at_z;
537 tmp.mul_assign(&c_at_z);
538 res.add_assign(&tmp);
539
540 let mut tmp = q_m_at_z;
541 tmp.mul_assign(&a_at_z);
542 tmp.mul_assign(&b_at_z);
543 res.add_assign(&tmp);
544
545 inverse_vanishing_at_z.mul_assign(&alpha);
546
547 res.mul_assign(&inverse_vanishing_at_z);
548
549 res
550 };
551
552 {
553 let mut res = z_1_at_z;
554
555 let mut tmp = s_id_at_z;
556 tmp.mul_assign(&beta);
557 tmp.add_assign(&a_at_z);
558 tmp.add_assign(&gamma);
559 res.mul_assign(&tmp);
560
561 let mut tmp = s_id_at_z;
562 tmp.add_assign(&n_fe);
563 tmp.mul_assign(&beta);
564 tmp.add_assign(&b_at_z);
565 tmp.add_assign(&gamma);
566 res.mul_assign(&tmp);
567
568 let mut tmp = s_id_at_z;
569 tmp.add_assign(&two_n_fe);
570 tmp.mul_assign(&beta);
571 tmp.add_assign(&c_at_z);
572 tmp.add_assign(&gamma);
573 res.mul_assign(&tmp);
574
575 res.sub_assign(&z_1_shifted_at_z);
576
577 inverse_vanishing_at_z.mul_assign(&alpha);
578
579 res.mul_assign(&inverse_vanishing_at_z);
580
581 t_1.add_assign(&res);
582 }
583
584 {
585 let mut res = z_2_at_z;
586
587 let mut tmp = sigma_1_at_z;
588 tmp.mul_assign(&beta);
589 tmp.add_assign(&a_at_z);
590 tmp.add_assign(&gamma);
591 res.mul_assign(&tmp);
592
593 let mut tmp = sigma_2_at_z;
594 tmp.mul_assign(&beta);
595 tmp.add_assign(&b_at_z);
596 tmp.add_assign(&gamma);
597 res.mul_assign(&tmp);
598
599 let mut tmp = sigma_3_at_z;
600 tmp.mul_assign(&beta);
601 tmp.add_assign(&c_at_z);
602 tmp.add_assign(&gamma);
603 res.mul_assign(&tmp);
604
605 res.sub_assign(&z_2_shifted_at_z);
606
607 inverse_vanishing_at_z.mul_assign(&alpha);
608
609 res.mul_assign(&inverse_vanishing_at_z);
610
611 t_1.add_assign(&res);
612 }
613
614 {
615 let mut res = z_1_shifted_at_z;
616 res.sub_assign(&z_2_shifted_at_z);
617 res.mul_assign(&l_n_minus_one_at_z);
618
619 inverse_vanishing_at_z.mul_assign(&alpha);
620
621 res.mul_assign(&inverse_vanishing_at_z);
622
623 t_1.add_assign(&res);
624 }
625
626 {
627 let mut res = z_1_at_z;
628 res.sub_assign(&z_2_at_z);
629 res.mul_assign(&l_0_at_z);
630
631 inverse_vanishing_at_z.mul_assign(&alpha);
632
633 res.mul_assign(&inverse_vanishing_at_z);
634
635 t_1.add_assign(&res);
636 }
637
638 let domain = Domain::<E::Fr>::new_for_size(required_domain_size as u64)?;
639
640 let mut z_by_omega = z;
641 z_by_omega.mul_assign(&domain.generator);
642
643 let commitments = vec![
644 &proof.a_commitment,
645 &proof.b_commitment,
646 &proof.c_commitment,
647
648 &setup.q_l,
649 &setup.q_r,
650 &setup.q_o,
651 &setup.q_m,
652 &setup.q_c,
653
654 &setup.s_id,
655 &setup.sigma_1,
656 &setup.sigma_2,
657 &setup.sigma_3,
658
659 &proof.z_1_commitment,
660 &proof.z_2_commitment,
661
662 &proof.z_1_commitment,
663 &proof.z_2_commitment,
664
665 &proof.t_low_commitment,
666 &proof.t_mid_commitment,
667 &proof.t_high_commitment,
668 ];
669
670 let claimed_values = vec![
671 a_at_z,
672 b_at_z,
673 c_at_z,
674
675 q_l_at_z,
676 q_r_at_z,
677 q_o_at_z,
678 q_m_at_z,
679 q_c_at_z,
680
681 s_id_at_z,
682 sigma_1_at_z,
683 sigma_2_at_z,
684 sigma_3_at_z,
685
686 z_1_at_z,
687 z_2_at_z,
688
689 z_1_shifted_at_z,
690 z_2_shifted_at_z,
691
692 t_low_at_z,
693 t_mid_at_z,
694 t_high_at_z,
695 ];
696
697 let opening_points = vec![
698 z,
699 z,
700 z,
701
702 z,
703 z,
704 z,
705 z,
706 z,
707
708 z,
709 z,
710 z,
711 z,
712
713 z,
714 z,
715
716 z_by_omega,
717 z_by_omega,
718
719 z,
720 z,
721 z,
722 ];
723
724 if t_1 != t_at_z {
725 println!("Recalculated t(z) is not equal to the provided value");
726 return Ok(false);
727 }
728
729 println!("Initial verification taken {:?}", t.elapsed());
730
731 let t = std::time::Instant::now();
732
733 let valid = committer.verify_multiple_openings(
734 commitments,
735 opening_points,
736 &claimed_values,
737 aggregation_challenge,
738 &proof.openings_proof,
739 &mut transcript
740 );
741
742 println!("Verification of multiple openings taken {:?}", t.elapsed());
743
744 if !valid {
745 println!("Multiopening is invalid");
746 return Ok(false);
747 }
748
749 println!("Verification without overhead taken {:?}", t0.elapsed());
750
751 Ok(valid)
752}
753
754#[cfg(test)]
755mod test {
756
757 use super::*;
758 use crate::pairing::ff::{Field, PrimeField};
759 use crate::pairing::{Engine};
760
761 use crate::{SynthesisError};
762 use std::marker::PhantomData;
763
764 use crate::plonk::cs::gates::*;
765 use crate::plonk::cs::*;
766
767 struct TestCircuit<E:Engine>{
768 _marker: PhantomData<E>
769 }
770
771 impl<E: Engine> Circuit<E> for TestCircuit<E> {
772 fn synthesize<CS: ConstraintSystem<E>>(&self, cs: &mut CS) -> Result<(), SynthesisError> {
773 let a = cs.alloc(|| {
774 Ok(E::Fr::from_str("10").unwrap())
775 })?;
776
777 let b = cs.alloc(|| {
778 Ok(E::Fr::from_str("20").unwrap())
779 })?;
780
781 let c = cs.alloc(|| {
782 Ok(E::Fr::from_str("200").unwrap())
783 })?;
784
785 let one = E::Fr::one();
786
787 let mut two = one;
788 two.double();
789
790 let mut negative_one = one;
791 negative_one.negate();
792
793 cs.enforce_zero_2((a, b), (two, negative_one))?;
794
795 let ten = E::Fr::from_str("10").unwrap();
796 cs.enforce_zero_2((b, c), (ten, negative_one))?;
797
798 cs.enforce_mul_3((a, b, c))?;
799
800 Ok(())
801 }
802 }
803
804 struct InvalidTestCircuit<E:Engine>{
805 _marker: PhantomData<E>
806 }
807
808 impl<E: Engine> Circuit<E> for InvalidTestCircuit<E> {
809 fn synthesize<CS: ConstraintSystem<E>>(&self, cs: &mut CS) -> Result<(), SynthesisError> {
810 let a = cs.alloc(|| {
811 Ok(E::Fr::from_str("11").unwrap())
812 })?;
813
814 let b = cs.alloc(|| {
815 Ok(E::Fr::from_str("20").unwrap())
816 })?;
817
818 let c = cs.alloc(|| {
819 Ok(E::Fr::from_str("200").unwrap())
820 })?;
821
822 let one = E::Fr::one();
823
824 let mut two = one;
825 two.double();
826
827 let mut negative_one = one;
828 negative_one.negate();
829
830 cs.enforce_zero_2((a, b), (two, negative_one))?;
831
832 let ten = E::Fr::from_str("10").unwrap();
833 cs.enforce_zero_2((b, c), (ten, negative_one))?;
834
835 cs.enforce_mul_3((a, b, c))?;
836
837 Ok(())
838 }
839 }
840
841 #[test]
842 fn test_small_circuit_transparent_verification() {
843 use crate::pairing::bn256::{Bn256, Fr};
844 use crate::plonk::utils::*;
845 use crate::plonk::commitments::transparent::fri::*;
846 use crate::plonk::commitments::transparent::iop::*;
847 use crate::plonk::commitments::transcript::*;
848 use crate::plonk::commitments::transparent::fri::naive_fri::naive_fri::*;
849 use crate::plonk::commitments::transparent::iop::blake2s_trivial_iop::*;
850 use crate::plonk::commitments::*;
851 use crate::plonk::commitments::transparent::*;
852
853 type Iop = TrivialBlake2sIOP<Fr>;
854 type Fri = NaiveFriIop<Fr, Iop>;
855 type Committer = StatelessTransparentCommitter<Fr, Fri, Blake2sTranscript<Fr>>;
856
857 let meta = TransparentCommitterParameters {
858 lde_factor: 16,
859 num_queries: 2,
860 output_coeffs_at_degree_plus_one: 1,
861 fri_params: ()
862 };
863
864 let meta_large = TransparentCommitterParameters {
865 lde_factor: 16,
866 num_queries: 2,
867 output_coeffs_at_degree_plus_one: 1,
868 fri_params: ()
869 };
870
871 let circuit = TestCircuit::<Bn256> {
872 _marker: PhantomData
873 };
874
875 let (setup, aux) = setup::<Bn256, Committer, _>(&circuit, meta).unwrap();
876
877 let meta = TransparentCommitterParameters {
878 lde_factor: 16,
879 num_queries: 2,
880 output_coeffs_at_degree_plus_one: 1,
881 fri_params: ()
882 };
883
884 println!("Proving");
885
886 let proof = prove_nonhomomorphic::<Bn256, Committer, Blake2sTranscript::<Fr>, _>(&circuit, &setup, &aux, meta.clone(), meta_large.clone()).unwrap();
887
888
889 println!("Verifying");
890
891 let valid = verify_nonhomomorphic::<Bn256, Committer, Blake2sTranscript::<Fr>>(&setup, &proof, meta, meta_large).unwrap();
892
893 assert!(valid);
894 }
895
896 #[test]
897 fn test_small_circuit_invalid_witness_transparent_verification() {
898 use crate::pairing::bn256::{Bn256, Fr};
899 use crate::plonk::utils::*;
900 use crate::plonk::commitments::transparent::fri::*;
901 use crate::plonk::commitments::transparent::iop::*;
902 use crate::plonk::commitments::transcript::*;
903 use crate::plonk::commitments::transparent::fri::naive_fri::naive_fri::*;
904 use crate::plonk::commitments::transparent::iop::blake2s_trivial_iop::*;
905 use crate::plonk::commitments::*;
906 use crate::plonk::commitments::transparent::*;
907
908 type Iop = TrivialBlake2sIOP<Fr>;
909 type Fri = NaiveFriIop<Fr, Iop>;
910 type Committer = StatelessTransparentCommitter<Fr, Fri, Blake2sTranscript<Fr>>;
911
912 let meta = TransparentCommitterParameters {
913 lde_factor: 16,
914 num_queries: 2,
915 output_coeffs_at_degree_plus_one: 1,
916 fri_params: ()
917 };
918
919 let meta_large = TransparentCommitterParameters {
920 lde_factor: 16,
921 num_queries: 2,
922 output_coeffs_at_degree_plus_one: 1,
923 fri_params: ()
924 };
925
926 let circuit = InvalidTestCircuit::<Bn256> {
927 _marker: PhantomData
928 };
929
930 let (setup, aux) = setup::<Bn256, Committer, _>(&circuit, meta.clone()).unwrap();
931
932 println!("Proving");
933
934 let proof = prove_nonhomomorphic::<Bn256, Committer, Blake2sTranscript::<Fr>, _>(&circuit, &setup, &aux, meta.clone(), meta_large.clone()).unwrap();
935
936 println!("Verifying");
937
938 let valid = verify_nonhomomorphic::<Bn256, Committer, Blake2sTranscript::<Fr>>(&setup, &proof, meta, meta_large).unwrap();
939
940 assert!(!valid);
941 }
942
943 #[derive(Clone)]
944 struct BenchmarkCircuit<E:Engine>{
945 num_steps: usize,
946 _marker: PhantomData<E>
947 }
948
949 impl<E: Engine> Circuit<E> for BenchmarkCircuit<E> {
950 fn synthesize<CS: ConstraintSystem<E>>(&self, cs: &mut CS) -> Result<(), SynthesisError> {
951 let one = E::Fr::one();
954 let mut negative_one = one;
955 negative_one.negate();
956
957 let mut two = one;
958 two.double();
959
960 let mut a = cs.alloc(|| {
961 Ok(E::Fr::one())
962 })?;
963
964 let mut b = cs.alloc(|| {
965 Ok(E::Fr::one())
966 })?;
967
968 cs.enforce_constant(a, E::Fr::one())?;
969 cs.enforce_constant(b, E::Fr::one())?;
970
971 let mut c = cs.alloc(|| {
972 Ok(two)
973 })?;
974
975 cs.enforce_zero_3((a, b, c), (one, one, negative_one))?;
976
977 let mut a_value = one;
978 let mut b_value = one;
979 let mut c_value = two;
980
981 for _ in 0..self.num_steps {
982 a = b;
983 b = c;
984
985 a_value = b_value;
986 b_value = c_value;
987 c_value.add_assign(&a_value);
988
989 c = cs.alloc(|| {
990 Ok(c_value)
991 })?;
992
993 cs.enforce_zero_3((a, b, c), (one, one, negative_one))?;
994 }
995
996 Ok(())
997 }
998 }
999
1000 #[test]
1001 fn test_bench_fibonacci_circuit() {
1002 use crate::pairing::bn256::{Bn256, Fr};
1003 use crate::plonk::utils::*;
1004 use crate::plonk::commitments::transparent::fri::*;
1005 use crate::plonk::commitments::transparent::iop::*;
1006 use crate::plonk::commitments::transcript::*;
1007 use crate::plonk::commitments::transparent::fri::naive_fri::naive_fri::*;
1008 use crate::plonk::commitments::transparent::iop::blake2s_trivial_iop::*;
1009 use crate::plonk::commitments::*;
1010 use crate::plonk::commitments::transparent::*;
1011 use crate::plonk::tester::*;
1012
1013 use std::time::Instant;
1014
1015 type Iop = TrivialBlake2sIOP<Fr>;
1016 type Fri = NaiveFriIop<Fr, Iop>;
1017 type Committer = StatelessTransparentCommitter<Fr, Fri, Blake2sTranscript<Fr>>;
1018
1019 let meta = TransparentCommitterParameters {
1020 lde_factor: 16,
1021 num_queries: 10,
1022 output_coeffs_at_degree_plus_one: 16,
1023 fri_params: ()
1024 };
1025
1026 let meta_large = TransparentCommitterParameters {
1027 lde_factor: 16,
1028 num_queries: 10,
1029 output_coeffs_at_degree_plus_one: 16,
1030 fri_params: ()
1031 };
1032
1033 let circuit = BenchmarkCircuit::<Bn256> {
1034 num_steps: 1_000_000,
1035 _marker: PhantomData
1036 };
1037
1038 {
1039 let mut tester = TestingAssembly::<Bn256>::new();
1040
1041 circuit.synthesize(&mut tester).expect("must synthesize");
1042
1043 let satisfied = tester.is_satisfied();
1044
1045 assert!(satisfied);
1046
1047 println!("Circuit is satisfied");
1048 }
1049
1050 println!("Start setup");
1051 let start = Instant::now();
1052 let (setup, aux) = setup::<Bn256, Committer, _>(&circuit, meta).unwrap();
1053 println!("Setup taken {:?}", start.elapsed());
1054
1055 println!("Using circuit with N = {}", setup.n);
1056
1057 let meta = TransparentCommitterParameters {
1058 lde_factor: 16,
1059 num_queries: 10,
1060 output_coeffs_at_degree_plus_one: 16,
1061 fri_params: ()
1062 };
1063
1064 println!("Start proving");
1065 let start = Instant::now();
1066 let proof = prove_nonhomomorphic::<Bn256, Committer, Blake2sTranscript::<Fr>, _>(&circuit, &setup, &aux, meta.clone(), meta_large.clone()).unwrap();
1067 println!("Proof taken {:?}", start.elapsed());
1068
1069 println!("Start verifying");
1070 let start = Instant::now();
1071 let valid = verify_nonhomomorphic::<Bn256, Committer, Blake2sTranscript::<Fr>>(&setup, &proof, meta, meta_large).unwrap();
1072 println!("Verification with unnecessary precomputation taken {:?}", start.elapsed());
1073
1074 assert!(valid);
1075 }
1076
1077 #[test]
1151 fn test_bench_homomorphic_plonk() {
1152 use rand::{XorShiftRng, SeedableRng, Rand, Rng};
1153 use crate::pairing::bn256::Bn256;
1154 use num_cpus;
1155 use crate::pairing::ff::ScalarEngine;
1156 use crate::pairing::CurveProjective;
1157 use crate::multiexp::*;
1158 use crate::worker::*;
1159 use crate::source::*;
1160 use std::sync::Arc;
1161 use futures::{Future};
1162
1163 const SAMPLES: usize = 1 << 20;
1164 let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1165
1166 let v = (0..SAMPLES).map(|_| <Bn256 as ScalarEngine>::Fr::rand(rng).into_repr()).collect::<Vec<_>>();
1167 let g = (0..SAMPLES).map(|_| <Bn256 as Engine>::G1::rand(rng).into_affine()).collect::<Vec<_>>();
1168
1169 println!("Done generating test points and scalars");
1170
1171 let pool = Worker::new();
1172 let start = std::time::Instant::now();
1173
1174 let _sparse = multiexp(
1175 &pool,
1176 (Arc::new(g), 0),
1177 FullDensity,
1178 Arc::new(v)
1179 ).wait().unwrap();
1180
1181 let per_one_poly = start.elapsed().as_micros();
1182 let total_expected_plonk = per_one_poly * (5 + 1 + 3 + 3 + 1);
1184 println!("{} ms for expected plonk with ~ {} gates", total_expected_plonk/1000u128, SAMPLES);
1185 }
1186
1187 #[test]
1188 fn test_bench_transparent_engine() {
1189 use crate::plonk::transparent_engine::proth_engine::*;
1190 use crate::plonk::utils::*;
1191 use crate::plonk::commitments::transparent::fri::*;
1192 use crate::plonk::commitments::transparent::iop::*;
1193 use crate::plonk::commitments::transcript::*;
1194 use crate::plonk::commitments::transparent::fri::naive_fri::naive_fri::*;
1195 use crate::plonk::commitments::transparent::iop::blake2s_trivial_iop::*;
1196 use crate::plonk::commitments::*;
1197 use crate::plonk::commitments::transparent::*;
1198 use crate::plonk::tester::*;
1199
1200 use std::time::Instant;
1201
1202 type Iop = TrivialBlake2sIOP<Fr>;
1203 type Fri = NaiveFriIop<Fr, Iop>;
1204 type Committer = StatelessTransparentCommitter<Fr, Fri, Blake2sTranscript<Fr>>;
1205
1206 let mut negative_one = Fr::one();
1207 negative_one.negate();
1208 println!("-1 = {}", negative_one);
1209
1210 let meta = TransparentCommitterParameters {
1211 lde_factor: 16,
1212 num_queries: 10,
1213 output_coeffs_at_degree_plus_one: 16,
1214 fri_params: ()
1215 };
1216
1217 let meta_large = TransparentCommitterParameters {
1218 lde_factor: 16,
1219 num_queries: 10,
1220 output_coeffs_at_degree_plus_one: 16,
1221 fri_params: ()
1222 };
1223
1224 let circuit = BenchmarkCircuit::<Transparent252> {
1225 num_steps: 20,
1226 _marker: PhantomData
1227 };
1228
1229 {
1230 let mut tester = TestingAssembly::<Transparent252>::new();
1231
1232 circuit.synthesize(&mut tester).expect("must synthesize");
1233
1234 let satisfied = tester.is_satisfied();
1235
1236 assert!(satisfied);
1237
1238 println!("Circuit is satisfied");
1239 }
1240
1241 println!("Start setup");
1242 let start = Instant::now();
1243 let (setup, aux) = setup::<Transparent252, Committer, _>(&circuit, meta).unwrap();
1244 println!("Setup taken {:?}", start.elapsed());
1245
1246 println!("Using circuit with N = {}", setup.n);
1247
1248 let meta = TransparentCommitterParameters {
1249 lde_factor: 16,
1250 num_queries: 10,
1251 output_coeffs_at_degree_plus_one: 16,
1252 fri_params: ()
1253 };
1254
1255 println!("Start proving");
1256 let start = Instant::now();
1257 let proof = prove_nonhomomorphic::<Transparent252, Committer, Blake2sTranscript::<Fr>, _>(&circuit, &setup, &aux, meta.clone(), meta_large.clone()).unwrap();
1258 println!("Proof taken {:?}", start.elapsed());
1259
1260 println!("Start verifying");
1261 let start = Instant::now();
1262 let valid = verify_nonhomomorphic::<Transparent252, Committer, Blake2sTranscript::<Fr>>(&setup, &proof, meta, meta_large).unwrap();
1263 println!("Verification with unnecessary precomputation taken {:?}", start.elapsed());
1264
1265 assert!(valid);
1266 }
1267
1268 #[test]
1269 fn test_bench_chunked_proof_on_transparent_engine() {
1270 use crate::plonk::transparent_engine::proth_engine::*;
1271 use crate::plonk::utils::*;
1272 use crate::plonk::commitments::transparent::fri::*;
1273 use crate::plonk::commitments::transparent::iop::*;
1274 use crate::plonk::commitments::transcript::*;
1275 use crate::plonk::commitments::transparent::fri::naive_fri::naive_fri::*;
1276 use crate::plonk::commitments::transparent::iop::blake2s_trivial_iop::*;
1277 use crate::plonk::commitments::*;
1278 use crate::plonk::commitments::transparent::*;
1279 use crate::plonk::tester::*;
1280
1281 use std::time::Instant;
1282
1283 type Iop = TrivialBlake2sIOP<Fr>;
1284 type Fri = NaiveFriIop<Fr, Iop>;
1285 type Committer = StatelessTransparentCommitter<Fr, Fri, Blake2sTranscript<Fr>>;
1286 let params = ();
1287
1288 let mut negative_one = Fr::one();
1289 negative_one.negate();
1290 println!("-1 = {}", negative_one);
1291
1292 let meta = TransparentCommitterParameters {
1293 lde_factor: 16,
1294 num_queries: 10,
1295 output_coeffs_at_degree_plus_one: 2,
1296 fri_params: params
1297 };
1298
1299 let circuit = BenchmarkCircuit::<Transparent252> {
1300 num_steps: 20,
1301 _marker: PhantomData
1302 };
1303
1304 {
1305 let mut tester = TestingAssembly::<Transparent252>::new();
1306
1307 circuit.synthesize(&mut tester).expect("must synthesize");
1308
1309 let satisfied = tester.is_satisfied();
1310
1311 assert!(satisfied);
1312
1313 println!("Circuit is satisfied");
1314 }
1315
1316 println!("Start setup");
1317 let start = Instant::now();
1318 let (setup, aux) = setup::<Transparent252, Committer, _>(&circuit, meta.clone()).unwrap();
1319 println!("Setup taken {:?}", start.elapsed());
1320
1321 println!("Using circuit with N = {}", setup.n);
1322
1323 println!("Start proving");
1324 let start = Instant::now();
1325 let proof = prove_nonhomomorphic_chunked::<Transparent252, Committer, Blake2sTranscript::<Fr>, _>(&circuit, &aux, meta.clone()).unwrap();
1326 println!("Proof taken {:?}", start.elapsed());
1327
1328 let proof_size = proof.estimate_proof_size();
1329 dbg!(&proof_size);
1330
1331 println!("Start verifying");
1332 let start = Instant::now();
1333 let valid = verify_nonhomomorphic_chunked::<Transparent252, Committer, Blake2sTranscript::<Fr>>(&setup, &proof, meta).unwrap();
1334 println!("Verification with unnecessary precomputation taken {:?}", start.elapsed());
1335
1336 assert!(valid);
1337 }
1338
1339
1340 #[test]
1341 fn test_bench_chunked_proof_on_transparent_engine_over_sizes() {
1342 use crate::plonk::transparent_engine::proth_engine::*;
1343 use crate::plonk::utils::*;
1344 use crate::plonk::commitments::transparent::fri::*;
1345 use crate::plonk::commitments::transparent::iop::*;
1346 use crate::plonk::commitments::transcript::*;
1347 use crate::plonk::commitments::transparent::fri::naive_fri::naive_fri::*;
1348 use crate::plonk::commitments::transparent::iop::blake2s_trivial_iop::*;
1349 use crate::plonk::commitments::*;
1350 use crate::plonk::commitments::transparent::*;
1351 use crate::plonk::tester::*;
1352
1353 use std::time::Instant;
1354
1355 type Iop = TrivialBlake2sIOP<Fr>;
1356 type Fri = NaiveFriIop<Fr, Iop>;
1357 type Committer = StatelessTransparentCommitter<Fr, Fri, Blake2sTranscript<Fr>>;
1358 let params = ();
1359
1360 let mut negative_one = Fr::one();
1361 negative_one.negate();
1362 println!("-1 = {}", negative_one);
1363
1364 let num_queries = 20;
1365
1366 for log2 in 10..=20 {
1367 let size = (1<<log2) - 10;
1368
1369 let meta = TransparentCommitterParameters {
1370 lde_factor: 16,
1371 num_queries: num_queries,
1372 output_coeffs_at_degree_plus_one: 16,
1373 fri_params: params
1374 };
1375
1376 let circuit = BenchmarkCircuit::<Transparent252> {
1377 num_steps: size,
1378 _marker: PhantomData
1379 };
1380
1381 {
1382 let mut tester = TestingAssembly::<Transparent252>::new();
1383
1384 circuit.synthesize(&mut tester).expect("must synthesize");
1385
1386 let satisfied = tester.is_satisfied();
1387
1388 assert!(satisfied);
1389
1390 println!("Circuit is satisfied");
1391 }
1392
1393 println!("Start setup");
1394 let start = Instant::now();
1395 let (setup, aux) = setup::<Transparent252, Committer, _>(&circuit, meta.clone()).unwrap();
1396 println!("Setup taken {:?}", start.elapsed());
1397
1398 let size_log_2 = setup.n.next_power_of_two().trailing_zeros();
1399
1400 println!("Using circuit with N = {}", setup.n);
1401
1402 println!("Start proving");
1403 let start = Instant::now();
1404 let proof = prove_nonhomomorphic_chunked::<Transparent252, Committer, Blake2sTranscript::<Fr>, _>(&circuit, &aux, meta.clone()).unwrap();
1405 println!("Proof taken {:?} for 2^{}", start.elapsed(), size_log_2);
1406
1407 let proof_size = proof.estimate_proof_size();
1408 println!("Proof size is {} for 2^{} for {} queries", proof_size, size_log_2, num_queries);
1409
1410 println!("Start verifying");
1411 let start = Instant::now();
1412 let valid = verify_nonhomomorphic_chunked::<Transparent252, Committer, Blake2sTranscript::<Fr>>(&setup, &proof, meta).unwrap();
1413 println!("Verification with unnecessary precomputation taken {:?} for 2^{}", start.elapsed(), size_log_2);
1414
1415 assert!(valid);
1416 }
1417 }
1418
1419
1420 #[test]
1421 fn test_poly_eval_correctness() {
1422 use rand::{XorShiftRng, SeedableRng, Rand, Rng};
1423 use crate::pairing::bn256::Fr;
1424 use num_cpus;
1425 use crate::pairing::ff::ScalarEngine;
1426 use crate::pairing::CurveProjective;
1427 use crate::multiexp::*;
1428 use crate::worker::*;
1429 use crate::source::*;
1430 use std::sync::Arc;
1431 use futures::{Future};
1432
1433 let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1434
1435 let poly_sizes = vec![1, 10, 100, 1000, 10_000, 1_000_000];
1436
1437 let x: Fr = rng.gen();
1438
1439 let worker = Worker::new();
1440
1441 for poly_size in poly_sizes.into_iter() {
1442 let coeffs = (0..poly_size).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
1443 let mut point = Fr::one();
1444 let mut result = Fr::zero();
1445 for c in coeffs.iter() {
1446 let mut tmp = point;
1447 tmp.mul_assign(&c);
1448 result.add_assign(&tmp);
1449
1450 point.mul_assign(&x);
1451 }
1452
1453 let poly = Polynomial::<Fr, _>::from_coeffs(coeffs).unwrap();
1454 let eval_result = poly.evaluate_at(&worker, x);
1455 assert!(eval_result == result, "failed for size {}", poly_size);
1456 }
1457 }
1458
1459 #[test]
1460 fn test_poly_grand_product_correctness() {
1461 use rand::{XorShiftRng, SeedableRng, Rand, Rng};
1462 use crate::pairing::bn256::Fr;
1463 use num_cpus;
1464 use crate::pairing::ff::ScalarEngine;
1465 use crate::pairing::CurveProjective;
1466 use crate::multiexp::*;
1467 use crate::worker::*;
1468 use crate::source::*;
1469 use std::sync::Arc;
1470 use futures::{Future};
1471
1472 let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1473
1474 let poly_sizes = vec![1, 10, 100, 1000, 10_000, 1_000_000];
1475
1476 let worker = Worker::new();
1477
1478 for poly_size in poly_sizes.into_iter() {
1479 let coeffs = (0..poly_size).map(|_| Fr::rand(rng)).filter(|el| !el.is_zero()).collect::<Vec<_>>();
1480 let poly = Polynomial::<Fr, _>::from_values_unpadded(coeffs).unwrap();
1481 let palallel_result = poly.calculate_grand_product(&worker).unwrap();
1482 let serial_result = poly.calculate_grand_product_serial().unwrap();
1483
1484 if palallel_result != serial_result {
1485 for (i, (c0, c1)) in palallel_result.as_ref().iter()
1486 .zip(serial_result.as_ref().iter())
1487 .enumerate()
1488 {
1489 assert!(c0 == c1, "failed at value number {} for size {}", i, poly_size);
1490 }
1491 }
1492 }
1493 }
1494
1495 #[test]
1496 fn test_bench_lde() {
1497 use rand::{XorShiftRng, SeedableRng, Rand, Rng};
1498 use crate::pairing::bn256::Fr;
1499 use crate::pairing::ff::ScalarEngine;
1500 use crate::pairing::CurveProjective;
1501 use std::time::Instant;
1502 use crate::worker::*;
1503 use crate::plonk::commitments::transparent::utils::*;
1504
1505 let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
1506
1507 let poly_sizes = vec![1, 10, 100, 1000, 10_000, 1_000_000, 2_000_000];
1508
1509 let worker = Worker::new();
1510
1511 for poly_size in poly_sizes.into_iter() {
1512 let coeffs = (0..poly_size).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
1513
1514 let poly = Polynomial::<Fr, _>::from_coeffs(coeffs).unwrap();
1515 let start = Instant::now();
1516 let _eval_result = poly.lde(&worker, 16);
1517 println!("LDE with factor 16 for size {} taken {:?}", poly_size, start.elapsed());
1518
1519 let coeffs = (0..(16*poly_size)).map(|_| Fr::rand(rng)).collect::<Vec<_>>();
1520
1521 let poly = Polynomial::<Fr, _>::from_coeffs(coeffs).unwrap();
1522 let start = Instant::now();
1523 let eval_result = poly.clone().fft(&worker);
1524 println!("FFT of the same size taken {:?}", start.elapsed());
1525
1526 if log2_floor(poly.size()) % 2 == 0 {
1527 let log_n = log2_floor(poly.size());
1528 let omega = poly.omega;
1529 let mut coeffs = poly.into_coeffs();
1530 let start = Instant::now();
1531 crate::plonk::fft::radix_4::best_fft(&mut coeffs, &worker, &omega, log_n as u32);
1532 println!("Radix-4 FFT of the same size taken {:?}", start.elapsed());
1533 let to_compare = eval_result.into_coeffs();
1534 assert!(to_compare == coeffs);
1535 }
1536
1537
1538 }
1539 }
1540}