Skip to main content

generic_ec/
arithmetic.rs

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