1use rand_core::RngCore;
2use group::{
3 ff::{Field, PrimeFieldBits},
4 Group,
5 prime::PrimeGroup,
6};
7
8use crate::prime_field::{test_prime_field, test_prime_field_bits};
9
10pub fn test_eq<G: Group>() {
12 assert_eq!(G::identity(), G::identity(), "identity != identity");
13 assert_eq!(G::generator(), G::generator(), "generator != generator");
14 assert!(G::identity() != G::generator(), "identity == generator");
15}
16
17pub fn test_identity<G: Group>() {
19 assert!(bool::from(G::identity().is_identity()), "identity wasn't identity");
20 assert!(
21 bool::from((G::identity() + G::identity()).is_identity()),
22 "identity + identity wasn't identity"
23 );
24 assert!(
25 bool::from((G::generator() - G::generator()).is_identity()),
26 "generator - generator wasn't identity"
27 );
28 assert!(!bool::from(G::generator().is_identity()), "is_identity claimed generator was identity");
29}
30
31pub fn test_generator<G: Group>() {
33 assert!(G::generator() != G::identity(), "generator was identity");
34 assert!(
35 (G::generator() + G::generator()) != G::generator(),
36 "generator added to itself was identity"
37 );
38}
39
40pub fn test_double<G: Group>() {
42 assert!(bool::from(G::identity().double().is_identity()), "identity.double() wasn't identity");
43 assert_eq!(
44 G::generator() + G::generator(),
45 G::generator().double(),
46 "generator + generator != generator.double()"
47 );
48}
49
50pub fn test_add<G: Group>() {
52 assert_eq!(G::identity() + G::identity(), G::identity(), "identity + identity != identity");
53 assert_eq!(G::identity() + G::generator(), G::generator(), "identity + generator != generator");
54 assert_eq!(G::generator() + G::identity(), G::generator(), "generator + identity != generator");
55
56 let two = G::generator().double();
57 assert_eq!(G::generator() + G::generator(), two, "generator + generator != two");
58 let four = two.double();
59 assert_eq!(
60 G::generator() + G::generator() + G::generator() + G::generator(),
61 four,
62 "generator + generator + generator + generator != four"
63 );
64}
65
66pub fn test_sum<G: Group>() {
68 assert_eq!(
69 [G::generator(), G::generator()].iter().sum::<G>(),
70 G::generator().double(),
71 "[generator, generator].sum() != two"
72 );
73 assert_eq!(
74 [G::generator().double(), G::generator()].iter().sum::<G>(),
75 G::generator().double() + G::generator(),
76 "[generator.double(), generator].sum() != three"
77 );
78}
79
80pub fn test_neg<G: Group>() {
82 assert_eq!(G::identity(), G::identity().neg(), "identity != -identity");
83 assert_eq!(
84 G::generator() + G::generator().neg(),
85 G::identity(),
86 "generator + -generator != identity"
87 );
88}
89
90pub fn test_sub<G: Group>() {
92 assert_eq!(G::generator() - G::generator(), G::identity(), "generator - generator != identity");
93 let two = G::generator() + G::generator();
94 assert_eq!(two - G::generator(), G::generator(), "two - one != one");
95}
96
97pub fn test_mul<G: Group>() {
99 assert_eq!(G::generator() * G::Scalar::from(0), G::identity(), "generator * 0 != identity");
100 assert_eq!(G::generator() * G::Scalar::from(1), G::generator(), "generator * 1 != generator");
101 assert_eq!(
102 G::generator() * G::Scalar::from(2),
103 G::generator() + G::generator(),
104 "generator * 2 != generator + generator"
105 );
106 assert_eq!(G::identity() * G::Scalar::from(2), G::identity(), "identity * 2 != identity");
107}
108
109pub fn test_order<G: Group>() {
111 let minus_one = G::generator() * (G::Scalar::ZERO - G::Scalar::ONE);
112 assert!(minus_one != G::identity(), "(modulus - 1) * G was identity");
113 assert_eq!(minus_one + G::generator(), G::identity(), "((modulus - 1) * G) + G wasn't identity");
114}
115
116pub fn test_random<R: RngCore, G: Group>(rng: &mut R) {
118 let a = G::random(&mut *rng);
119 assert!(!bool::from(a.is_identity()), "random returned identity");
120
121 let mut pass = false;
126 for _ in 0 .. 128 {
127 let b = G::random(&mut *rng);
128 assert!(!bool::from(b.is_identity()), "random returned identity");
129
130 if b != a {
132 pass = true;
133 }
134 }
135 assert!(pass, "random always returned the same value");
136}
137
138pub fn test_group<R: RngCore, G: Group>(rng: &mut R) {
140 test_prime_field::<R, G::Scalar>(rng);
141
142 test_eq::<G>();
143 test_identity::<G>();
144 test_generator::<G>();
145 test_double::<G>();
146 test_add::<G>();
147 test_sum::<G>();
148 test_neg::<G>();
149 test_sub::<G>();
150 test_mul::<G>();
151 test_order::<G>();
152 test_random::<R, G>(rng);
153}
154
155pub fn test_encoding<G: PrimeGroup>() {
157 let test = |point: G, msg| -> G {
158 let bytes = point.to_bytes();
159 let mut repr = G::Repr::default();
160 repr.as_mut().copy_from_slice(bytes.as_ref());
161 let decoded = G::from_bytes(&repr).unwrap();
162 assert_eq!(point, decoded, "{msg} couldn't be encoded and decoded");
163 assert_eq!(
164 point,
165 G::from_bytes_unchecked(&repr).unwrap(),
166 "{msg} couldn't be encoded and decoded",
167 );
168 decoded
169 };
170 assert!(bool::from(test(G::identity(), "identity").is_identity()));
171 test(G::generator(), "generator");
172 test(G::generator() + G::generator(), "(generator * 2)");
173}
174
175pub fn test_prime_group<R: RngCore, G: PrimeGroup>(rng: &mut R) {
177 test_group::<R, G>(rng);
178
179 test_encoding::<G>();
180}
181
182pub fn test_prime_group_bits<R: RngCore, G: PrimeGroup<Scalar: PrimeFieldBits>>(rng: &mut R) {
184 test_prime_field_bits::<R, G::Scalar>(rng);
185 test_prime_group::<R, G>(rng);
186}
187
188#[test]
197fn test_k256() {
198 test_prime_group_bits::<_, k256::ProjectivePoint>(&mut rand_core::OsRng);
199}
200
201#[test]
202fn test_p256() {
203 test_prime_group_bits::<_, p256::ProjectivePoint>(&mut rand_core::OsRng);
204}
205
206#[test]
207fn test_bls12_381() {
208 test_prime_group_bits::<_, bls12_381::G1Projective>(&mut rand_core::OsRng);
209 test_prime_group_bits::<_, bls12_381::G2Projective>(&mut rand_core::OsRng);
210}
211
212#[test]
213fn test_pallas_vesta() {
214 test_prime_group_bits::<_, pasta_curves::pallas::Point>(&mut rand_core::OsRng);
215 test_prime_group_bits::<_, pasta_curves::vesta::Point>(&mut rand_core::OsRng);
216}