ark_curve_constraint_tests/
lib.rs

1#![macro_use]
2extern crate ark_relations;
3
4pub mod fields {
5    use ark_ff::{BitIteratorLE, Field, PrimeField, UniformRand};
6    use ark_r1cs_std::prelude::*;
7    use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
8    use ark_std::{test_rng, vec::*};
9
10    pub fn field_test<F, ConstraintF, AF>() -> Result<(), SynthesisError>
11    where
12        F: Field,
13        ConstraintF: PrimeField,
14        AF: FieldVar<F, ConstraintF>,
15        AF: TwoBitLookupGadget<ConstraintF, TableConstant = F>,
16        for<'a> &'a AF: FieldOpsBounds<'a, F, AF>,
17    {
18        let modes = [
19            AllocationMode::Input,
20            AllocationMode::Witness,
21            AllocationMode::Constant,
22        ];
23        for &mode in &modes {
24            let cs = ConstraintSystem::<ConstraintF>::new_ref();
25
26            let mut rng = test_rng();
27            let a_native = F::rand(&mut rng);
28            let b_native = F::rand(&mut rng);
29            let a = AF::new_variable(ark_relations::ns!(cs, "generate_a"), || Ok(a_native), mode)?;
30            let b = AF::new_variable(ark_relations::ns!(cs, "generate_b"), || Ok(b_native), mode)?;
31            let b_const = AF::new_constant(ark_relations::ns!(cs, "b_as_constant"), b_native)?;
32
33            let zero = AF::zero();
34            let zero_native = zero.value()?;
35            zero.enforce_equal(&zero)?;
36
37            let one = AF::one();
38            let one_native = one.value()?;
39            one.enforce_equal(&one)?;
40
41            one.enforce_not_equal(&zero)?;
42
43            let one_dup = &zero + &one;
44            one_dup.enforce_equal(&one)?;
45
46            let two = &one + &one;
47            two.enforce_equal(&two)?;
48            two.enforce_equal(&one.double()?)?;
49            two.enforce_not_equal(&one)?;
50            two.enforce_not_equal(&zero)?;
51
52            // a + 0 = a
53            let a_plus_zero = &a + &zero;
54            assert_eq!(a_plus_zero.value()?, a_native);
55            a_plus_zero.enforce_equal(&a)?;
56            a_plus_zero.enforce_not_equal(&a.double()?)?;
57
58            // a - 0 = a
59            let a_minus_zero = &a - &zero;
60            assert_eq!(a_minus_zero.value()?, a_native);
61            a_minus_zero.enforce_equal(&a)?;
62
63            // a - a = 0
64            let a_minus_a = &a - &a;
65            assert_eq!(a_minus_a.value()?, zero_native);
66            a_minus_a.enforce_equal(&zero)?;
67
68            // a + b = b + a
69            let a_b = &a + &b;
70            let b_a = &b + &a;
71            assert_eq!(a_b.value()?, a_native + &b_native);
72            a_b.enforce_equal(&b_a)?;
73
74            // (a + b) + a = a + (b + a)
75            let ab_a = &a_b + &a;
76            let a_ba = &a + &b_a;
77            assert_eq!(ab_a.value()?, a_native + &b_native + &a_native);
78            ab_a.enforce_equal(&a_ba)?;
79
80            let b_times_a_plus_b = &a_b * &b;
81            let b_times_b_plus_a = &b_a * &b;
82            assert_eq!(
83                b_times_a_plus_b.value()?,
84                b_native * &(b_native + &a_native)
85            );
86            assert_eq!(
87                b_times_a_plus_b.value()?,
88                (b_native + &a_native) * &b_native
89            );
90            assert_eq!(
91                b_times_a_plus_b.value()?,
92                (a_native + &b_native) * &b_native
93            );
94            b_times_b_plus_a.enforce_equal(&b_times_a_plus_b)?;
95
96            // a * 1 = a
97            assert_eq!((&a * &one).value()?, a_native * &one_native);
98
99            // a * b = b * a
100            let ab = &a * &b;
101            let ba = &b * &a;
102            assert_eq!(ab.value()?, ba.value()?);
103            assert_eq!(ab.value()?, a_native * &b_native);
104
105            let ab_const = &a * &b_const;
106            let b_const_a = &b_const * &a;
107            assert_eq!(ab_const.value()?, b_const_a.value()?);
108            assert_eq!(ab_const.value()?, ab.value()?);
109            assert_eq!(ab_const.value()?, a_native * &b_native);
110
111            // (a * b) * a = a * (b * a)
112            let ab_a = &ab * &a;
113            let a_ba = &a * &ba;
114            assert_eq!(ab_a.value()?, a_ba.value()?);
115            assert_eq!(ab_a.value()?, a_native * &b_native * &a_native);
116
117            let aa = &a * &a;
118            let a_squared = a.square()?;
119            a_squared.enforce_equal(&aa)?;
120            assert_eq!(aa.value()?, a_squared.value()?);
121            assert_eq!(aa.value()?, a_native.square());
122
123            let aa = &a * a_native;
124            a_squared.enforce_equal(&aa)?;
125            assert_eq!(aa.value()?, a_squared.value()?);
126            assert_eq!(aa.value()?, a_native.square());
127
128            let a_b2 = &a + b_native;
129            a_b.enforce_equal(&a_b2)?;
130            assert_eq!(a_b.value()?, a_b2.value()?);
131
132            let a_inv = a.inverse()?;
133            a_inv.mul_equals(&a, &one)?;
134            assert_eq!(a_inv.value()?, a.value()?.inverse().unwrap());
135            assert_eq!(a_inv.value()?, a_native.inverse().unwrap());
136
137            let a_b_inv = a.mul_by_inverse(&b)?;
138            a_b_inv.mul_equals(&b, &a)?;
139            assert_eq!(a_b_inv.value()?, a_native * b_native.inverse().unwrap());
140
141            // a * a * a = a^3
142            let bits = BitIteratorLE::without_trailing_zeros([3u64])
143                .map(Boolean::constant)
144                .collect::<Vec<_>>();
145            assert_eq!(a_native.pow([0x3]), a.pow_le(&bits)?.value()?);
146
147            // a * a * a = a^3
148            assert_eq!(a_native.pow([0x3]), a.pow_by_constant(&[0x3])?.value()?);
149            assert!(cs.is_satisfied().unwrap());
150
151            let mut constants = [F::zero(); 4];
152            for c in &mut constants {
153                *c = UniformRand::rand(&mut test_rng());
154            }
155            let bits = [
156                Boolean::<ConstraintF>::constant(false),
157                Boolean::constant(true),
158            ];
159            let lookup_result = AF::two_bit_lookup(&bits, constants.as_ref())?;
160            assert_eq!(lookup_result.value()?, constants[2]);
161            assert!(cs.is_satisfied().unwrap());
162
163            let f = F::from(1u128 << 64);
164            let f_bits = ark_ff::BitIteratorLE::new(&[0u64, 1u64]).collect::<Vec<_>>();
165            let fv = AF::new_variable(ark_relations::ns!(cs, "alloc u128"), || Ok(f), mode)?;
166            assert_eq!(fv.to_bits_le()?.value().unwrap()[..128], f_bits[..128]);
167            assert!(cs.is_satisfied().unwrap());
168
169            let r_native: F = UniformRand::rand(&mut test_rng());
170
171            let r = AF::new_variable(ark_relations::ns!(cs, "r_native"), || Ok(r_native), mode)
172                .unwrap();
173            let _ = r.to_non_unique_bits_le()?;
174            assert!(cs.is_satisfied().unwrap());
175            let _ = r.to_bits_le()?;
176            assert!(cs.is_satisfied().unwrap());
177
178            let ab_false = &a + (AF::from(Boolean::Constant(false)) * b_native);
179            let ab_true = &a + (AF::from(Boolean::Constant(true)) * b_native);
180            assert_eq!(ab_false.value()?, a_native);
181            assert_eq!(ab_true.value()?, a_native + &b_native);
182
183            if !cs.is_satisfied().unwrap() {
184                panic!(
185                    "Unsatisfied in mode {:?}.\n{:?}",
186                    mode,
187                    cs.which_is_unsatisfied().unwrap()
188                );
189            }
190            assert!(cs.is_satisfied().unwrap());
191        }
192        Ok(())
193    }
194
195    pub fn frobenius_tests<F: Field, ConstraintF, AF>(maxpower: usize) -> Result<(), SynthesisError>
196    where
197        F: Field,
198        ConstraintF: PrimeField,
199        AF: FieldVar<F, ConstraintF>,
200        for<'a> &'a AF: FieldOpsBounds<'a, F, AF>,
201    {
202        let modes = [
203            AllocationMode::Input,
204            AllocationMode::Witness,
205            AllocationMode::Constant,
206        ];
207        for &mode in &modes {
208            let cs = ConstraintSystem::<ConstraintF>::new_ref();
209            let mut rng = test_rng();
210            for i in 0..=maxpower {
211                let mut a = F::rand(&mut rng);
212                let mut a_gadget = AF::new_variable(ark_relations::ns!(cs, "a"), || Ok(a), mode)?;
213                a_gadget.frobenius_map_in_place(i)?;
214                a.frobenius_map_in_place(i);
215
216                assert_eq!(a_gadget.value()?, a);
217            }
218
219            assert!(cs.is_satisfied().unwrap());
220        }
221        Ok(())
222    }
223}
224
225pub mod curves {
226    use ark_ec::{
227        short_weierstrass::Projective as SWProjective, twisted_edwards::Projective as TEProjective,
228        AdditiveGroup, CurveGroup,
229    };
230    use ark_ff::{BitIteratorLE, Field, One, PrimeField};
231    use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
232    use ark_std::{test_rng, vec::*, UniformRand};
233
234    use ark_r1cs_std::{fields::emulated_fp::EmulatedFpVar, prelude::*};
235
236    pub fn group_test<C, ConstraintF, GG>() -> Result<(), SynthesisError>
237    where
238        C: CurveGroup,
239        ConstraintF: PrimeField,
240        GG: CurveVar<C, ConstraintF>,
241        for<'a> &'a GG: GroupOpsBounds<'a, C, GG>,
242    {
243        let modes = [
244            AllocationMode::Input,
245            AllocationMode::Witness,
246            AllocationMode::Constant,
247        ];
248        for &mode in &modes {
249            let cs = ConstraintSystem::<ConstraintF>::new_ref();
250
251            let mut rng = test_rng();
252            let a_native = C::rand(&mut rng);
253            let b_native = C::rand(&mut rng);
254            let a = GG::new_variable(ark_relations::ns!(cs, "generate_a"), || Ok(a_native), mode)
255                .unwrap();
256            let b = GG::new_variable(ark_relations::ns!(cs, "generate_b"), || Ok(b_native), mode)
257                .unwrap();
258
259            let zero = GG::zero();
260            assert_eq!(zero.value()?, zero.value()?);
261
262            // a == a
263            assert_eq!(a.value()?, a.value()?);
264            // a + 0 = a
265            assert_eq!((&a + &zero).value()?, a.value()?);
266            // a - 0 = a
267            assert_eq!((&a - &zero).value()?, a.value()?);
268            // a - a = 0
269            assert_eq!((&a - &a).value()?, zero.value()?);
270            // a + b = b + a
271            let a_b = &a + &b;
272            let b_a = &b + &a;
273            assert_eq!(a_b.value()?, b_a.value()?);
274            a_b.enforce_equal(&b_a)?;
275            assert!(cs.is_satisfied().unwrap());
276
277            // (a + b) + a = a + (b + a)
278            let ab_a = &a_b + &a;
279            let a_ba = &a + &b_a;
280            assert_eq!(ab_a.value()?, a_ba.value()?);
281            ab_a.enforce_equal(&a_ba)?;
282            assert!(cs.is_satisfied().unwrap());
283
284            // a.double() = a + a
285            let a_a = &a + &a;
286            let mut a2 = a.clone();
287            a2.double_in_place()?;
288            a2.enforce_equal(&a_a)?;
289            assert_eq!(a2.value()?, a_native.double());
290            assert_eq!(a_a.value()?, a_native.double());
291            assert_eq!(a2.value()?, a_a.value()?);
292            assert!(cs.is_satisfied().unwrap());
293
294            // b.double() = b + b
295            let mut b2 = b.clone();
296            b2.double_in_place()?;
297            let b_b = &b + &b;
298            b2.enforce_equal(&b_b)?;
299            assert!(cs.is_satisfied().unwrap());
300            assert_eq!(b2.value()?, b_b.value()?);
301
302            let _ = a.to_bytes_le()?;
303            assert!(cs.is_satisfied().unwrap());
304            let _ = a.to_non_unique_bytes_le()?;
305            assert!(cs.is_satisfied().unwrap());
306
307            let _ = b.to_bytes_le()?;
308            let _ = b.to_non_unique_bytes_le()?;
309            if !cs.is_satisfied().unwrap() {
310                panic!(
311                    "Unsatisfied in mode {:?}.\n{:?}",
312                    mode,
313                    cs.which_is_unsatisfied().unwrap()
314                );
315            }
316            assert!(cs.is_satisfied().unwrap());
317
318            let modulus = C::ScalarField::MODULUS.as_ref().to_vec();
319            let mut max = modulus.clone();
320            for limb in &mut max {
321                *limb = u64::MAX;
322            }
323
324            let num_limbs = max.len();
325
326            let modulus_num_bits_mod_64 = <C::ScalarField as PrimeField>::MODULUS_BIT_SIZE % 64;
327            if modulus_num_bits_mod_64 != 0 {
328                *max.last_mut().unwrap() >>= 64 - modulus_num_bits_mod_64;
329            }
330            let scalars = [
331                C::ScalarField::rand(&mut rng)
332                    .into_bigint()
333                    .as_ref()
334                    .to_vec(),
335                vec![u64::rand(&mut rng)],
336                (-C::ScalarField::one()).into_bigint().as_ref().to_vec(),
337                modulus,
338                max,
339                vec![0u64; num_limbs],
340                vec![1000012341233u64; num_limbs],
341            ];
342
343            let mut input = vec![];
344
345            // Check scalar mul with edge cases
346            for scalar in scalars.iter() {
347                let native_result = a_native.mul_bigint(scalar);
348                let native_result = native_result.into_affine();
349
350                let scalar_bits: Vec<bool> = BitIteratorLE::new(&scalar).collect();
351                input =
352                    Vec::new_witness(ark_relations::ns!(cs, "bits"), || Ok(scalar_bits)).unwrap();
353                let scalar_var = EmulatedFpVar::new_variable(
354                    ark_relations::ns!(cs, "scalar"),
355                    || {
356                        let scalar = scalar
357                            .iter()
358                            .flat_map(|b| b.to_le_bytes())
359                            .collect::<Vec<_>>();
360                        Ok(C::ScalarField::from_le_bytes_mod_order(&scalar))
361                    },
362                    mode,
363                )
364                .unwrap();
365                let result = a
366                    .scalar_mul_le(input.iter())
367                    .expect(&format!("Mode: {:?}", mode));
368                let mul_result = a.clone() * scalar_var;
369                let result_val = result.value()?.into_affine();
370                assert_eq!(
371                    result_val, native_result,
372                    "gadget & native values are diff. after scalar mul {:?}",
373                    scalar,
374                );
375                assert_eq!(mul_result.value().unwrap().into_affine(), native_result);
376                assert!(cs.is_satisfied().unwrap());
377            }
378
379            let result = zero.scalar_mul_le(input.iter())?;
380            let result_val = result.value()?.into_affine();
381            result.enforce_equal(&zero)?;
382            assert_eq!(
383                result_val,
384                C::zero().into_affine(),
385                "gadget & native values are diff. after scalar mul of zero"
386            );
387            assert!(cs.is_satisfied().unwrap());
388        }
389        Ok(())
390    }
391
392    pub fn sw_test<P, GG>() -> Result<(), SynthesisError>
393    where
394        P: ark_ec::models::short_weierstrass::SWCurveConfig,
395        GG: CurveVar<SWProjective<P>, <P::BaseField as Field>::BasePrimeField>,
396        for<'a> &'a GG: GroupOpsBounds<'a, SWProjective<P>, GG>,
397    {
398        group_test::<SWProjective<P>, _, GG>()?;
399        let modes = [
400            AllocationMode::Input,
401            AllocationMode::Witness,
402            AllocationMode::Constant,
403        ];
404        for &mode in &modes {
405            let mut rng = test_rng();
406
407            let cs = ConstraintSystem::<<P::BaseField as Field>::BasePrimeField>::new_ref();
408
409            let a = SWProjective::<P>::rand(&mut rng);
410            let b = SWProjective::<P>::rand(&mut rng);
411            let a_affine = a.into_affine();
412            let b_affine = b.into_affine();
413
414            let ns = ark_relations::ns!(cs, "allocating variables");
415            let mut gadget_a = GG::new_variable(cs.clone(), || Ok(a), mode)?;
416            let gadget_b = GG::new_variable(cs.clone(), || Ok(b), mode)?;
417            let zero = GG::zero();
418            drop(ns);
419            assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x);
420            assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y);
421            assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x);
422            assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y);
423            assert_eq!(cs.which_is_unsatisfied().unwrap(), None);
424
425            // Check addition
426            let ab = a + &b;
427            let ab_affine = ab.into_affine();
428            let gadget_ab = &gadget_a + &gadget_b;
429            let gadget_ba = &gadget_b + &gadget_a;
430            gadget_ba.enforce_equal(&gadget_ab)?;
431
432            let ab_val = gadget_ab.value()?.into_affine();
433            assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
434            assert!(cs.is_satisfied().unwrap());
435
436            let gadget_a_zero = &gadget_a + &zero;
437            gadget_a_zero.enforce_equal(&gadget_a)?;
438
439            // Check doubling
440            let aa = &a.double();
441            let aa_affine = aa.into_affine();
442            gadget_a.double_in_place()?;
443            let aa_val = gadget_a.value()?.into_affine();
444            assert_eq!(
445                aa_val, aa_affine,
446                "Gadget and native values are unequal after double."
447            );
448            assert!(cs.is_satisfied().unwrap());
449
450            if !cs.is_satisfied().unwrap() {
451                panic!(
452                    "Unsatisfied in mode {:?}.\n{:?}",
453                    mode,
454                    cs.which_is_unsatisfied().unwrap()
455                );
456            }
457
458            assert!(cs.is_satisfied().unwrap());
459        }
460        Ok(())
461    }
462
463    pub fn te_test<P, GG>() -> Result<(), SynthesisError>
464    where
465        P: ark_ec::twisted_edwards::TECurveConfig,
466        GG: CurveVar<TEProjective<P>, <P::BaseField as Field>::BasePrimeField>,
467        for<'a> &'a GG: GroupOpsBounds<'a, TEProjective<P>, GG>,
468    {
469        group_test::<TEProjective<P>, _, GG>()?;
470        let modes = [
471            AllocationMode::Input,
472            AllocationMode::Witness,
473            AllocationMode::Constant,
474        ];
475        for &mode in &modes {
476            let mut rng = test_rng();
477
478            let cs = ConstraintSystem::<<P::BaseField as Field>::BasePrimeField>::new_ref();
479
480            let a = TEProjective::<P>::rand(&mut rng);
481            let b = TEProjective::<P>::rand(&mut rng);
482            let a_affine = a.into_affine();
483            let b_affine = b.into_affine();
484
485            let ns = ark_relations::ns!(cs, "allocating variables");
486            let mut gadget_a = GG::new_variable(cs.clone(), || Ok(a), mode)?;
487            let gadget_b = GG::new_variable(cs.clone(), || Ok(b), mode)?;
488            drop(ns);
489
490            assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x);
491            assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y);
492            assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x);
493            assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y);
494            assert_eq!(cs.which_is_unsatisfied()?, None);
495
496            // Check addition
497            let ab = a + &b;
498            let ab_affine = ab.into_affine();
499            let gadget_ab = &gadget_a + &gadget_b;
500            let gadget_ba = &gadget_b + &gadget_a;
501            gadget_ba.enforce_equal(&gadget_ab)?;
502
503            let ab_val = gadget_ab.value()?.into_affine();
504            assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
505            assert!(cs.is_satisfied().unwrap());
506
507            // Check doubling
508            let aa = &a.double();
509            let aa_affine = aa.into_affine();
510            gadget_a.double_in_place()?;
511            let aa_val = gadget_a.value()?.into_affine();
512            assert_eq!(
513                aa_val, aa_affine,
514                "Gadget and native values are unequal after double."
515            );
516            assert!(cs.is_satisfied().unwrap());
517
518            if !cs.is_satisfied().unwrap() {
519                panic!(
520                    "Unsatisfied in mode {:?}.\n{:?}",
521                    mode,
522                    cs.which_is_unsatisfied().unwrap()
523                );
524            }
525
526            assert!(cs.is_satisfied().unwrap());
527        }
528        Ok(())
529    }
530}
531
532pub mod pairing {
533    use ark_ec::{
534        pairing::{Pairing, PairingOutput},
535        AffineRepr, CurveGroup,
536    };
537    use ark_ff::{BitIteratorLE, Field, PrimeField};
538    use ark_r1cs_std::prelude::*;
539    use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
540    use ark_std::{test_rng, vec::*, UniformRand};
541
542    type BasePrimeField<P> = <<P as Pairing>::BaseField as Field>::BasePrimeField;
543
544    #[allow(dead_code)]
545    pub fn bilinearity_test<E: Pairing, P: PairingVar<E>>() -> Result<(), SynthesisError>
546    where
547        for<'a> &'a P::G1Var: GroupOpsBounds<'a, E::G1, P::G1Var>,
548        for<'a> &'a P::G2Var: GroupOpsBounds<'a, E::G2, P::G2Var>,
549        for<'a> &'a P::GTVar: FieldOpsBounds<'a, E::TargetField, P::GTVar>,
550    {
551        let modes = [
552            AllocationMode::Input,
553            AllocationMode::Witness,
554            AllocationMode::Constant,
555        ];
556        for &mode in &modes {
557            let cs = ConstraintSystem::<BasePrimeField<E>>::new_ref();
558
559            let mut rng = test_rng();
560            let a = E::G1::rand(&mut rng);
561            let b = E::G2::rand(&mut rng);
562            let s = E::ScalarField::rand(&mut rng);
563
564            let mut sa = a;
565            sa *= s;
566            let mut sb = b;
567            sb *= s;
568
569            let a_g = P::G1Var::new_variable(cs.clone(), || Ok(a.into_affine()), mode)?;
570            let b_g = P::G2Var::new_variable(cs.clone(), || Ok(b.into_affine()), mode)?;
571            let sa_g = P::G1Var::new_variable(cs.clone(), || Ok(sa.into_affine()), mode)?;
572            let sb_g = P::G2Var::new_variable(cs.clone(), || Ok(sb.into_affine()), mode)?;
573
574            let mut _preparation_num_constraints = cs.num_constraints();
575            let a_prep_g = P::prepare_g1(&a_g)?;
576            let b_prep_g = P::prepare_g2(&b_g)?;
577            _preparation_num_constraints = cs.num_constraints() - _preparation_num_constraints;
578
579            let sa_prep_g = P::prepare_g1(&sa_g)?;
580            let sb_prep_g = P::prepare_g2(&sb_g)?;
581
582            let (ans1_g, ans1_n) = {
583                let _ml_constraints = cs.num_constraints();
584                let ml_g = P::miller_loop(&[sa_prep_g], &[b_prep_g.clone()])?;
585                let _fe_constraints = cs.num_constraints();
586                let ans_g = P::final_exponentiation(&ml_g)?;
587                let ans_n = E::pairing(sa, b);
588                (ans_g, ans_n)
589            };
590
591            let (ans2_g, ans2_n) = {
592                let ans_g = P::pairing(a_prep_g.clone(), sb_prep_g)?;
593                let ans_n = E::pairing(a, sb);
594                (ans_g, ans_n)
595            };
596
597            let (ans3_g, ans3_n) = {
598                let s_iter = BitIteratorLE::without_trailing_zeros(s.into_bigint())
599                    .map(Boolean::constant)
600                    .collect::<Vec<_>>();
601
602                let mut ans_g = P::pairing(a_prep_g, b_prep_g)?;
603                let mut ans_n = E::pairing(a, b);
604                ans_n = PairingOutput(ans_n.0.pow(s.into_bigint()));
605                ans_g = ans_g.pow_le(&s_iter)?;
606
607                (ans_g, ans_n)
608            };
609
610            ans1_g.enforce_equal(&ans2_g)?;
611            ans2_g.enforce_equal(&ans3_g)?;
612
613            assert_eq!(ans1_g.value()?, ans1_n.0, "Failed native test 1");
614            assert_eq!(ans2_g.value()?, ans2_n.0, "Failed native test 2");
615            assert_eq!(ans3_g.value()?, ans3_n.0, "Failed native test 3");
616
617            assert_eq!(ans1_n.0, ans2_n.0, "Failed ans1_native == ans2_native");
618            assert_eq!(ans2_n.0, ans3_n.0, "Failed ans2_native == ans3_native");
619            assert_eq!(ans1_g.value()?, ans3_g.value()?, "Failed ans1 == ans3");
620            assert_eq!(ans1_g.value()?, ans2_g.value()?, "Failed ans1 == ans2");
621            assert_eq!(ans2_g.value()?, ans3_g.value()?, "Failed ans2 == ans3");
622
623            if !cs.is_satisfied().unwrap() {
624                panic!(
625                    "Unsatisfied in mode {:?}.\n{:?}",
626                    mode,
627                    cs.which_is_unsatisfied().unwrap()
628                );
629            }
630
631            assert!(cs.is_satisfied().unwrap(), "cs is not satisfied");
632        }
633        Ok(())
634    }
635
636    #[allow(dead_code)]
637    pub fn g2_prepare_consistency_test<E: Pairing, P: PairingVar<E>>() -> Result<(), SynthesisError>
638    {
639        let test_g2_elem = E::G2Affine::generator();
640        let test_g2_prepared = E::G2Prepared::from(test_g2_elem.clone());
641
642        let modes = [
643            AllocationMode::Input,
644            AllocationMode::Witness,
645            AllocationMode::Constant,
646        ];
647        for &mode in &modes {
648            let cs = ConstraintSystem::new_ref();
649
650            let test_g2_gadget =
651                P::G2Var::new_witness(cs.clone(), || Ok(test_g2_elem.clone())).unwrap();
652
653            let prepared_test_g2_gadget = P::prepare_g2(&test_g2_gadget).unwrap();
654            let allocated_test_g2_gadget =
655                P::G2PreparedVar::new_variable(cs.clone(), || Ok(test_g2_prepared.clone()), mode)
656                    .unwrap();
657
658            let prepared_test_g2_gadget_bytes = prepared_test_g2_gadget.to_bytes_le().unwrap();
659            let allocated_test_g2_gadget_bytes = allocated_test_g2_gadget.to_bytes_le().unwrap();
660
661            prepared_test_g2_gadget_bytes
662                .enforce_equal(&allocated_test_g2_gadget_bytes)
663                .unwrap();
664
665            assert!(cs.is_satisfied().unwrap(), "cs is not satisfied");
666        }
667        Ok(())
668    }
669}