ark_ec/models/short_weierstrass/
mod.rs

1use ark_serialize::{
2    CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize,
3    CanonicalSerializeWithFlags, Compress, SerializationError, Valid, Validate,
4};
5use ark_std::io::{Read, Write};
6
7use ark_ff::{fields::Field, AdditiveGroup};
8
9use crate::{
10    scalar_mul::{
11        sw_double_and_add_affine, sw_double_and_add_projective, variable_base::VariableBaseMSM,
12    },
13    AffineRepr,
14};
15use num_traits::Zero;
16
17mod affine;
18pub use affine::*;
19
20mod group;
21pub use group::*;
22
23mod serialization_flags;
24pub use serialization_flags::*;
25
26/// Constants and convenience functions that collectively define the [Short Weierstrass model](https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html)
27/// of the curve. In this model, the curve equation is `y² = x³ + a * x + b`,
28/// for constants `a` and `b`.
29pub trait SWCurveConfig: super::CurveConfig {
30    /// Coefficient `a` of the curve equation.
31    const COEFF_A: Self::BaseField;
32    /// Coefficient `b` of the curve equation.
33    const COEFF_B: Self::BaseField;
34    /// Generator of the prime-order subgroup.
35    const GENERATOR: Affine<Self>;
36
37    /// Helper method for computing `elem * Self::COEFF_A`.
38    ///
39    /// The default implementation should be overridden only if
40    /// the product can be computed faster than standard field multiplication
41    /// (eg: via doubling if `COEFF_A == 2`, or if `COEFF_A.is_zero()`).
42    #[inline(always)]
43    fn mul_by_a(elem: Self::BaseField) -> Self::BaseField {
44        if Self::COEFF_A.is_zero() {
45            Self::BaseField::ZERO
46        } else {
47            elem * Self::COEFF_A
48        }
49    }
50
51    /// Helper method for computing `elem + Self::COEFF_B`.
52    ///
53    /// The default implementation should be overridden only if
54    /// the sum can be computed faster than standard field addition (eg: via
55    /// doubling).
56    #[inline(always)]
57    fn add_b(elem: Self::BaseField) -> Self::BaseField {
58        if Self::COEFF_B.is_zero() {
59            elem
60        } else {
61            elem + &Self::COEFF_B
62        }
63    }
64
65    /// Check if the provided curve point is in the prime-order subgroup.
66    ///
67    /// The default implementation multiplies `item` by the order `r` of the
68    /// prime-order subgroup, and checks if the result is zero. If the
69    /// curve's cofactor is one, this check automatically returns true.
70    /// Implementors can choose to override this default impl
71    /// if the given curve has faster methods
72    /// for performing this check (for example, via leveraging curve
73    /// isomorphisms).
74    fn is_in_correct_subgroup_assuming_on_curve(item: &Affine<Self>) -> bool {
75        if Self::cofactor_is_one() {
76            true
77        } else {
78            Self::mul_affine(item, Self::ScalarField::characteristic()).is_zero()
79        }
80    }
81
82    /// Performs cofactor clearing.
83    /// The default method is simply to multiply by the cofactor.
84    /// Some curves can implement a more efficient algorithm.
85    fn clear_cofactor(item: &Affine<Self>) -> Affine<Self> {
86        item.mul_by_cofactor()
87    }
88
89    /// Default implementation of group multiplication for projective
90    /// coordinates
91    fn mul_projective(base: &Projective<Self>, scalar: &[u64]) -> Projective<Self> {
92        sw_double_and_add_projective(base, scalar)
93    }
94
95    /// Default implementation of group multiplication for affine
96    /// coordinates.
97    fn mul_affine(base: &Affine<Self>, scalar: &[u64]) -> Projective<Self> {
98        sw_double_and_add_affine(base, scalar)
99    }
100
101    /// Default implementation for multi scalar multiplication
102    fn msm(
103        bases: &[Affine<Self>],
104        scalars: &[Self::ScalarField],
105    ) -> Result<Projective<Self>, usize> {
106        (bases.len() == scalars.len())
107            .then(|| VariableBaseMSM::msm_unchecked(bases, scalars))
108            .ok_or(bases.len().min(scalars.len()))
109    }
110
111    /// If uncompressed, serializes both x and y coordinates as well as a bit for whether it is
112    /// infinity. If compressed, serializes x coordinate with two bits to encode whether y is
113    /// positive, negative, or infinity.
114    #[inline]
115    fn serialize_with_mode<W: Write>(
116        item: &Affine<Self>,
117        mut writer: W,
118        compress: ark_serialize::Compress,
119    ) -> Result<(), SerializationError> {
120        let (x, y, flags) = match item.infinity {
121            true => (
122                Self::BaseField::zero(),
123                Self::BaseField::zero(),
124                SWFlags::infinity(),
125            ),
126            false => (item.x, item.y, item.to_flags()),
127        };
128
129        match compress {
130            Compress::Yes => x.serialize_with_flags(writer, flags),
131            Compress::No => {
132                x.serialize_with_mode(&mut writer, compress)?;
133                y.serialize_with_flags(&mut writer, flags)
134            },
135        }
136    }
137
138    /// If `validate` is `Yes`, calls `check()` to make sure the element is valid.
139    fn deserialize_with_mode<R: Read>(
140        mut reader: R,
141        compress: Compress,
142        validate: Validate,
143    ) -> Result<Affine<Self>, SerializationError> {
144        let (x, y, flags) = match compress {
145            Compress::Yes => {
146                let (x, flags): (_, SWFlags) =
147                    CanonicalDeserializeWithFlags::deserialize_with_flags(reader)?;
148                match flags {
149                    SWFlags::PointAtInfinity => (
150                        Affine::<Self>::identity().x,
151                        Affine::<Self>::identity().y,
152                        flags,
153                    ),
154                    _ => {
155                        let is_positive = flags.is_positive().unwrap();
156                        let (y, neg_y) = Affine::<Self>::get_ys_from_x_unchecked(x)
157                            .ok_or(SerializationError::InvalidData)?;
158                        if is_positive {
159                            (x, y, flags)
160                        } else {
161                            (x, neg_y, flags)
162                        }
163                    },
164                }
165            },
166            Compress::No => {
167                let x: Self::BaseField =
168                    CanonicalDeserialize::deserialize_with_mode(&mut reader, compress, validate)?;
169                let (y, flags): (_, SWFlags) =
170                    CanonicalDeserializeWithFlags::deserialize_with_flags(&mut reader)?;
171                (x, y, flags)
172            },
173        };
174        if flags.is_infinity() {
175            Ok(Affine::<Self>::identity())
176        } else {
177            let point = Affine::<Self>::new_unchecked(x, y);
178            if let Validate::Yes = validate {
179                point.check()?;
180            }
181            Ok(point)
182        }
183    }
184
185    #[inline]
186    fn serialized_size(compress: Compress) -> usize {
187        let zero = Self::BaseField::zero();
188        match compress {
189            Compress::Yes => zero.serialized_size_with_flags::<SWFlags>(),
190            Compress::No => zero.compressed_size() + zero.serialized_size_with_flags::<SWFlags>(),
191        }
192    }
193}