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