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