primitives/algebra/elliptic_curve/
point.rs1use std::{
2 hash::Hash,
3 iter::Sum,
4 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
5 sync::Arc,
6};
7
8use elliptic_curve::group::{Group, GroupEncoding};
9use rand::{distributions::Standard, prelude::Distribution, RngCore};
10use serde::{Deserialize, Serialize};
11use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
12
13use crate::{
14 algebra::elliptic_curve::{
15 curve::{FromExtendedEdwards, PointAtInfinityError, ToExtendedEdwards},
16 BaseFieldElement,
17 Curve,
18 Scalar,
19 ScalarAsExtension,
20 },
21 errors::SerializationError,
22 impl_borrow_variants,
23 impl_commutative,
24 sharing::unauthenticated::AdditiveShares,
25};
26
27#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Hash)]
29pub struct Point<C: Curve>(pub(crate) C::Point);
30impl<C: Curve> Unpin for Point<C> {}
31
32impl<C: Curve> Serialize for Point<C> {
33 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
34 let bytes = self.0.to_bytes();
35 serde_bytes::serialize(bytes.as_ref(), serializer)
36 }
37}
38
39impl<'de, C: Curve> Deserialize<'de> for Point<C> {
40 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
41 let bytes: &[u8] = serde_bytes::deserialize(deserializer)?;
42 let endian_bytes = if C::POINT_BIG_ENDIAN {
43 Point::from_be_bytes(bytes)
44 } else {
45 Point::from_le_bytes(bytes)
46 };
47 let point = endian_bytes.map_err(|err| {
48 serde::de::Error::custom(format!("Failed to deserialize curve point: {err:?}"))
49 })?;
50 Ok(point)
51 }
52}
53
54impl<C: Curve> Point<C> {
59 pub fn identity() -> Point<C> {
61 Point(C::Point::identity())
62 }
63
64 pub fn new(point: C::Point) -> Point<C> {
65 Point(point)
66 }
67
68 pub fn is_identity(&self) -> Choice {
70 self.ct_eq(&Point::identity())
71 }
72
73 pub fn inner(&self) -> C::Point {
75 self.0
76 }
77
78 pub fn generator() -> Point<C> {
80 Point(<C::Point as Group>::generator())
81 }
82
83 pub fn from_be_bytes(bytes: &[u8]) -> Result<Point<C>, SerializationError> {
86 let mut encoding = <C::Point as GroupEncoding>::Repr::default();
87
88 if C::POINT_BIG_ENDIAN {
89 encoding.as_mut().copy_from_slice(bytes);
90 } else {
91 encoding.as_mut().copy_from_slice(bytes);
92 encoding.as_mut().reverse();
93 }
94
95 let point = Option::from(C::Point::from_bytes(&encoding))
96 .ok_or(SerializationError::DeserializationFailed)?;
97 Ok(Point(point))
98 }
99
100 pub fn from_le_bytes(bytes: &[u8]) -> Result<Point<C>, SerializationError> {
103 let mut encoding = <C::Point as GroupEncoding>::Repr::default();
104
105 if C::POINT_BIG_ENDIAN {
106 encoding.as_mut().copy_from_slice(bytes);
107 encoding.as_mut().reverse();
108 } else {
109 encoding.as_mut().copy_from_slice(bytes);
110 }
111
112 let point = Option::from(C::Point::from_bytes(&encoding))
113 .ok_or(SerializationError::DeserializationFailed)?;
114 Ok(Point(point))
115 }
116
117 pub fn to_bytes(&self) -> Arc<[u8]> {
119 self.0.to_bytes().as_ref().into()
120 }
121
122 pub fn from_extended_edwards(coordinates: [BaseFieldElement<C>; 4]) -> Option<Point<C>> {
123 C::Point::from_extended_edwards(coordinates).map(Point)
124 }
125
126 pub fn to_extended_edwards(self) -> Result<[BaseFieldElement<C>; 4], PointAtInfinityError> {
127 self.0.to_extended_edwards()
128 }
129}
130
131impl<C: Curve> Distribution<Point<C>> for Standard {
132 #[inline]
133 fn sample<R: RngCore + ?Sized>(&self, rng: &mut R) -> Point<C> {
134 Point(C::Point::random(rng))
135 }
136}
137
138impl<C: Curve> Add<&Point<C>> for &Point<C> {
145 type Output = Point<C>;
146
147 #[inline]
148 fn add(self, rhs: &Point<C>) -> Self::Output {
149 Point(self.0 + rhs.0)
150 }
151}
152impl_borrow_variants!(Point<C>, Add, add, +, Point<C>, C: Curve);
153
154impl<C: Curve> AddAssign for Point<C> {
157 #[inline]
158 fn add_assign(&mut self, rhs: Self) {
159 self.0 += rhs.0;
160 }
161}
162
163impl<'a, C: Curve> AddAssign<&'a Point<C>> for Point<C> {
164 #[inline]
165 fn add_assign(&mut self, rhs: &'a Point<C>) {
166 self.0 += rhs.0;
167 }
168}
169
170impl<C: Curve> Sub<&Point<C>> for &Point<C> {
173 type Output = Point<C>;
174
175 #[inline]
176 fn sub(self, rhs: &Point<C>) -> Self::Output {
177 Point(self.0 - rhs.0)
178 }
179}
180impl_borrow_variants!(Point<C>, Sub, sub, -, Point<C>, C: Curve);
181
182impl<C: Curve> SubAssign for Point<C> {
185 #[inline]
186 fn sub_assign(&mut self, rhs: Self) {
187 self.0 -= rhs.0;
188 }
189}
190
191impl<'a, C: Curve> SubAssign<&'a Point<C>> for Point<C> {
192 #[inline]
193 fn sub_assign(&mut self, rhs: &'a Point<C>) {
194 self.0 -= rhs.0;
195 }
196}
197
198impl<C: Curve> Neg for &Point<C> {
201 type Output = Point<C>;
202
203 #[inline]
204 fn neg(self) -> Self::Output {
205 Point(-self.0)
206 }
207}
208impl_borrow_variants!(Point<C>, Neg, neg, -, C: Curve);
209
210impl<C: Curve> Mul<&ScalarAsExtension<C>> for &Point<C> {
213 type Output = Point<C>;
214
215 #[inline]
216 fn mul(self, rhs: &ScalarAsExtension<C>) -> Self::Output {
217 Point(self.0 * rhs.0)
218 }
219}
220impl_borrow_variants!(Point<C>, Mul, mul, *, ScalarAsExtension<C>, C: Curve);
221impl_commutative!(Point<C>, Mul, mul, *, ScalarAsExtension<C>, C: Curve);
222
223impl<C: Curve> Mul<&Scalar<C>> for &Point<C> {
224 type Output = Point<C>;
225
226 #[inline]
227 fn mul(self, rhs: &Scalar<C>) -> Self::Output {
228 Point(self.0 * rhs.0)
229 }
230}
231impl_borrow_variants!(Point<C>, Mul, mul, *, Scalar<C>, C: Curve);
232impl_commutative!(Point<C>, Mul, mul, *, Scalar<C>, C: Curve);
233
234impl<C: Curve> MulAssign<ScalarAsExtension<C>> for Point<C> {
237 #[inline]
238 fn mul_assign(&mut self, rhs: ScalarAsExtension<C>) {
239 self.0 *= rhs.0;
240 }
241}
242
243impl<C: Curve> MulAssign<&ScalarAsExtension<C>> for Point<C> {
244 #[inline]
245 fn mul_assign(&mut self, rhs: &ScalarAsExtension<C>) {
246 self.0 *= rhs.0;
247 }
248}
249
250impl<C: Curve> MulAssign<Scalar<C>> for Point<C> {
251 #[inline]
252 fn mul_assign(&mut self, rhs: Scalar<C>) {
253 self.0 *= rhs.0;
254 }
255}
256
257impl<C: Curve> MulAssign<&Scalar<C>> for Point<C> {
258 #[inline]
259 fn mul_assign(&mut self, rhs: &Scalar<C>) {
260 self.0 *= rhs.0;
261 }
262}
263
264impl<C: Curve> ConstantTimeEq for Point<C> {
267 #[inline]
268 fn ct_eq(&self, other: &Self) -> Choice {
269 self.0.ct_eq(&other.0)
270 }
271}
272
273impl<C: Curve> ConditionallySelectable for Point<C> {
274 #[inline]
275 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
276 let selected = C::Point::conditional_select(&a.0, &b.0, choice);
277 Point(selected)
278 }
279}
280
281impl<C: Curve> AdditiveShares for Point<C> {}
284
285impl<C: Curve> Sum for Point<C> {
288 #[inline]
289 fn sum<I: Iterator<Item = Point<C>>>(iter: I) -> Self {
290 iter.fold(Point::identity(), |acc, x| acc + x)
291 }
292}
293
294impl<'a, C: Curve> Sum<&'a Point<C>> for Point<C> {
295 #[inline]
296 fn sum<I: Iterator<Item = &'a Point<C>>>(iter: I) -> Self {
297 iter.fold(Point::identity(), |acc, x| acc + x)
298 }
299}