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