ark_ec/models/twisted_edwards/
group.rs1use ark_serialize::{
2    CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate,
3};
4use ark_std::{
5    borrow::Borrow,
6    fmt::{Display, Formatter, Result as FmtResult},
7    hash::{Hash, Hasher},
8    io::{Read, Write},
9    ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
10    rand::{
11        distributions::{Distribution, Standard},
12        Rng,
13    },
14    vec::*,
15    One, Zero,
16};
17
18use ark_ff::{fields::Field, AdditiveGroup, PrimeField, ToConstraintField, UniformRand};
19
20use educe::Educe;
21use zeroize::Zeroize;
22
23#[cfg(feature = "parallel")]
24use rayon::prelude::*;
25
26use super::{Affine, MontCurveConfig, TECurveConfig};
27use crate::{
28    scalar_mul::{variable_base::VariableBaseMSM, ScalarMul},
29    AffineRepr, CurveGroup, PrimeGroup,
30};
31
32#[derive(Educe)]
38#[educe(Copy, Clone, Eq(bound(P: TECurveConfig)), Debug)]
39#[must_use]
40pub struct Projective<P: TECurveConfig> {
41    pub x: P::BaseField,
42    pub y: P::BaseField,
43    pub t: P::BaseField,
44    pub z: P::BaseField,
45}
46
47impl<P: TECurveConfig> PartialEq<Affine<P>> for Projective<P> {
48    fn eq(&self, other: &Affine<P>) -> bool {
49        *self == other.into_group()
50    }
51}
52
53impl<P: TECurveConfig> Display for Projective<P> {
54    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
55        write!(f, "{}", Affine::from(*self))
56    }
57}
58
59impl<P: TECurveConfig> PartialEq for Projective<P> {
60    fn eq(&self, other: &Self) -> bool {
61        if self.is_zero() {
62            return other.is_zero();
63        }
64
65        if other.is_zero() {
66            return false;
67        }
68
69        (self.x * &other.z) == (other.x * &self.z) && (self.y * &other.z) == (other.y * &self.z)
71    }
72}
73
74impl<P: TECurveConfig> Hash for Projective<P> {
75    fn hash<H: Hasher>(&self, state: &mut H) {
76        self.into_affine().hash(state)
77    }
78}
79
80impl<P: TECurveConfig> Distribution<Projective<P>> for Standard {
81    #[inline]
83    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Projective<P> {
84        loop {
85            let y = P::BaseField::rand(rng);
86            let greatest = rng.gen();
87
88            if let Some(p) = Affine::get_point_from_y_unchecked(y, greatest) {
89                return p.mul_by_cofactor_to_group();
90            }
91        }
92    }
93}
94
95impl<P: TECurveConfig> Default for Projective<P> {
96    #[inline]
97    fn default() -> Self {
98        Self::zero()
99    }
100}
101
102impl<P: TECurveConfig> Projective<P> {
103    pub const fn new_unchecked(
106        x: P::BaseField,
107        y: P::BaseField,
108        t: P::BaseField,
109        z: P::BaseField,
110    ) -> Self {
111        Self { x, y, t, z }
112    }
113
114    pub fn new(x: P::BaseField, y: P::BaseField, t: P::BaseField, z: P::BaseField) -> Self {
117        let p = Self::new_unchecked(x, y, t, z).into_affine();
118        assert!(p.is_on_curve());
119        assert!(p.is_in_correct_subgroup_assuming_on_curve());
120        p.into()
121    }
122}
123impl<P: TECurveConfig> Zeroize for Projective<P> {
124    fn zeroize(&mut self) {
127        self.x.zeroize();
128        self.y.zeroize();
129        self.t.zeroize();
130        self.z.zeroize();
131    }
132}
133
134impl<P: TECurveConfig> Zero for Projective<P> {
135    fn zero() -> Self {
136        Self::new_unchecked(
137            P::BaseField::zero(),
138            P::BaseField::one(),
139            P::BaseField::zero(),
140            P::BaseField::one(),
141        )
142    }
143
144    fn is_zero(&self) -> bool {
145        self.x.is_zero() && self.y == self.z && !self.y.is_zero() && self.t.is_zero()
146    }
147}
148
149impl<P: TECurveConfig> AdditiveGroup for Projective<P> {
150    type Scalar = P::ScalarField;
151
152    const ZERO: Self = Self::new_unchecked(
153        P::BaseField::ZERO,
154        P::BaseField::ONE,
155        P::BaseField::ZERO,
156        P::BaseField::ONE,
157    );
158
159    fn double_in_place(&mut self) -> &mut Self {
160        let a = self.x.square();
167        let b = self.y.square();
169        let c = self.z.square().double();
171        let d = P::mul_by_a(a);
173        let e = (self.x + &self.y).square() - &a - &b;
175        let g = d + &b;
177        let f = g - &c;
179        let h = d - &b;
181        self.x = e * &f;
183        self.y = g * &h;
185        self.t = e * &h;
187        self.z = f * &g;
189
190        self
191    }
192}
193
194impl<P: TECurveConfig> PrimeGroup for Projective<P> {
195    type ScalarField = P::ScalarField;
196
197    fn generator() -> Self {
198        Affine::generator().into()
199    }
200
201    #[inline]
202    fn mul_bigint(&self, other: impl AsRef<[u64]>) -> Self {
203        P::mul_projective(self, other.as_ref())
204    }
205}
206
207impl<P: TECurveConfig> CurveGroup for Projective<P> {
208    type Config = P;
209    type BaseField = P::BaseField;
210    type Affine = Affine<P>;
211    type FullGroup = Affine<P>;
212
213    fn normalize_batch(v: &[Self]) -> Vec<Self::Affine> {
214        let mut z_s = v.iter().map(|g| g.z).collect::<Vec<_>>();
221        ark_ff::batch_inversion(&mut z_s);
222
223        ark_std::cfg_iter!(v)
225            .zip(z_s)
226            .map(|(g, z)| match g.is_zero() {
227                true => Affine::zero(),
228                false => {
229                    let x = g.x * &z;
230                    let y = g.y * &z;
231                    Affine::new_unchecked(x, y)
232                },
233            })
234            .collect()
235    }
236}
237
238impl<P: TECurveConfig> Neg for Projective<P> {
239    type Output = Self;
240    fn neg(mut self) -> Self {
241        self.x = -self.x;
242        self.t = -self.t;
243        self
244    }
245}
246
247impl<P: TECurveConfig, T: Borrow<Affine<P>>> AddAssign<T> for Projective<P> {
248    fn add_assign(&mut self, other: T) {
249        let other = other.borrow();
250        let a = self.x * &other.x;
257        let b = self.y * &other.y;
259        let c = P::COEFF_D * &self.t * &other.x * &other.y;
261
262        let d = self.z;
264        let e = (self.x + &self.y) * &(other.x + &other.y) - &a - &b;
266        let f = d - &c;
268        let g = d + &c;
270        let h = b - &P::mul_by_a(a);
272        self.x = e * &f;
274        self.y = g * &h;
276        self.t = e * &h;
278        self.z = f * &g;
280    }
281}
282
283impl<P: TECurveConfig, T: Borrow<Affine<P>>> Add<T> for Projective<P> {
284    type Output = Self;
285    fn add(mut self, other: T) -> Self {
286        let other = other.borrow();
287        self += other;
288        self
289    }
290}
291
292impl<P: TECurveConfig, T: Borrow<Affine<P>>> SubAssign<T> for Projective<P> {
293    fn sub_assign(&mut self, other: T) {
294        *self += -(*other.borrow());
295    }
296}
297
298impl<P: TECurveConfig, T: Borrow<Affine<P>>> Sub<T> for Projective<P> {
299    type Output = Self;
300    fn sub(mut self, other: T) -> Self {
301        self -= other.borrow();
302        self
303    }
304}
305ark_ff::impl_additive_ops_from_ref!(Projective, TECurveConfig);
306
307impl<'a, P: TECurveConfig> Add<&'a Self> for Projective<P> {
308    type Output = Self;
309    fn add(mut self, other: &'a Self) -> Self {
310        self += other;
311        self
312    }
313}
314
315impl<'a, P: TECurveConfig> Sub<&'a Self> for Projective<P> {
316    type Output = Self;
317    fn sub(mut self, other: &'a Self) -> Self {
318        self -= other;
319        self
320    }
321}
322
323impl<'a, P: TECurveConfig> AddAssign<&'a Self> for Projective<P> {
324    fn add_assign(&mut self, other: &'a Self) {
325        let a = self.x * &other.x;
331
332        let b = self.y * &other.y;
334
335        let c = P::COEFF_D * &self.t * &other.t;
337
338        let d = self.z * &other.z;
340
341        let h = b - &P::mul_by_a(a);
343
344        let e = (self.x + &self.y) * &(other.x + &other.y) - &a - &b;
346
347        let f = d - &c;
349
350        let g = d + &c;
352
353        self.x = e * &f;
355
356        self.y = g * &h;
358
359        self.t = e * &h;
361
362        self.z = f * &g;
364    }
365}
366
367impl<'a, P: TECurveConfig> SubAssign<&'a Self> for Projective<P> {
368    fn sub_assign(&mut self, other: &'a Self) {
369        *self += -(*other);
370    }
371}
372
373impl<P: TECurveConfig, T: Borrow<P::ScalarField>> MulAssign<T> for Projective<P> {
374    fn mul_assign(&mut self, other: T) {
375        *self = self.mul_bigint(other.borrow().into_bigint())
376    }
377}
378
379impl<P: TECurveConfig, T: Borrow<P::ScalarField>> Mul<T> for Projective<P> {
380    type Output = Self;
381
382    #[inline]
383    fn mul(mut self, other: T) -> Self {
384        self *= other;
385        self
386    }
387}
388
389impl<P: TECurveConfig, T: Borrow<Affine<P>>> ark_std::iter::Sum<T> for Projective<P> {
390    fn sum<I>(iter: I) -> Self
391    where
392        I: Iterator<Item = T>,
393    {
394        iter.fold(Self::zero(), |acc, x| acc + x.borrow())
395    }
396}
397
398impl<P: TECurveConfig> From<Affine<P>> for Projective<P> {
401    fn from(p: Affine<P>) -> Projective<P> {
402        Self::new_unchecked(p.x, p.y, p.x * &p.y, P::BaseField::one())
403    }
404}
405
406#[derive(Educe)]
407#[educe(Copy, Clone, PartialEq, Eq, Debug, Hash)]
408pub struct MontgomeryAffine<P: MontCurveConfig> {
409    pub x: P::BaseField,
410    pub y: P::BaseField,
411}
412
413impl<P: MontCurveConfig> Display for MontgomeryAffine<P> {
414    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
415        write!(f, "MontgomeryAffine(x={}, y={})", self.x, self.y)
416    }
417}
418
419impl<P: MontCurveConfig> MontgomeryAffine<P> {
420    pub fn new(x: P::BaseField, y: P::BaseField) -> Self {
421        Self { x, y }
422    }
423}
424
425impl<P: TECurveConfig> CanonicalSerialize for Projective<P> {
426    #[allow(unused_qualifications)]
427    #[inline]
428    fn serialize_with_mode<W: Write>(
429        &self,
430        writer: W,
431        compress: Compress,
432    ) -> Result<(), SerializationError> {
433        let aff = Affine::<P>::from(*self);
434        P::serialize_with_mode(&aff, writer, compress)
435    }
436
437    #[inline]
438    fn serialized_size(&self, compress: Compress) -> usize {
439        P::serialized_size(compress)
440    }
441}
442
443impl<P: TECurveConfig> Valid for Projective<P> {
444    fn check(&self) -> Result<(), SerializationError> {
445        self.into_affine().check()
446    }
447
448    fn batch_check<'a>(
449        batch: impl Iterator<Item = &'a Self> + Send,
450    ) -> Result<(), SerializationError>
451    where
452        Self: 'a,
453    {
454        let batch = batch.copied().collect::<Vec<_>>();
455        let batch = Self::normalize_batch(&batch);
456        Affine::batch_check(batch.iter())
457    }
458}
459
460impl<P: TECurveConfig> CanonicalDeserialize for Projective<P> {
461    #[allow(unused_qualifications)]
462    fn deserialize_with_mode<R: Read>(
463        reader: R,
464        compress: Compress,
465        validate: Validate,
466    ) -> Result<Self, SerializationError> {
467        let aff = P::deserialize_with_mode(reader, compress, validate)?;
468        Ok(aff.into())
469    }
470}
471
472impl<M: TECurveConfig, ConstraintF: Field> ToConstraintField<ConstraintF> for Projective<M>
473where
474    M::BaseField: ToConstraintField<ConstraintF>,
475{
476    #[inline]
477    fn to_field_elements(&self) -> Option<Vec<ConstraintF>> {
478        Affine::from(*self).to_field_elements()
479    }
480}
481
482impl<P: TECurveConfig> ScalarMul for Projective<P> {
483    type MulBase = Affine<P>;
484    const NEGATION_IS_CHEAP: bool = true;
485
486    fn batch_convert_to_mul_base(bases: &[Self]) -> Vec<Self::MulBase> {
487        Self::normalize_batch(bases)
488    }
489}
490
491impl<P: TECurveConfig> VariableBaseMSM for Projective<P> {
492    fn msm(bases: &[Self::MulBase], bigints: &[Self::ScalarField]) -> Result<Self, usize> {
493        P::msm(bases, bigints)
494    }
495}