generic_ec/
arithmetic.rs

1use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
2
3use crate::{Curve, Generator, NonZero, Point, Scalar, SecretScalar};
4
5mod laws {
6    use crate::{
7        as_raw::AsRaw,
8        core::{self, *},
9        Generator, NonZero,
10    };
11    use crate::{Point, Scalar};
12
13    pub trait AlwaysNonZero {}
14    impl<T> AlwaysNonZero for NonZero<T> {}
15
16    /// If $A$ and $B$ are valid `Point<E>`, then $A + B$ is a valid `Point<E>`
17    ///
18    /// For `Point<E>` to be valid it needs to meet two conditions:
19    /// 1. It has to be on curve
20    /// 2. It has to be free of torsion component
21    ///
22    /// Sum of two points on curve is always a point on curve by definition, so (1) holds.
23    ///
24    /// Recall that, generally, any point on elliptic curve can be represented as sum of its
25    /// components:
26    ///
27    /// $$P = p_0 \G + p_1 \T_1 + \dots + p_t \T_t$$
28    ///
29    /// where $\G$ is a group of large prime order, and $\T_{1,\dots,t}$ are torsion small groups.
30    /// Then sum of two points can be represented as:
31    ///
32    /// $$A + B = (a_0 + b_0) \G + (a_1 + b_1) \T_1 + \dots + (a_t + b_t) \T_t$$
33    ///
34    /// $A$ and $B$ are valid `Point<E>`, so they are torsion free, which means that
35    /// $a_{1,\dots,t} = b_{1,\dots,t} = 0$, so their sum is also torsion free:
36    ///
37    /// $$A + B = (a_0 + b_0) \G$$
38    ///
39    /// Therefore, (2) holds.
40    #[inline]
41    pub fn sum_of_points_is_valid_point<E: Curve>(a: &Point<E>, b: &Point<E>) -> Point<E> {
42        let sum = Additive::add(a.as_raw(), b.as_raw());
43        // Correctness: refer to doc comment of the function
44        Point::from_raw_unchecked(sum)
45    }
46
47    /// If $A$ and $B$ are valid `Point<E>`, then $A - B$ are valid `Point<E>`
48    ///
49    /// Please, refer to [`sum_of_points_is_valid_point`], as the proof is pretty much the same.
50    #[inline]
51    pub fn sub_of_points_is_valid_point<E: Curve>(a: &Point<E>, b: &Point<E>) -> Point<E> {
52        let result = Additive::sub(a.as_raw(), b.as_raw());
53        // Correctness: refer to doc comment of the function
54        Point::from_raw_unchecked(result)
55    }
56
57    /// If $A$ is a valid `Point<E>`, then $A + A$ is a valid `Point<E>`
58    ///
59    /// The proof is the same as for [`sum_of_points_is_valid_point`], just put `B=A`
60    #[inline]
61    pub fn double_point_is_valid_point<E: Curve>(x: &Point<E>) -> Point<E> {
62        let result = Additive::double(x.as_raw());
63        // Correctness: refer to doc comment of the function
64        Point::from_raw_unchecked(result)
65    }
66
67    /// If $A$ is valid `Point<E>`, then $A + G$ is valid `Point<E>`
68    #[inline]
69    pub fn sum_of_point_and_generator_is_valid_point<E: Curve>(
70        a: &Point<E>,
71        g: &Generator<E>,
72    ) -> Point<E> {
73        sum_of_points_is_valid_point(a, &g.to_point())
74    }
75    /// If $A$ is valid `Point<E>`, then $G + A$ is valid `Point<E>`
76    #[inline]
77    pub fn sum_of_generator_and_point_is_valid_point<E: Curve>(
78        g: &Generator<E>,
79        a: &Point<E>,
80    ) -> Point<E> {
81        sum_of_points_is_valid_point(&g.to_point(), a)
82    }
83
84    /// If $A$ is valid `Point<E>`, then $A - G$ is valid `Point<E>`
85    pub fn sub_of_point_and_generator_is_valid_point<E: Curve>(
86        a: &Point<E>,
87        g: &Generator<E>,
88    ) -> Point<E> {
89        sub_of_points_is_valid_point(a, &g.to_point())
90    }
91    /// If $A$ is valid `Point<E>`, then $G - A$ is valid `Point<E>`
92    pub fn sub_of_generator_and_point_is_valid_point<E: Curve>(
93        g: &Generator<E>,
94        a: &Point<E>,
95    ) -> Point<E> {
96        sub_of_points_is_valid_point(&g.to_point(), a)
97    }
98
99    /// If $A$ is a valid `Point<E>`, then $-A$ is a valid `Point<E>`
100    ///
101    /// [`sub_of_points_is_valid_point`] proves that subtraction of two valid `Point<E>` is a
102    /// valid `Point<E>`, so $O - A$ is also a valid `Point<E>`
103    #[inline]
104    pub fn neg_point_is_valid_point<E: Curve>(a: &Point<E>) -> Point<E> {
105        let neg = Additive::negate(a.as_raw());
106        // Correctness: refer to doc comment of the function
107        Point::from_raw_unchecked(neg)
108    }
109
110    /// If $n$ is valid `Scalar<E>` and $A$ is valid `Point<E>`, then $n A$ is a valid `Point<E>`
111    ///
112    /// For `Point<E>` to be valid it needs to meet two conditions:
113    /// 1. It has to be on curve
114    /// 2. It has to be free of torsion component
115    ///
116    /// Point on curve multiplied at any integer is always a point on curve by definition, so
117    /// (1) holds.
118    ///
119    /// Recall that, generally, any point on elliptic curve can be represented as sum of its
120    /// components:
121    ///
122    /// $$P = p_0 \G + p_1 \T_1 + \dots + p_t \T_t$$
123    ///
124    /// where $\G$ is a group of large prime order, and $\T_{1,\dots,t}$ are torsion small groups.
125    /// Then multiplication of point at scalar can be represented as:
126    ///
127    /// $$nA = n a_0 \G + n a_1 \T_1 + \dots + n a_t \T_t$$
128    ///
129    /// $A$ is valid `Point<E>`, so it is torsion free, which means that $a_{1,\dots,t} = 0$, so
130    /// resulting point is also torsion free:
131    ///
132    /// $$nA = n a_0 \G$$
133    ///
134    /// Therefore, (2) holds.
135    #[inline]
136    pub fn mul_of_scalar_at_point_is_valid_point<E: Curve>(
137        n: impl AsRef<Scalar<E>>,
138        a: &Point<E>,
139    ) -> Point<E> {
140        let prod = Multiplicative::mul(n.as_ref().as_raw(), a.as_raw());
141        // Correctness: refer to doc comment of the function
142        Point::from_raw_unchecked(prod)
143    }
144
145    /// Same as [`mul_of_scalar_at_point_is_valid_point`] but flipped arguments
146    #[inline]
147    pub fn mul_of_point_at_scalar_is_valid_point<E: Curve>(
148        a: &Point<E>,
149        b: impl AsRef<Scalar<E>>,
150    ) -> Point<E> {
151        mul_of_scalar_at_point_is_valid_point(b, a)
152    }
153
154    /// If $n$ is valid `Scalar<E>`, then $n \G$ is valid `Point<E>`
155    ///
156    /// Proof is the same as in [`mul_of_scalar_at_point_is_valid_point`] with $A = \G$
157    #[inline]
158    pub fn mul_of_scalar_at_generator_is_valid_point<E: Curve>(
159        n: impl AsRef<Scalar<E>>,
160        _g: &Generator<E>,
161    ) -> Point<E> {
162        let prod = Multiplicative::mul(n.as_ref().as_raw(), &core::CurveGenerator);
163        // Correctness: refer to doc comment of the function
164        Point::from_raw_unchecked(prod)
165    }
166
167    /// Same as [`mul_of_scalar_at_generator_is_valid_point`] but flipped arguments
168    #[inline]
169    pub fn mul_of_generator_at_scalar_is_valid_point<E: Curve>(
170        g: &Generator<E>,
171        n: impl AsRef<Scalar<E>>,
172    ) -> Point<E> {
173        mul_of_scalar_at_generator_is_valid_point(n, g)
174    }
175
176    /// If $n$ is valid `NonZero<Scalar<E>>` and $A$ is valid `NonZero<Point<E>>`, then $n A$ is a valid `NonZero<Point<E>>`
177    ///
178    /// As shown in [`mul_of_scalar_at_point_is_valid_point`], $n A$ is a valid `Point<E>`.
179    ///
180    /// Since $A$ is free of torsion component and non zero, it has order equal to curve `group_order`,
181    /// which means (be definition):
182    ///
183    /// $$\forall n' < \mathit{group\\_order}: n' A \ne O$$
184    ///
185    /// As $n$ is valid `Scalar<E>`, it's less than curve `group_order`, therefore $n A \ne O$.
186    #[inline]
187    pub fn mul_of_nonzero_scalar_at_nonzero_point_is_valid_nonzero_point<E: Curve>(
188        n: &(impl AsRef<Scalar<E>> + AlwaysNonZero),
189        a: &NonZero<Point<E>>,
190    ) -> NonZero<Point<E>> {
191        let prod = mul_of_scalar_at_point_is_valid_point(n, a);
192        // Correctness: refer to doc comment of the function
193        NonZero::new_unchecked(prod)
194    }
195
196    /// Same as [`mul_of_nonzero_scalar_at_nonzero_point_is_valid_nonzero_point`] but flipped arguments
197    #[inline]
198    pub fn mul_of_nonzero_point_at_nonzero_scalar_is_valid_nonzero_point<E: Curve>(
199        a: &NonZero<Point<E>>,
200        n: &(impl AsRef<Scalar<E>> + AlwaysNonZero),
201    ) -> NonZero<Point<E>> {
202        mul_of_nonzero_scalar_at_nonzero_point_is_valid_nonzero_point(n, a)
203    }
204
205    /// If $n$ is valid `NonZero<Scalar<E>>`, then $n \G$ is valid `NonZero<Point<E>>`
206    ///
207    /// Proof is the same as in [`mul_of_nonzero_scalar_at_nonzero_point_is_valid_nonzero_point`]
208    #[inline]
209    pub fn mul_of_nonzero_scalar_at_generator_is_valid_nonzero_point<E: Curve>(
210        n: &(impl AsRef<Scalar<E>> + AlwaysNonZero),
211        g: &Generator<E>,
212    ) -> NonZero<Point<E>> {
213        let prod = mul_of_scalar_at_generator_is_valid_point(n, g);
214        // Correctness: refer to doc comment of the function
215        NonZero::new_unchecked(prod)
216    }
217
218    /// Same as [`mul_of_nonzero_scalar_at_generator_is_valid_nonzero_point`] but flipped arguments
219    #[inline]
220    pub fn mul_of_generator_at_nonzero_scalar_is_valid_nonzero_point<E: Curve>(
221        g: &Generator<E>,
222        n: &(impl AsRef<Scalar<E>> + AlwaysNonZero),
223    ) -> NonZero<Point<E>> {
224        mul_of_nonzero_scalar_at_generator_is_valid_nonzero_point(n, g)
225    }
226
227    /// If $A$ is valid `NonZero<Point<E>>`, then $-A$ is valid `NonZero<Point<E>>`
228    ///
229    /// As shown in [`neg_point_is_valid_point`], $-A$ is a valid `Point<E>`.
230    ///
231    /// Since $A$ is not zero, $-A$ is not zero as well.
232    #[inline]
233    pub fn neg_nonzero_point_is_nonzero_point<E: Curve>(
234        a: &NonZero<Point<E>>,
235    ) -> NonZero<Point<E>> {
236        let neg = neg_point_is_valid_point(a);
237        // Correctness: refer to doc comment of the function
238        NonZero::new_unchecked(neg)
239    }
240
241    /// If $A$ and $B$ are non-zero scalars mod prime integer $q$, then $A \cdot B \ne 0 \pmod{q}$
242    ///
243    /// Product of two non-zero integers mod $q$ can be zero if, and only if, $A \cdot B$ divides $q$.
244    /// It's not possible as $q$ is prime and $A,B < q$.
245    pub fn non_zero_scalar_at_non_zero_scalar_is_non_zero_scalar<E: Curve>(
246        a: &(impl AsRef<Scalar<E>> + AlwaysNonZero),
247        b: &(impl AsRef<Scalar<E>> + AlwaysNonZero),
248    ) -> NonZero<Scalar<E>> {
249        let prod = super::scalar::mul(a, b);
250        // Correctness: refer to doc commnet of the function
251        NonZero::new_unchecked(prod)
252    }
253}
254
255mod scalar {
256    use crate::as_raw::{AsRaw, FromRaw};
257    use crate::{core::*, SecretScalar};
258    use crate::{NonZero, Scalar};
259
260    #[inline]
261    pub fn add<E: Curve>(a: impl AsRef<Scalar<E>>, b: impl AsRef<Scalar<E>>) -> Scalar<E> {
262        let sum = Additive::add(a.as_ref().as_raw(), b.as_ref().as_raw());
263        Scalar::from_raw(sum)
264    }
265
266    #[inline]
267    pub fn sub<E: Curve>(a: impl AsRef<Scalar<E>>, b: impl AsRef<Scalar<E>>) -> Scalar<E> {
268        let result = Additive::sub(a.as_ref().as_raw(), b.as_ref().as_raw());
269        Scalar::from_raw(result)
270    }
271
272    #[inline]
273    pub fn mul<E: Curve>(a: impl AsRef<Scalar<E>>, b: impl AsRef<Scalar<E>>) -> Scalar<E> {
274        let prod = Multiplicative::mul(a.as_ref().as_raw(), b.as_ref().as_raw());
275        Scalar::from_raw(prod)
276    }
277
278    #[inline]
279    pub fn neg<E: Curve>(a: &Scalar<E>) -> Scalar<E> {
280        let result = Additive::negate(a.as_raw());
281        Scalar::from_raw(result)
282    }
283
284    #[inline]
285    pub fn neg_nonzero<E: Curve>(a: &NonZero<Scalar<E>>) -> NonZero<Scalar<E>> {
286        let neg = neg(a);
287        // Correctness: since `a` is not zero, `-a` is not zero by definition
288        NonZero::new_unchecked(neg)
289    }
290
291    #[inline]
292    pub fn neg_nonzero_secret<E: Curve>(a: &NonZero<SecretScalar<E>>) -> NonZero<SecretScalar<E>> {
293        let mut a: Scalar<E> = *a.as_ref();
294        a *= -Scalar::one();
295        // Correctness: since `a` is not zero, `-a` is not zero by definition
296        NonZero::new_unchecked(SecretScalar::new(&mut a))
297    }
298}
299
300macro_rules! impl_binary_ops {
301    ($($op:ident ($lhs:ty, $op_fn:ident, $rhs:ty = $out:ty) $impl_fn:path),+,) => {$(
302        impl<E: Curve> $op<$rhs> for $lhs {
303            type Output = $out;
304            #[inline]
305            fn $op_fn(self, rhs: $rhs) -> Self::Output {
306                $impl_fn(&self, &rhs)
307            }
308        }
309        impl<E: Curve> $op<&$rhs> for $lhs {
310            type Output = $out;
311            #[inline]
312            fn $op_fn(self, rhs: &$rhs) -> Self::Output {
313                $impl_fn(&self, rhs)
314            }
315        }
316        impl<E: Curve> $op<$rhs> for &$lhs {
317            type Output = $out;
318            #[inline]
319            fn $op_fn(self, rhs: $rhs) -> Self::Output {
320                $impl_fn(self, &rhs)
321            }
322        }
323        impl<E: Curve> $op<&$rhs> for &$lhs {
324            type Output = $out;
325            #[inline]
326            fn $op_fn(self, rhs: &$rhs) -> Self::Output {
327                $impl_fn(self, rhs)
328            }
329        }
330    )+};
331}
332
333macro_rules! impl_nonzero_ops {
334    ($($op:ident ($lhs:ty, $op_fn:ident, $rhs:ty = $out:ty) $impl_fn:path),+,) => {
335        impl_binary_ops! {$(
336            $op (NonZero<$lhs>, $op_fn, NonZero<$rhs> = $out) $impl_fn,
337            $op ($lhs, $op_fn, NonZero<$rhs> = $out) $impl_fn,
338            $op (NonZero<$lhs>, $op_fn, $rhs = $out) $impl_fn,
339        )+}
340    };
341}
342
343macro_rules! impl_unary_ops {
344    ($($op:ident ($op_fn:ident $ty:ty) $impl_fn:path),*,) => {$(
345        impl<E: Curve> $op for $ty {
346            type Output = $ty;
347            #[inline]
348            fn $op_fn(self) -> Self::Output {
349                $impl_fn(&self)
350            }
351        }
352        impl<E: Curve> $op for &$ty {
353            type Output = $ty;
354            #[inline]
355            fn $op_fn(self) -> Self::Output {
356                $impl_fn(self)
357            }
358        }
359    )*};
360}
361
362macro_rules! impl_op_assign {
363    ($($ty:ty, $trait:ident, $rhs:ty, $fn:ident, $op:tt),+,) => {$(
364        impl<E: Curve> $trait<$rhs> for $ty {
365            fn $fn(&mut self, rhs: $rhs) {
366                *self = *self $op rhs;
367            }
368        }
369        impl<E: Curve> $trait<&$rhs> for $ty {
370            fn $fn(&mut self, rhs: &$rhs) {
371                *self = *self $op rhs;
372            }
373        }
374    )+};
375}
376
377// Point <> Point, Point <> Scalar, Scalar <> Scalar arithmetic ops
378impl_binary_ops! {
379    Add (Point<E>, add, Point<E> = Point<E>) laws::sum_of_points_is_valid_point,
380    Sub (Point<E>, sub, Point<E> = Point<E>) laws::sub_of_points_is_valid_point,
381
382    Add (Point<E>, add, Generator<E> = Point<E>) laws::sum_of_point_and_generator_is_valid_point,
383    Add (Generator<E>, add, Point<E> = Point<E>) laws::sum_of_generator_and_point_is_valid_point,
384    Sub (Point<E>, sub, Generator<E> = Point<E>) laws::sub_of_point_and_generator_is_valid_point,
385    Sub (Generator<E>, sub, Point<E> = Point<E>) laws::sub_of_generator_and_point_is_valid_point,
386
387    Add (Scalar<E>, add, Scalar<E> = Scalar<E>) scalar::add,
388    Sub (Scalar<E>, sub, Scalar<E> = Scalar<E>) scalar::sub,
389    Mul (Scalar<E>, mul, Scalar<E> = Scalar<E>) scalar::mul,
390
391    Mul (Point<E>, mul, Scalar<E> = Point<E>) laws::mul_of_point_at_scalar_is_valid_point,
392    Mul (Scalar<E>, mul, Point<E> = Point<E>) laws::mul_of_scalar_at_point_is_valid_point,
393    Mul (Generator<E>, mul, Scalar<E> = Point<E>) laws::mul_of_generator_at_scalar_is_valid_point,
394    Mul (Scalar<E>, mul, Generator<E> = Point<E>) laws::mul_of_scalar_at_generator_is_valid_point,
395}
396
397// SecretScalar and NonZero<SecretScalar> multiplication, addition, substruction with Scalar,
398// NonZero<Scalar>, Point, and NonZero<Point>
399impl_binary_ops! {
400    Add (SecretScalar<E>, add, Scalar<E> = Scalar<E>) scalar::add,
401    Add (Scalar<E>, add, SecretScalar<E> = Scalar<E>) scalar::add,
402    Add (SecretScalar<E>, add, NonZero<Scalar<E>> = Scalar<E>) scalar::add,
403    Add (NonZero<Scalar<E>>, add, SecretScalar<E> = Scalar<E>) scalar::add,
404
405    Add (NonZero<SecretScalar<E>>, add, Scalar<E> = Scalar<E>) scalar::add,
406    Add (Scalar<E>, add, NonZero<SecretScalar<E>> = Scalar<E>) scalar::add,
407    Add (NonZero<SecretScalar<E>>, add, NonZero<Scalar<E>> = Scalar<E>) scalar::add,
408    Add (NonZero<Scalar<E>>, add, NonZero<SecretScalar<E>> = Scalar<E>) scalar::add,
409
410    Sub (SecretScalar<E>, sub, Scalar<E> = Scalar<E>) scalar::sub,
411    Sub (Scalar<E>, sub, SecretScalar<E> = Scalar<E>) scalar::sub,
412    Sub (SecretScalar<E>, sub, NonZero<Scalar<E>> = Scalar<E>) scalar::sub,
413    Sub (NonZero<Scalar<E>>, sub, SecretScalar<E> = Scalar<E>) scalar::sub,
414
415    Sub (NonZero<SecretScalar<E>>, sub, Scalar<E> = Scalar<E>) scalar::sub,
416    Sub (Scalar<E>, sub, NonZero<SecretScalar<E>> = Scalar<E>) scalar::sub,
417    Sub (NonZero<SecretScalar<E>>, sub, NonZero<Scalar<E>> = Scalar<E>) scalar::sub,
418    Sub (NonZero<Scalar<E>>, sub, NonZero<SecretScalar<E>> = Scalar<E>) scalar::sub,
419
420    Mul (SecretScalar<E>, mul, Scalar<E> = Scalar<E>) scalar::mul,
421    Mul (Scalar<E>, mul, SecretScalar<E> = Scalar<E>) scalar::mul,
422    Mul (SecretScalar<E>, mul, NonZero<Scalar<E>> = Scalar<E>) scalar::mul,
423    Mul (NonZero<Scalar<E>>, mul, SecretScalar<E> = Scalar<E>) scalar::mul,
424
425    Mul (NonZero<SecretScalar<E>>, mul, Scalar<E> = Scalar<E>) scalar::mul,
426    Mul (Scalar<E>, mul, NonZero<SecretScalar<E>> = Scalar<E>) scalar::mul,
427
428    Mul (Point<E>, mul, SecretScalar<E> = Point<E>) laws::mul_of_point_at_scalar_is_valid_point,
429    Mul (SecretScalar<E>, mul, Point<E> = Point<E>) laws::mul_of_scalar_at_point_is_valid_point,
430    Mul (Generator<E>, mul, SecretScalar<E> = Point<E>) laws::mul_of_generator_at_scalar_is_valid_point,
431    Mul (SecretScalar<E>, mul, Generator<E> = Point<E>) laws::mul_of_scalar_at_generator_is_valid_point,
432    Mul (NonZero<Point<E>>, mul, SecretScalar<E> = Point<E>) laws::mul_of_point_at_scalar_is_valid_point,
433    Mul (SecretScalar<E>, mul, NonZero<Point<E>> = Point<E>) laws::mul_of_scalar_at_point_is_valid_point,
434
435    Mul (Point<E>, mul, NonZero<SecretScalar<E>> = Point<E>) laws::mul_of_point_at_scalar_is_valid_point,
436    Mul (NonZero<SecretScalar<E>>, mul, Point<E> = Point<E>) laws::mul_of_scalar_at_point_is_valid_point,
437}
438
439// NonZero<Point> <> NonZero<Scalar> arithmetic ops
440impl_binary_ops! {
441    Mul (NonZero<Point<E>>, mul, NonZero<Scalar<E>> = NonZero<Point<E>>) laws::mul_of_nonzero_point_at_nonzero_scalar_is_valid_nonzero_point,
442    Mul (NonZero<Scalar<E>>, mul, NonZero<Point<E>> = NonZero<Point<E>>) laws::mul_of_nonzero_scalar_at_nonzero_point_is_valid_nonzero_point,
443    Mul (Generator<E>, mul, NonZero<Scalar<E>> = NonZero<Point<E>>) laws::mul_of_generator_at_nonzero_scalar_is_valid_nonzero_point,
444    Mul (NonZero<Scalar<E>>, mul, Generator<E> = NonZero<Point<E>>) laws::mul_of_nonzero_scalar_at_generator_is_valid_nonzero_point,
445
446    Mul (NonZero<Point<E>>, mul, NonZero<SecretScalar<E>> = NonZero<Point<E>>) laws::mul_of_nonzero_point_at_nonzero_scalar_is_valid_nonzero_point,
447    Mul (NonZero<SecretScalar<E>>, mul, NonZero<Point<E>> = NonZero<Point<E>>) laws::mul_of_nonzero_scalar_at_nonzero_point_is_valid_nonzero_point,
448    Mul (Generator<E>, mul, NonZero<SecretScalar<E>> = NonZero<Point<E>>) laws::mul_of_generator_at_nonzero_scalar_is_valid_nonzero_point,
449    Mul (NonZero<SecretScalar<E>>, mul, Generator<E> = NonZero<Point<E>>) laws::mul_of_nonzero_scalar_at_generator_is_valid_nonzero_point,
450}
451
452// Point <> NonZero<Point>, Scalar <> NonZero<Scalar>,
453// NonZero<Point> <> NonZero<Point>, NonZero<Scalar> <> NonZero<Scalar> arithmetic ops
454impl_nonzero_ops! {
455    Add (Point<E>, add, Point<E> = Point<E>) laws::sum_of_points_is_valid_point,
456    Sub (Point<E>, sub, Point<E> = Point<E>) laws::sub_of_points_is_valid_point,
457
458    Add (Scalar<E>, add, Scalar<E> = Scalar<E>) scalar::add,
459    Sub (Scalar<E>, sub, Scalar<E> = Scalar<E>) scalar::sub,
460
461    Add (SecretScalar<E>, add, SecretScalar<E> = Scalar<E>) scalar::add,
462    Sub (SecretScalar<E>, sub, SecretScalar<E> = Scalar<E>) scalar::sub,
463}
464
465// NonZero<Scalar> * NonZero<Scalar>, Scalar * NonZero<Scalar>, NonZero<Scalar> * Scalar
466impl_binary_ops! {
467    Mul (NonZero<Scalar<E>>, mul, NonZero<Scalar<E>> = NonZero<Scalar<E>>) laws::non_zero_scalar_at_non_zero_scalar_is_non_zero_scalar,
468    Mul (Scalar<E>, mul, NonZero<Scalar<E>> = Scalar<E>) scalar::mul,
469    Mul (NonZero<Scalar<E>>, mul, Scalar<E> = Scalar<E>) scalar::mul,
470
471    Mul (NonZero<SecretScalar<E>>, mul, NonZero<SecretScalar<E>> = NonZero<Scalar<E>>) laws::non_zero_scalar_at_non_zero_scalar_is_non_zero_scalar,
472    Mul (NonZero<Scalar<E>>, mul, NonZero<SecretScalar<E>> = NonZero<Scalar<E>>) laws::non_zero_scalar_at_non_zero_scalar_is_non_zero_scalar,
473    Mul (NonZero<SecretScalar<E>>, mul, NonZero<Scalar<E>> = NonZero<Scalar<E>>) laws::non_zero_scalar_at_non_zero_scalar_is_non_zero_scalar,
474}
475
476// Point <> NonZero<Scalar>, NonZero<Point> <> Scalar
477impl_binary_ops! {
478    Mul (Point<E>, mul, NonZero<Scalar<E>> = Point<E>) laws::mul_of_point_at_scalar_is_valid_point,
479    Mul (NonZero<Scalar<E>>, mul, Point<E> = Point<E>) laws::mul_of_scalar_at_point_is_valid_point,
480    Mul (NonZero<Point<E>>, mul, Scalar<E> = Point<E>) laws::mul_of_point_at_scalar_is_valid_point,
481    Mul (Scalar<E>, mul, NonZero<Point<E>> = Point<E>) laws::mul_of_scalar_at_point_is_valid_point,
482}
483
484// -Point, -Scalar, -NonZero<Point>, -NonZero<Scalar>
485impl_unary_ops! {
486    Neg (neg Point<E>) laws::neg_point_is_valid_point,
487    Neg (neg Scalar<E>) scalar::neg,
488    Neg (neg NonZero<Point<E>>) laws::neg_nonzero_point_is_nonzero_point,
489    Neg (neg NonZero<Scalar<E>>) scalar::neg_nonzero,
490    Neg (neg NonZero<SecretScalar<E>>) scalar::neg_nonzero_secret,
491}
492
493impl_op_assign! {
494    Point<E>, AddAssign, Point<E>, add_assign, +,
495    Point<E>, AddAssign, NonZero<Point<E>>, add_assign, +,
496    Point<E>, AddAssign, Generator<E>, add_assign, +,
497
498    Point<E>, SubAssign, Point<E>, sub_assign, -,
499    Point<E>, SubAssign, NonZero<Point<E>>, sub_assign, -,
500    Point<E>, SubAssign, Generator<E>, sub_assign, -,
501
502    Point<E>, MulAssign, Scalar<E>, mul_assign, *,
503    Point<E>, MulAssign, NonZero<Scalar<E>>, mul_assign, *,
504    Point<E>, MulAssign, SecretScalar<E>, mul_assign, *,
505    Point<E>, MulAssign, NonZero<SecretScalar<E>>, mul_assign, *,
506
507    Scalar<E>, AddAssign, Scalar<E>, add_assign, +,
508    Scalar<E>, AddAssign, NonZero<Scalar<E>>, add_assign, +,
509    Scalar<E>, AddAssign, SecretScalar<E>, add_assign, +,
510    Scalar<E>, AddAssign, NonZero<SecretScalar<E>>, add_assign, +,
511
512    Scalar<E>, SubAssign, Scalar<E>, sub_assign, -,
513    Scalar<E>, SubAssign, NonZero<Scalar<E>>, sub_assign, -,
514    Scalar<E>, SubAssign, SecretScalar<E>, sub_assign, -,
515    Scalar<E>, SubAssign, NonZero<SecretScalar<E>>, sub_assign, -,
516
517    Scalar<E>, MulAssign, Scalar<E>, mul_assign, *,
518    Scalar<E>, MulAssign, NonZero<Scalar<E>>, mul_assign, *,
519    Scalar<E>, MulAssign, SecretScalar<E>, mul_assign, *,
520    Scalar<E>, MulAssign, NonZero<SecretScalar<E>>, mul_assign, *,
521
522    NonZero<Point<E>>, MulAssign, NonZero<Scalar<E>>, mul_assign, *,
523    NonZero<Point<E>>, MulAssign, NonZero<SecretScalar<E>>, mul_assign, *,
524    NonZero<Scalar<E>>, MulAssign, NonZero<Scalar<E>>, mul_assign, *,
525    NonZero<Scalar<E>>, MulAssign, NonZero<SecretScalar<E>>, mul_assign, *,
526}
527
528impl<E: Curve> Point<E> {
529    /// Doubles the point, returns `self + self`
530    ///
531    /// `point.double()` may be more efficient than `point + point` or `2 * point`
532    pub fn double(&self) -> Self {
533        laws::double_point_is_valid_point(self)
534    }
535}
536
537#[cfg(test)]
538#[allow(dead_code, clippy::redundant_clone)]
539fn ensure_ops_implemented<E: Curve>(
540    g: Generator<E>,
541    point: Point<E>,
542    scalar: Scalar<E>,
543    non_zero_point: NonZero<Point<E>>,
544    non_zero_scalar: NonZero<Scalar<E>>,
545    secret_scalar: SecretScalar<E>,
546    non_zero_secret_scalar: NonZero<SecretScalar<E>>,
547) {
548    macro_rules! assert_binary_ops {
549        ($($a:ident $op:tt $b:ident => $out:ty),+,) => {$(
550            let _: $out = $a.clone() $op $b.clone();
551            let _: $out = &$a $op $b.clone();
552            let _: $out = $a.clone() $op &$b;
553            let _: $out = &$a $op &$b;
554
555            let _: $out = $b.clone() $op $a.clone();
556            let _: $out = &$b $op $a.clone();
557            let _: $out = $b.clone() $op &$a;
558            let _: $out = &$b $op &$a;
559        )+};
560    }
561    macro_rules! assert_unary_ops {
562        ($($op:tt $a:ident => $out:ty),+,) => {$(
563            let _: $out = $op $a.clone();
564            let _: $out = $op &$a;
565        )+};
566    }
567
568    macro_rules! assert_op_assign {
569        ($($a:ident $op:tt $b:ident);+;) => {{$(
570            let mut a = $a.clone();
571            a $op $b.clone();
572            a $op &$b;
573        )+}};
574    }
575
576    assert_binary_ops!(
577        g * scalar => Point<E>,
578        point * scalar => Point<E>,
579        g * non_zero_scalar => NonZero<Point<E>>,
580        non_zero_point * non_zero_scalar => NonZero<Point<E>>,
581
582        g * secret_scalar => Point<E>,
583        point * secret_scalar => Point<E>,
584        non_zero_point * secret_scalar => Point<E>,
585
586        g * non_zero_secret_scalar => NonZero<Point<E>>,
587        point * non_zero_secret_scalar => Point<E>,
588        non_zero_point * non_zero_secret_scalar => NonZero<Point<E>>,
589
590        point + point => Point<E>,
591        point + non_zero_point => Point<E>,
592        non_zero_point + non_zero_point => Point<E>,
593
594        point - point => Point<E>,
595        point - non_zero_point => Point<E>,
596        non_zero_point - non_zero_point => Point<E>,
597
598        scalar + scalar => Scalar<E>,
599        scalar + non_zero_scalar => Scalar<E>,
600        non_zero_scalar + non_zero_scalar => Scalar<E>,
601
602        scalar + secret_scalar => Scalar<E>,
603        non_zero_scalar + secret_scalar => Scalar<E>,
604
605        scalar + non_zero_secret_scalar => Scalar<E>,
606        non_zero_scalar + non_zero_secret_scalar => Scalar<E>,
607
608        scalar - scalar => Scalar<E>,
609        scalar - non_zero_scalar => Scalar<E>,
610        non_zero_scalar - non_zero_scalar => Scalar<E>,
611
612        scalar - secret_scalar => Scalar<E>,
613        non_zero_scalar - secret_scalar => Scalar<E>,
614
615        scalar - non_zero_secret_scalar => Scalar<E>,
616        non_zero_scalar - non_zero_secret_scalar => Scalar<E>,
617
618        scalar * scalar => Scalar<E>,
619        scalar * non_zero_scalar => Scalar<E>,
620        non_zero_scalar * non_zero_scalar => NonZero<Scalar<E>>,
621
622        scalar * secret_scalar => Scalar<E>,
623        non_zero_scalar * secret_scalar => Scalar<E>,
624
625        scalar * non_zero_secret_scalar => Scalar<E>,
626        non_zero_scalar * non_zero_secret_scalar => NonZero<Scalar<E>>,
627
628        non_zero_secret_scalar + non_zero_secret_scalar => Scalar<E>,
629        non_zero_secret_scalar - non_zero_secret_scalar => Scalar<E>,
630        non_zero_secret_scalar * non_zero_secret_scalar => NonZero<Scalar<E>>,
631    );
632
633    assert_unary_ops!(
634        -point => Point<E>,
635        -non_zero_point => NonZero<Point<E>>,
636        -scalar => Scalar<E>,
637        -non_zero_scalar => NonZero<Scalar<E>>,
638        -non_zero_secret_scalar => NonZero<SecretScalar<E>>,
639    );
640
641    assert_op_assign!(
642        point += point;
643        point += non_zero_point;
644        point += g;
645
646        point -= point;
647        point -= non_zero_point;
648        point -= g;
649
650        point *= scalar;
651        point *= non_zero_scalar;
652        point *= secret_scalar;
653        point *= non_zero_scalar;
654
655        non_zero_point *= non_zero_scalar;
656
657        scalar += scalar;
658        scalar -= scalar;
659        scalar *= scalar;
660
661        scalar += non_zero_scalar;
662        scalar -= non_zero_scalar;
663        scalar *= non_zero_scalar;
664
665        scalar += secret_scalar;
666        scalar -= secret_scalar;
667        scalar *= secret_scalar;
668
669        scalar += non_zero_secret_scalar;
670        scalar -= non_zero_secret_scalar;
671        scalar *= non_zero_secret_scalar;
672
673        non_zero_scalar *= non_zero_scalar;
674    );
675}