1use core::iter::{Product, Sum};
24use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
25
26use elliptic_curve::{
27 Field, Group, PrimeField,
28 subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
29};
30use ff_013::PrimeField as PrimeField013;
31use group_013::Group as Group013Trait;
32use rand_core::TryRng;
33
34#[derive(Clone, Copy, Debug, PartialEq, Eq)]
36pub struct Group013<P>(
37 pub P,
39);
40
41#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
43pub struct Scalar013<F>(
44 pub F,
46);
47
48macro_rules! scalar_binop {
51 ($trait:ident, $method:ident) => {
52 impl<F: PrimeField013> $trait for Scalar013<F> {
53 type Output = Self;
54 #[inline]
55 fn $method(self, rhs: Self) -> Self {
56 Scalar013($trait::$method(self.0, rhs.0))
57 }
58 }
59 impl<F: PrimeField013> $trait<&Scalar013<F>> for Scalar013<F> {
60 type Output = Self;
61 #[inline]
62 fn $method(self, rhs: &Scalar013<F>) -> Self {
63 Scalar013($trait::$method(self.0, rhs.0))
64 }
65 }
66 };
67}
68
69macro_rules! scalar_assign {
70 ($trait:ident, $method:ident) => {
71 impl<F: PrimeField013> $trait for Scalar013<F> {
72 #[inline]
73 fn $method(&mut self, rhs: Self) {
74 $trait::$method(&mut self.0, rhs.0)
75 }
76 }
77 impl<F: PrimeField013> $trait<&Scalar013<F>> for Scalar013<F> {
78 #[inline]
79 fn $method(&mut self, rhs: &Scalar013<F>) {
80 $trait::$method(&mut self.0, rhs.0)
81 }
82 }
83 };
84}
85
86scalar_binop!(Add, add);
87scalar_binop!(Sub, sub);
88scalar_binop!(Mul, mul);
89scalar_assign!(AddAssign, add_assign);
90scalar_assign!(SubAssign, sub_assign);
91scalar_assign!(MulAssign, mul_assign);
92
93impl<F: PrimeField013> Neg for Scalar013<F> {
94 type Output = Self;
95 #[inline]
96 fn neg(self) -> Self {
97 Scalar013(-self.0)
98 }
99}
100
101impl<F: PrimeField013> Sum for Scalar013<F> {
102 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
103 iter.fold(Scalar013(F::ZERO), Add::add)
104 }
105}
106
107impl<'a, F: PrimeField013> Sum<&'a Self> for Scalar013<F> {
108 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
109 iter.fold(Scalar013(F::ZERO), |acc, x| acc + *x)
110 }
111}
112
113impl<F: PrimeField013> Product for Scalar013<F> {
114 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
115 iter.fold(Scalar013(F::ONE), Mul::mul)
116 }
117}
118
119impl<'a, F: PrimeField013> Product<&'a Self> for Scalar013<F> {
120 fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
121 iter.fold(Scalar013(F::ONE), |acc, x| acc * *x)
122 }
123}
124
125impl<F: PrimeField013> ConstantTimeEq for Scalar013<F> {
126 fn ct_eq(&self, other: &Self) -> Choice {
127 self.0.ct_eq(&other.0)
128 }
129}
130
131impl<F: PrimeField013> ConditionallySelectable for Scalar013<F> {
132 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
133 Scalar013(F::conditional_select(&a.0, &b.0, choice))
134 }
135}
136
137impl<F: PrimeField013> From<u64> for Scalar013<F> {
138 fn from(value: u64) -> Self {
139 Scalar013(F::from(value))
140 }
141}
142
143impl<F: PrimeField013> Field for Scalar013<F> {
144 const ZERO: Self = Scalar013(F::ZERO);
145 const ONE: Self = Scalar013(F::ONE);
146
147 fn try_random<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
148 loop {
151 let mut repr = F::Repr::default();
152 let bytes: &mut [u8] = repr.as_mut();
153 rng.try_fill_bytes(bytes)?;
154 if let Some(value) = Option::<F>::from(F::from_repr(repr)) {
155 return Ok(Scalar013(value));
156 }
157 }
158 }
159
160 fn square(&self) -> Self {
161 Scalar013(self.0.square())
162 }
163
164 fn double(&self) -> Self {
165 Scalar013(self.0.double())
166 }
167
168 fn invert(&self) -> CtOption<Self> {
169 self.0.invert().map(Scalar013)
170 }
171
172 fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
173 let (choice, root) = F::sqrt_ratio(&num.0, &div.0);
174 (choice, Scalar013(root))
175 }
176}
177
178impl<F: PrimeField013> PrimeField for Scalar013<F> {
179 type Repr = F::Repr;
180
181 const MODULUS: &'static str = F::MODULUS;
182 const NUM_BITS: u32 = F::NUM_BITS;
183 const CAPACITY: u32 = F::CAPACITY;
184 const TWO_INV: Self = Scalar013(F::TWO_INV);
185 const MULTIPLICATIVE_GENERATOR: Self = Scalar013(F::MULTIPLICATIVE_GENERATOR);
186 const S: u32 = F::S;
187 const ROOT_OF_UNITY: Self = Scalar013(F::ROOT_OF_UNITY);
188 const ROOT_OF_UNITY_INV: Self = Scalar013(F::ROOT_OF_UNITY_INV);
189 const DELTA: Self = Scalar013(F::DELTA);
190
191 fn from_repr(repr: Self::Repr) -> CtOption<Self> {
192 F::from_repr(repr).map(Scalar013)
193 }
194
195 fn to_repr(&self) -> Self::Repr {
196 self.0.to_repr()
197 }
198
199 fn is_odd(&self) -> Choice {
200 self.0.is_odd()
201 }
202}
203
204macro_rules! group_binop {
207 ($trait:ident, $method:ident) => {
208 impl<P: Group013Trait + ConditionallySelectable> $trait for Group013<P> {
209 type Output = Self;
210 #[inline]
211 fn $method(self, rhs: Self) -> Self {
212 Group013($trait::$method(self.0, rhs.0))
213 }
214 }
215 impl<P: Group013Trait + ConditionallySelectable> $trait<&Group013<P>> for Group013<P> {
216 type Output = Self;
217 #[inline]
218 fn $method(self, rhs: &Group013<P>) -> Self {
219 Group013($trait::$method(self.0, rhs.0))
220 }
221 }
222 };
223}
224
225macro_rules! group_assign {
226 ($trait:ident, $method:ident) => {
227 impl<P: Group013Trait + ConditionallySelectable> $trait for Group013<P> {
228 #[inline]
229 fn $method(&mut self, rhs: Self) {
230 $trait::$method(&mut self.0, rhs.0)
231 }
232 }
233 impl<P: Group013Trait + ConditionallySelectable> $trait<&Group013<P>> for Group013<P> {
234 #[inline]
235 fn $method(&mut self, rhs: &Group013<P>) {
236 $trait::$method(&mut self.0, rhs.0)
237 }
238 }
239 };
240}
241
242group_binop!(Add, add);
243group_binop!(Sub, sub);
244group_assign!(AddAssign, add_assign);
245group_assign!(SubAssign, sub_assign);
246
247impl<P: Group013Trait + ConditionallySelectable> Neg for Group013<P> {
248 type Output = Self;
249 #[inline]
250 fn neg(self) -> Self {
251 Group013(-self.0)
252 }
253}
254
255impl<P: Group013Trait + ConditionallySelectable> Mul<Scalar013<P::Scalar>> for Group013<P> {
256 type Output = Self;
257 #[inline]
258 fn mul(self, rhs: Scalar013<P::Scalar>) -> Self {
259 Group013(self.0 * rhs.0)
260 }
261}
262
263impl<P: Group013Trait + ConditionallySelectable> Mul<&Scalar013<P::Scalar>> for Group013<P> {
264 type Output = Self;
265 #[inline]
266 fn mul(self, rhs: &Scalar013<P::Scalar>) -> Self {
267 Group013(self.0 * rhs.0)
268 }
269}
270
271impl<P: Group013Trait + ConditionallySelectable> MulAssign<Scalar013<P::Scalar>> for Group013<P> {
272 #[inline]
273 fn mul_assign(&mut self, rhs: Scalar013<P::Scalar>) {
274 self.0 *= rhs.0;
275 }
276}
277
278impl<P: Group013Trait + ConditionallySelectable> MulAssign<&Scalar013<P::Scalar>> for Group013<P> {
279 #[inline]
280 fn mul_assign(&mut self, rhs: &Scalar013<P::Scalar>) {
281 self.0 *= rhs.0;
282 }
283}
284
285impl<P: Group013Trait + ConditionallySelectable> Sum for Group013<P> {
286 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
287 iter.fold(Group013(P::identity()), Add::add)
288 }
289}
290
291impl<'a, P: Group013Trait + ConditionallySelectable> Sum<&'a Self> for Group013<P> {
292 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
293 iter.fold(Group013(P::identity()), |acc, x| acc + *x)
294 }
295}
296
297impl<P: Group013Trait + ConditionallySelectable> ConditionallySelectable for Group013<P> {
298 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
299 Group013(P::conditional_select(&a.0, &b.0, choice))
300 }
301}
302
303impl<P: Group013Trait + ConditionallySelectable> Group for Group013<P> {
304 type Scalar = Scalar013<P::Scalar>;
305
306 fn try_random<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
307 let scalar = <Scalar013<P::Scalar> as Field>::try_random(rng)?;
308 Ok(Group013(P::generator() * scalar.0))
309 }
310
311 fn identity() -> Self {
312 Group013(P::identity())
313 }
314
315 fn generator() -> Self {
316 Group013(P::generator())
317 }
318
319 fn is_identity(&self) -> Choice {
320 self.0.is_identity()
321 }
322
323 fn double(&self) -> Self {
324 Group013(self.0.double())
325 }
326}
327
328#[cfg(any(feature = "alloc", feature = "std"))]
336pub type Scratch<P> = crate::Scratch<Group013<P>>;
337
338#[cfg(any(feature = "alloc", feature = "std"))]
343pub trait SumOfProducts: Group013Trait + ConditionallySelectable {
344 fn sum_of_products(pairs: &[(<Self as Group013Trait>::Scalar, Self)]) -> Self;
346
347 fn sum_of_products_vartime(pairs: &[(<Self as Group013Trait>::Scalar, Self)]) -> Self;
349
350 fn sum_of_products_inplace(
356 pairs: &[(<Self as Group013Trait>::Scalar, Self)],
357 scratch: &mut Scratch<Self>,
358 ) -> Result<Self, crate::InsufficientScratch>;
359
360 fn sum_of_products_vartime_inplace(
363 pairs: &[(<Self as Group013Trait>::Scalar, Self)],
364 scratch: &mut Scratch<Self>,
365 ) -> Result<Self, crate::InsufficientScratch>;
366
367 fn sum_of_products_iter<I>(pairs: I) -> Self
370 where
371 I: IntoIterator<Item = (<Self as Group013Trait>::Scalar, Self)>,
372 I::IntoIter: ExactSizeIterator;
373}
374
375#[cfg(any(feature = "alloc", feature = "std"))]
376impl<P> SumOfProducts for P
377where
378 P: Group013Trait + ConditionallySelectable,
379 P::Scalar: PrimeField013,
380{
381 fn sum_of_products(pairs: &[(P::Scalar, Self)]) -> Self {
382 let wrapped = wrap(pairs);
383 crate::SumOfProducts::sum_of_products(wrapped.as_slice()).0
384 }
385
386 fn sum_of_products_vartime(pairs: &[(P::Scalar, Self)]) -> Self {
387 let wrapped = wrap(pairs);
388 crate::SumOfProducts::sum_of_products_vartime(wrapped.as_slice()).0
389 }
390
391 fn sum_of_products_inplace(
392 pairs: &[(P::Scalar, Self)],
393 scratch: &mut Scratch<Self>,
394 ) -> Result<Self, crate::InsufficientScratch> {
395 let wrapped = wrap(pairs);
396 crate::SumOfProducts::sum_of_products_inplace(wrapped.as_slice(), scratch).map(|g| g.0)
397 }
398
399 fn sum_of_products_vartime_inplace(
400 pairs: &[(P::Scalar, Self)],
401 scratch: &mut Scratch<Self>,
402 ) -> Result<Self, crate::InsufficientScratch> {
403 let wrapped = wrap(pairs);
404 crate::SumOfProducts::sum_of_products_vartime_inplace(wrapped.as_slice(), scratch)
405 .map(|g| g.0)
406 }
407
408 fn sum_of_products_iter<I>(pairs: I) -> Self
409 where
410 I: IntoIterator<Item = (P::Scalar, Self)>,
411 I::IntoIter: ExactSizeIterator,
412 {
413 let wrapped = pairs
414 .into_iter()
415 .map(|(scalar, point)| (Scalar013(scalar), Group013(point)));
416 crate::SumOfProducts::sum_of_products_iter(wrapped).0
417 }
418}
419
420#[cfg(all(feature = "alloc", not(feature = "std")))]
421use alloc::vec::Vec;
422#[cfg(feature = "std")]
423use std::vec::Vec;
424
425#[cfg(any(feature = "alloc", feature = "std"))]
426fn wrap<P>(pairs: &[(P::Scalar, P)]) -> Vec<(Scalar013<P::Scalar>, Group013<P>)>
427where
428 P: Group013Trait + ConditionallySelectable,
429 P::Scalar: PrimeField013,
430{
431 pairs
432 .iter()
433 .map(|(scalar, point)| (Scalar013(*scalar), Group013(*point)))
434 .collect()
435}