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