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, PrimeField, UniformRand};
6 use ark_r1cs_std::prelude::*;
7 use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
8 use ark_std::{test_rng, vec::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: Field,
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(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 CurveGroup, Group,
229 };
230 use ark_ff::{BitIteratorLE, Field, One, PrimeField};
231 use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
232 use ark_std::{test_rng, vec::Vec, UniformRand};
233
234 use ark_r1cs_std::prelude::*;
235
236 pub fn group_test<C, ConstraintF, GG>() -> Result<(), SynthesisError>
237 where
238 C: CurveGroup,
239 ConstraintF: Field,
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()?;
303 assert!(cs.is_satisfied().unwrap());
304 let _ = a.to_non_unique_bytes()?;
305 assert!(cs.is_satisfied().unwrap());
306
307 let _ = b.to_bytes()?;
308 let _ = b.to_non_unique_bytes()?;
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 as PrimeField>::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 modulus_last_limb_bits = <C::ScalarField as PrimeField>::MODULUS_BIT_SIZE % 64;
325 *max.last_mut().unwrap() >>= 64 - modulus_last_limb_bits;
326 let scalars = [
327 C::ScalarField::rand(&mut rng)
328 .into_bigint()
329 .as_ref()
330 .to_vec(),
331 vec![u64::rand(&mut rng)],
332 (-C::ScalarField::one()).into_bigint().as_ref().to_vec(),
333 <C::ScalarField as PrimeField>::MODULUS.as_ref().to_vec(),
334 max,
335 vec![0; 50],
336 vec![1000012341233u64; 36],
337 ];
338
339 let mut input = vec![];
340
341 // Check scalar mul with edge cases
342 for scalar in scalars.iter() {
343 let native_result = a_native.mul_bigint(scalar);
344 let native_result = native_result.into_affine();
345
346 let scalar_bits: Vec<bool> = BitIteratorLE::new(&scalar).collect();
347 input =
348 Vec::new_witness(ark_relations::ns!(cs, "bits"), || Ok(scalar_bits)).unwrap();
349 let result = a
350 .scalar_mul_le(input.iter())
351 .expect(&format!("Mode: {:?}", mode));
352 let result_val = result.value()?.into_affine();
353 assert_eq!(
354 result_val, native_result,
355 "gadget & native values are diff. after scalar mul {:?}",
356 scalar,
357 );
358 assert!(cs.is_satisfied().unwrap());
359 }
360
361 let result = zero.scalar_mul_le(input.iter())?;
362 let result_val = result.value()?.into_affine();
363 result.enforce_equal(&zero)?;
364 assert_eq!(
365 result_val,
366 C::zero().into_affine(),
367 "gadget & native values are diff. after scalar mul of zero"
368 );
369 assert!(cs.is_satisfied().unwrap());
370 }
371 Ok(())
372 }
373
374 pub fn sw_test<P, GG>() -> Result<(), SynthesisError>
375 where
376 P: ark_ec::models::short_weierstrass::SWCurveConfig,
377 GG: CurveVar<SWProjective<P>, <P::BaseField as Field>::BasePrimeField>,
378 for<'a> &'a GG: GroupOpsBounds<'a, SWProjective<P>, GG>,
379 {
380 group_test::<SWProjective<P>, _, GG>()?;
381 let modes = [
382 AllocationMode::Input,
383 AllocationMode::Witness,
384 AllocationMode::Constant,
385 ];
386 for &mode in &modes {
387 let mut rng = test_rng();
388
389 let cs = ConstraintSystem::<<P::BaseField as Field>::BasePrimeField>::new_ref();
390
391 let a = SWProjective::<P>::rand(&mut rng);
392 let b = SWProjective::<P>::rand(&mut rng);
393 let a_affine = a.into_affine();
394 let b_affine = b.into_affine();
395
396 let ns = ark_relations::ns!(cs, "allocating variables");
397 let mut gadget_a = GG::new_variable(cs.clone(), || Ok(a), mode)?;
398 let gadget_b = GG::new_variable(cs.clone(), || Ok(b), mode)?;
399 let zero = GG::zero();
400 drop(ns);
401 assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x);
402 assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y);
403 assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x);
404 assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y);
405 assert_eq!(cs.which_is_unsatisfied().unwrap(), None);
406
407 // Check addition
408 let ab = a + &b;
409 let ab_affine = ab.into_affine();
410 let gadget_ab = &gadget_a + &gadget_b;
411 let gadget_ba = &gadget_b + &gadget_a;
412 gadget_ba.enforce_equal(&gadget_ab)?;
413
414 let ab_val = gadget_ab.value()?.into_affine();
415 assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
416 assert!(cs.is_satisfied().unwrap());
417
418 let gadget_a_zero = &gadget_a + &zero;
419 gadget_a_zero.enforce_equal(&gadget_a)?;
420
421 // Check doubling
422 let aa = &a.double();
423 let aa_affine = aa.into_affine();
424 gadget_a.double_in_place()?;
425 let aa_val = gadget_a.value()?.into_affine();
426 assert_eq!(
427 aa_val, aa_affine,
428 "Gadget and native values are unequal after double."
429 );
430 assert!(cs.is_satisfied().unwrap());
431
432 if !cs.is_satisfied().unwrap() {
433 panic!(
434 "Unsatisfied in mode {:?}.\n{:?}",
435 mode,
436 cs.which_is_unsatisfied().unwrap()
437 );
438 }
439
440 assert!(cs.is_satisfied().unwrap());
441 }
442 Ok(())
443 }
444
445 pub fn te_test<P, GG>() -> Result<(), SynthesisError>
446 where
447 P: ark_ec::twisted_edwards::TECurveConfig,
448 GG: CurveVar<TEProjective<P>, <P::BaseField as Field>::BasePrimeField>,
449 for<'a> &'a GG: GroupOpsBounds<'a, TEProjective<P>, GG>,
450 {
451 group_test::<TEProjective<P>, _, GG>()?;
452 let modes = [
453 AllocationMode::Input,
454 AllocationMode::Witness,
455 AllocationMode::Constant,
456 ];
457 for &mode in &modes {
458 let mut rng = test_rng();
459
460 let cs = ConstraintSystem::<<P::BaseField as Field>::BasePrimeField>::new_ref();
461
462 let a = TEProjective::<P>::rand(&mut rng);
463 let b = TEProjective::<P>::rand(&mut rng);
464 let a_affine = a.into_affine();
465 let b_affine = b.into_affine();
466
467 let ns = ark_relations::ns!(cs, "allocating variables");
468 let mut gadget_a = GG::new_variable(cs.clone(), || Ok(a), mode)?;
469 let gadget_b = GG::new_variable(cs.clone(), || Ok(b), mode)?;
470 drop(ns);
471
472 assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x);
473 assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y);
474 assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x);
475 assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y);
476 assert_eq!(cs.which_is_unsatisfied()?, None);
477
478 // Check addition
479 let ab = a + &b;
480 let ab_affine = ab.into_affine();
481 let gadget_ab = &gadget_a + &gadget_b;
482 let gadget_ba = &gadget_b + &gadget_a;
483 gadget_ba.enforce_equal(&gadget_ab)?;
484
485 let ab_val = gadget_ab.value()?.into_affine();
486 assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
487 assert!(cs.is_satisfied().unwrap());
488
489 // Check doubling
490 let aa = &a.double();
491 let aa_affine = aa.into_affine();
492 gadget_a.double_in_place()?;
493 let aa_val = gadget_a.value()?.into_affine();
494 assert_eq!(
495 aa_val, aa_affine,
496 "Gadget and native values are unequal after double."
497 );
498 assert!(cs.is_satisfied().unwrap());
499
500 if !cs.is_satisfied().unwrap() {
501 panic!(
502 "Unsatisfied in mode {:?}.\n{:?}",
503 mode,
504 cs.which_is_unsatisfied().unwrap()
505 );
506 }
507
508 assert!(cs.is_satisfied().unwrap());
509 }
510 Ok(())
511 }
512}
513
514pub mod pairing {
515 use ark_ec::{
516 pairing::{Pairing, PairingOutput},
517 CurveGroup,
518 };
519 use ark_ff::{BitIteratorLE, Field, PrimeField};
520 use ark_r1cs_std::prelude::*;
521 use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
522 use ark_std::{test_rng, vec::Vec, UniformRand};
523
524 #[allow(dead_code)]
525 pub fn bilinearity_test<E: Pairing, P: PairingVar<E>>() -> Result<(), SynthesisError>
526 where
527 for<'a> &'a P::G1Var: GroupOpsBounds<'a, E::G1, P::G1Var>,
528 for<'a> &'a P::G2Var: GroupOpsBounds<'a, E::G2, P::G2Var>,
529 for<'a> &'a P::GTVar: FieldOpsBounds<'a, E::TargetField, P::GTVar>,
530 {
531 let modes = [
532 AllocationMode::Input,
533 AllocationMode::Witness,
534 AllocationMode::Constant,
535 ];
536 for &mode in &modes {
537 let cs = ConstraintSystem::<<E::G1 as CurveGroup>::BaseField>::new_ref();
538
539 let mut rng = test_rng();
540 let a = E::G1::rand(&mut rng);
541 let b = E::G2::rand(&mut rng);
542 let s = E::ScalarField::rand(&mut rng);
543
544 let mut sa = a;
545 sa *= s;
546 let mut sb = b;
547 sb *= s;
548
549 let a_g = P::G1Var::new_variable(cs.clone(), || Ok(a.into_affine()), mode)?;
550 let b_g = P::G2Var::new_variable(cs.clone(), || Ok(b.into_affine()), mode)?;
551 let sa_g = P::G1Var::new_variable(cs.clone(), || Ok(sa.into_affine()), mode)?;
552 let sb_g = P::G2Var::new_variable(cs.clone(), || Ok(sb.into_affine()), mode)?;
553
554 let mut _preparation_num_constraints = cs.num_constraints();
555 let a_prep_g = P::prepare_g1(&a_g)?;
556 let b_prep_g = P::prepare_g2(&b_g)?;
557 _preparation_num_constraints = cs.num_constraints() - _preparation_num_constraints;
558
559 let sa_prep_g = P::prepare_g1(&sa_g)?;
560 let sb_prep_g = P::prepare_g2(&sb_g)?;
561
562 let (ans1_g, ans1_n) = {
563 let _ml_constraints = cs.num_constraints();
564 let ml_g = P::miller_loop(&[sa_prep_g], &[b_prep_g.clone()])?;
565 let _fe_constraints = cs.num_constraints();
566 let ans_g = P::final_exponentiation(&ml_g)?;
567 let ans_n = E::pairing(sa, b);
568 (ans_g, ans_n)
569 };
570
571 let (ans2_g, ans2_n) = {
572 let ans_g = P::pairing(a_prep_g.clone(), sb_prep_g)?;
573 let ans_n = E::pairing(a, sb);
574 (ans_g, ans_n)
575 };
576
577 let (ans3_g, ans3_n) = {
578 let s_iter = BitIteratorLE::without_trailing_zeros(s.into_bigint())
579 .map(Boolean::constant)
580 .collect::<Vec<_>>();
581
582 let mut ans_g = P::pairing(a_prep_g, b_prep_g)?;
583 let mut ans_n = E::pairing(a, b);
584 ans_n = PairingOutput(ans_n.0.pow(s.into_bigint()));
585 ans_g = ans_g.pow_le(&s_iter)?;
586
587 (ans_g, ans_n)
588 };
589
590 ans1_g.enforce_equal(&ans2_g)?;
591 ans2_g.enforce_equal(&ans3_g)?;
592
593 assert_eq!(ans1_g.value()?, ans1_n.0, "Failed native test 1");
594 assert_eq!(ans2_g.value()?, ans2_n.0, "Failed native test 2");
595 assert_eq!(ans3_g.value()?, ans3_n.0, "Failed native test 3");
596
597 assert_eq!(ans1_n.0, ans2_n.0, "Failed ans1_native == ans2_native");
598 assert_eq!(ans2_n.0, ans3_n.0, "Failed ans2_native == ans3_native");
599 assert_eq!(ans1_g.value()?, ans3_g.value()?, "Failed ans1 == ans3");
600 assert_eq!(ans1_g.value()?, ans2_g.value()?, "Failed ans1 == ans2");
601 assert_eq!(ans2_g.value()?, ans3_g.value()?, "Failed ans2 == ans3");
602
603 if !cs.is_satisfied().unwrap() {
604 panic!(
605 "Unsatisfied in mode {:?}.\n{:?}",
606 mode,
607 cs.which_is_unsatisfied().unwrap()
608 );
609 }
610
611 assert!(cs.is_satisfied().unwrap(), "cs is not satisfied");
612 }
613 Ok(())
614 }
615}