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 + b = b + a
281 let a_b = &a + &b;
282 let b_a = &b + &a;
283 assert_eq!(a_b.value()?, b_a.value()?);
284 a_b.enforce_equal(&b_a)?;
285 assert!(cs.is_satisfied().unwrap());
286 // a - a = 0
287 assert_eq!((&a - &a).value()?, zero.value()?);
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::miller_loop_gadget(&[sa_prep_g], &[b_prep_g.clone()])?;
584 let _fe_constraints = cs.num_constraints();
585 let ans_g = P::final_exponentiation_gadget(&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::pairing_gadget(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::pairing_gadget(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}