ark_algebra_test_templates/
groups.rs

1#[macro_export]
2#[doc(hidden)]
3macro_rules! __test_group {
4    ($group: ty) => {
5        type ScalarField = <$group as PrimeGroup>::ScalarField;
6        #[test]
7        fn test_add_properties() {
8            let mut rng = &mut ark_std::test_rng();
9            let zero = <$group>::zero();
10            for _ in 0..ITERATIONS {
11                let a = <$group>::rand(rng);
12                let b = <$group>::rand(rng);
13                let c = <$group>::rand(rng);
14
15                // Associativity
16                assert_eq!((a + b) + c, a + (b + c));
17
18                // Commutativity
19                assert_eq!(a + b, b + a);
20
21                // Identity
22                assert_eq!(zero + a, a);
23                assert_eq!(zero + b, b);
24                assert_eq!(zero + c, c);
25                assert_eq!(a + zero, a);
26                assert_eq!(b + zero, b);
27                assert_eq!(c + zero, c);
28
29                // Negation
30                assert_eq!(-a + a, zero);
31                assert_eq!(-b + b, zero);
32                assert_eq!(-c + c, zero);
33                assert_eq!(-zero, zero);
34
35                // Associativity and commutativity simultaneously
36                let t0 = (a + &b) + &c; // (a + b) + c
37                let t1 = (a + &c) + &b; // (a + c) + b
38                let t2 = (b + &c) + &a; // (b + c) + a
39
40                assert_eq!(t0, t1);
41                assert_eq!(t1, t2);
42
43                // Doubling
44                assert_eq!(a.double(), a + a);
45                assert_eq!(b.double(), b + b);
46                assert_eq!(c.double(), c + c);
47                assert_eq!(zero.double(), zero);
48                assert_eq!((-zero).double(), zero);
49            }
50        }
51
52        #[test]
53        fn test_sub_properties() {
54            use ark_std::UniformRand;
55            let mut rng = test_rng();
56            let zero = <$group>::zero();
57
58            for _ in 0..ITERATIONS{
59                // Anti-commutativity
60                let a = <$group>::rand(&mut rng);
61                let b = <$group>::rand(&mut rng);
62                assert!(((a - b) + (b - a)).is_zero());
63
64                // Identity
65                assert_eq!(zero - a, -a);
66                assert_eq!(zero - b, -b);
67
68                assert_eq!(a - zero, a);
69                assert_eq!(b - zero, b);
70
71                // Affine - Projective
72                assert_eq!(a.into_affine() - b, a - b);
73            }
74        }
75
76        #[test]
77        fn test_mul_properties() {
78            use ark_std::UniformRand;
79            let mut rng = test_rng();
80            let zero = ScalarField::zero();
81            let one = ScalarField::one();
82            assert_eq!(one.inverse().unwrap(), one);
83            assert!(one.is_one());
84
85            for _ in 0..ITERATIONS {
86                // Associativity
87                let a = <$group>::rand(&mut rng);
88                let b = ScalarField::rand(&mut rng);
89                let c = ScalarField::rand(&mut rng);
90                assert_eq!((a * b) * c, a * (b * c));
91
92                // Identity
93                assert_eq!(a * one, a);
94
95                assert_eq!(a * zero, <$group>::zero());
96
97                // Inverses
98                assert_eq!((a * b.inverse().unwrap()) * b, a);
99
100                // Distributivity
101                assert_eq!(a * (b + c), a * b + a * c);
102
103                // s ( a + b) using wNAF for several window values in [2,5]
104                for w in 2..=5 {
105                    let context = WnafContext::new(w);
106                    assert_eq!(a * b, context.mul(a, &b));
107
108                    let table = context.table(a);
109                    assert_eq!(a * b, context.mul_with_table(&table, &b).unwrap());
110
111                    if w > 2 {
112                        let bad_context = WnafContext::new(w - 1);
113                        let bad_table = bad_context.table(a);
114                        assert_eq!(context.mul_with_table(&bad_table, &b), None);
115                    }
116                }
117
118                // num_scalars != scalars.len()
119                let mut scalars = vec![ScalarField::rand(&mut rng); 100];
120                scalars[0] = ScalarField::zero();
121                let table = BatchMulPreprocessing::new(a, scalars.len() - 1);
122                let result = table.batch_mul(&scalars);
123                let naive_result = scalars
124                    .iter()
125                    .enumerate()
126                    .map(|(i, s)| a * s)
127                    .collect::<Vec<_>>();
128                assert_eq!(result, naive_result);
129            }
130        }
131
132        #[test]
133        fn test_serialization() {
134            for compress in [Compress::Yes, Compress::No] {
135                for validate in [Validate::Yes, Validate::No] {
136                    let buf_size = <$group>::zero().serialized_size(compress);
137
138                    let mut rng = ark_std::test_rng();
139
140                    // Test that serializing and deserializing random elements
141                    // works.
142                    for _ in 0..ITERATIONS {
143                        let a = <$group>::rand(&mut rng);
144                        {
145                            let mut serialized = vec![0; buf_size];
146                            let mut cursor = Cursor::new(&mut serialized[..]);
147                            a.serialize_with_mode(&mut cursor, compress).unwrap();
148
149                            let mut cursor = Cursor::new(&serialized[..]);
150                            let b = <$group>::deserialize_with_mode(&mut cursor, compress, validate).unwrap();
151                            assert_eq!(a, b);
152                        }
153                    }
154
155                    // Test that serializing and deserializing the identity element
156                    // works.
157                    {
158                        let a = <$group>::zero();
159                        let mut serialized = vec![0; buf_size];
160                        let mut cursor = Cursor::new(&mut serialized[..]);
161                        a.serialize_with_mode(&mut cursor, compress).unwrap();
162                        let mut cursor = Cursor::new(&serialized[..]);
163                        let b = <$group>::deserialize_with_mode(&mut cursor, compress, validate).unwrap();
164                        assert_eq!(a, b);
165                    }
166
167                    // Test that serializing the identity point into a buffer that
168                    // is not big enough will yield an error.
169                    {
170                        let a = <$group>::zero();
171                        let mut serialized = vec![0; buf_size - 1];
172                        let mut cursor = Cursor::new(&mut serialized[..]);
173                        a.serialize_with_mode(&mut cursor, compress).unwrap_err();
174                    }
175
176                    // Test that deserializing from a buffer that is not big enough
177                    // will yield and error.
178                    // This test does not explicitly check that the error is due to
179                    // a buffer that is not big enough.
180                    {
181                        let serialized = vec![0; buf_size - 1];
182                        let mut cursor = Cursor::new(&serialized[..]);
183                        <$group>::deserialize_with_mode(&mut cursor, compress, validate).unwrap_err();
184                    }
185                }
186            }
187        }
188    };
189    ($group:ty; msm) => {
190        #[test]
191        fn test_var_base_msm() {
192            $crate::msm::test_var_base_msm::<$group>();
193        }
194
195        #[test]
196        fn test_chunked_pippenger() {
197            $crate::msm::test_chunked_pippenger::<$group>();
198        }
199
200        #[test]
201        fn test_hashmap_pippenger() {
202            $crate::msm::test_hashmap_pippenger::<$group>();
203        }
204    };
205    ($group:ty; curve) => {
206        $crate::__test_group!($group);
207        $crate::__test_group!($group; msm);
208        type Affine = <$group as CurveGroup>::Affine;
209        type Config = <$group as CurveGroup>::Config;
210        type BaseField = <$group as CurveGroup>::BaseField;
211
212        #[test]
213        fn test_affine_conversion() {
214            let mut rng = &mut ark_std::test_rng();
215
216            for _ in 0..ITERATIONS {
217                let g = <$group>::rand(&mut rng);
218                let g_affine = g.into_affine();
219                let g_projective = g_affine.into_group();
220                assert_eq!(g, g_projective);
221            }
222
223            // Batch normalization
224            for _ in 0..10 {
225                let mut v = (0..ITERATIONS)
226                    .map(|_| <$group>::rand(&mut rng).double())
227                    .collect::<Vec<_>>();
228
229                use ark_std::rand::distributions::{Distribution, Uniform};
230                let between = Uniform::from(0..ITERATIONS);
231                // Sprinkle in some normalized points
232                for _ in 0..5 {
233                    v[between.sample(&mut rng)] = <$group>::zero();
234                }
235                for _ in 0..5 {
236                    let s = between.sample(&mut rng);
237                    v[s] = v[s].into_affine().into_group();
238                }
239
240                let expected_v = v.iter().map(|v| v.into_affine()).collect::<Vec<_>>();
241                let actual_v = <$group>::normalize_batch(&v);
242
243                assert_eq!(actual_v, expected_v);
244            }
245        }
246
247        #[test]
248        fn test_cofactor_ops() {
249            let rng = &mut ark_std::test_rng();
250            for _ in 0..ITERATIONS {
251                let a = Affine::rand(rng);
252                assert_eq!(a.mul_by_cofactor_to_group(), a.mul_bigint(&Config::COFACTOR));
253                assert_eq!(a.mul_by_cofactor(), a.mul_bigint(&Config::COFACTOR));
254                assert_eq!(a.mul_by_cofactor().mul_by_cofactor_inv(), a);
255                assert_eq!(a.mul_by_cofactor_inv().mul_by_cofactor(), a);
256                assert_eq!(a.mul_by_cofactor_inv(), a * Config::COFACTOR_INV);
257
258                assert!(a.clear_cofactor().is_in_correct_subgroup_assuming_on_curve());
259            }
260        }
261
262        #[test]
263        fn test_mixed_addition() {
264            let rng = &mut ark_std::test_rng();
265            for _ in 0..ITERATIONS {
266                let a = Affine::rand(rng);
267                let a_group = a.into_group();
268                let b = <$group>::rand(rng);
269                assert!(a.is_on_curve());
270                assert!(b.into_affine().is_on_curve());
271                assert_eq!(b + a, b + a_group, "b + a failed on input {a}, {b}");
272                assert_eq!(a + b, a_group + b, "a + b failed on input {a}, {b}");
273            }
274        }
275    };
276    ($group:ty; sw) => {
277        $crate::__test_group!($group; curve);
278
279        #[test]
280        fn test_sw_properties() {
281            let mut rng = &mut ark_std::test_rng();
282
283            let generator = <$group>::generator().into_affine();
284            assert!(generator.is_on_curve());
285            assert!(generator.is_in_correct_subgroup_assuming_on_curve());
286
287            for i in 0.. {
288                let x = BaseField::from(i);
289                // y^2 = x^3 + a * x + b
290                let rhs = x * x.square() + x * <Config as SWCurveConfig>::COEFF_A + <Config as SWCurveConfig>::COEFF_B;
291
292                if let Some(y) = rhs.sqrt() {
293                    let p = Affine::new_unchecked(x, if y < -y { y } else { -y });
294                    if !<<$group as CurveGroup>::Config as CurveConfig>::cofactor_is_one() {
295                        if p.is_in_correct_subgroup_assuming_on_curve() {
296                            continue;
297                        }
298                    }
299
300                    let g1 = p.mul_by_cofactor_to_group();
301                    if !g1.is_zero() {
302                        let g1 = Affine::from(g1);
303                        assert!(g1.is_in_correct_subgroup_assuming_on_curve());
304                        break;
305                    }
306                }
307            }
308
309            for _ in 0..ITERATIONS {
310                let f = BaseField::rand(rng);
311                assert_eq!(<Config as SWCurveConfig>::mul_by_a(f), f * <Config as SWCurveConfig>::COEFF_A);
312                assert_eq!(<Config as SWCurveConfig>::add_b(f), f + <Config as SWCurveConfig>::COEFF_B);
313            }
314            {
315                use ark_ec::models::short_weierstrass::SWFlags;
316                for compress in [Compress::Yes, Compress::No] {
317                    for flag in [SWFlags::PointAtInfinity, SWFlags::YIsNegative, SWFlags::YIsPositive] {
318                        let a = BaseField::rand(&mut rng);
319                        let buf_size = a.serialized_size(compress);
320                        let mut serialized = vec![0u8; buf_size + 1];
321                        let mut cursor = Cursor::new(&mut serialized[..]);
322                        a.serialize_with_flags(&mut cursor, flag)
323                        .unwrap();
324                        let mut cursor = Cursor::new(&serialized[..]);
325                        let (b, flags) = BaseField::deserialize_with_flags::<_, SWFlags>(&mut cursor).unwrap();
326                        assert_eq!(flags, flag);
327                        assert_eq!(a, b);
328                    }
329
330                }
331            }
332        }
333    };
334    ($group:ty; te) => {
335        $crate::__test_group!($group; curve);
336
337        #[test]
338        fn test_te_properties() {
339            let mut rng = &mut ark_std::test_rng();
340
341            let generator = <$group>::generator().into_affine();
342            assert!(generator.is_on_curve());
343            assert!(generator.is_in_correct_subgroup_assuming_on_curve());
344            let mut y = BaseField::zero();
345            let one = BaseField::one();
346            for _ in 0..ITERATIONS {
347                let f = BaseField::rand(rng);
348                assert_eq!(<Config as TECurveConfig>::mul_by_a(f), f * <Config as TECurveConfig>::COEFF_A);
349            }
350            {
351                use ark_ec::models::twisted_edwards::TEFlags;
352                for compress in [Compress::Yes, Compress::No] {
353                    for flag in [TEFlags::XIsPositive, TEFlags::XIsNegative] {
354                        let a = BaseField::rand(&mut rng);
355                        let buf_size = a.serialized_size(compress);
356                        let mut serialized = vec![0u8; buf_size + 1];
357                        let mut cursor = Cursor::new(&mut serialized[..]);
358                        a.serialize_with_flags(&mut cursor, flag)
359                        .unwrap();
360                        let mut cursor = Cursor::new(&serialized[..]);
361                        let (b, flags) = BaseField::deserialize_with_flags::<_, TEFlags>(&mut cursor).unwrap();
362                        assert_eq!(flags, flag);
363                        assert_eq!(a, b);
364                    }
365
366                }
367            }
368        }
369
370        #[test]
371        fn test_montgomery_conversion_test()
372        {
373            use ark_ec::twisted_edwards::MontCurveConfig;
374            // A = 2 * (a + d) / (a - d)
375            let a = <Config as CurveConfig>::BaseField::one().double()
376                * &(<Config as TECurveConfig>::COEFF_A + &<Config as TECurveConfig>::COEFF_D)
377                * &(<Config as TECurveConfig>::COEFF_A - &<Config as TECurveConfig>::COEFF_D).inverse().unwrap();
378            // B = 4 / (a - d)
379            let b = <Config as CurveConfig>::BaseField::one().double().double() *
380                &(<Config as TECurveConfig>::COEFF_A - &<Config as TECurveConfig>::COEFF_D).inverse().unwrap();
381
382            assert_eq!(a, <Config as MontCurveConfig>::COEFF_A);
383            assert_eq!(b, <Config as MontCurveConfig>::COEFF_B);
384        }
385    };
386    ($group:ty; glv) => {
387        type Config = <$group as CurveGroup>::Config;
388
389        #[test]
390        fn test_scalar_decomposition()
391        {
392            $crate::glv::glv_scalar_decomposition::<Config>();
393        }
394
395
396        #[test]
397        fn test_endomorphism_eigenvalue() {
398            $crate::glv::glv_endomorphism_eigenvalue::<Config>();
399        }
400
401        #[test]
402        fn test_glv_mul() {
403            $crate::glv::glv_projective::<Config>();
404            $crate::glv::glv_affine::<Config>();
405        }
406    }
407}
408
409#[macro_export]
410macro_rules! test_group {
411    ($mod_name:ident; $group:ty $(; $tail:tt)* ) => {
412        mod $mod_name {
413            use super::*;
414            use ark_ff::*;
415            use ark_ec::{PrimeGroup, CurveGroup, ScalarMul, AffineRepr, CurveConfig, short_weierstrass::SWCurveConfig, twisted_edwards::TECurveConfig, scalar_mul::{*, wnaf::*}};
416            use ark_serialize::*;
417            use ark_std::{io::Cursor, rand::Rng, vec::*, test_rng, vec, Zero, One, UniformRand};
418            const ITERATIONS: usize = 500;
419
420            $crate::__test_group!($group $(; $tail)*);
421        }
422    };
423
424    ($iters:expr; $mod_name:ident; $group:ty $(; $tail:tt)* ) => {
425        mod $mod_name {
426            use super::*;
427            use ark_ff::*;
428            use ark_ec::{PrimeGroup, CurveGroup, ScalarMul, AffineRepr, CurveConfig, short_weierstrass::SWCurveConfig, twisted_edwards::TECurveConfig, scalar_mul::{*, wnaf::*}};
429            use ark_serialize::*;
430            use ark_std::{io::Cursor, rand::Rng, vec::*, test_rng, vec, Zero, One, UniformRand};
431            const ITERATIONS: usize = $iters;
432
433            $crate::__test_group!($group $(; $tail)*);
434        }
435    };
436}