snarkvm_curves/templates/
macros.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16// https://github.com/rust-lang/rust/issues/57966 forces us to export these and
17// import them via `use crate::` syntax. It'd be nice if we were able to avoid any
18// macro_use/macro_export and just import the macro
19#[macro_export]
20macro_rules! impl_sw_curve_serializer {
21    ($params: ident) => {
22        // Projective Group point implementations delegate to the Affine version
23        impl<P: $params> CanonicalSerialize for Projective<P> {
24            #[allow(unused_qualifications)]
25            #[inline]
26            fn serialize_with_mode<W: std::io::Write>(
27                &self,
28                writer: W,
29                compress: Compress,
30            ) -> Result<(), snarkvm_utilities::serialize::SerializationError> {
31                CanonicalSerialize::serialize_with_mode(&Affine::<P>::from(*self), writer, compress)
32            }
33
34            #[inline]
35            fn serialized_size(&self, compress: Compress) -> usize {
36                Affine::<P>::from(*self).serialized_size(compress)
37            }
38
39            #[inline]
40            fn uncompressed_size(&self) -> usize {
41                Affine::<P>::from(*self).uncompressed_size()
42            }
43        }
44
45        impl<P: $params> Valid for Projective<P> {
46            fn check(&self) -> Result<(), snarkvm_utilities::serialize::SerializationError> {
47                let point = Affine::<P>::from(*self);
48                if point.is_on_curve() & point.is_in_correct_subgroup_assuming_on_curve() {
49                    Ok(())
50                } else {
51                    Err(snarkvm_utilities::serialize::SerializationError::InvalidData)
52                }
53            }
54        }
55
56        impl<P: $params> CanonicalDeserialize for Projective<P> {
57            #[allow(unused_qualifications)]
58            fn deserialize_with_mode<R: std::io::Read>(
59                reader: R,
60                compress: Compress,
61                validate: Validate,
62            ) -> Result<Self, snarkvm_utilities::serialize::SerializationError> {
63                Affine::<P>::deserialize_with_mode(reader, compress, validate).map(Into::into)
64            }
65        }
66
67        impl<P: $params> CanonicalSerialize for Affine<P> {
68            #[allow(unused_qualifications)]
69            #[inline]
70            fn serialize_with_mode<W: std::io::Write>(
71                &self,
72                mut writer: W,
73                compress: Compress,
74            ) -> Result<(), snarkvm_utilities::serialize::SerializationError> {
75                match compress {
76                    Compress::Yes => {
77                        if self.is_zero() {
78                            let flags = snarkvm_utilities::serialize::SWFlags::infinity();
79                            // Serialize 0.
80                            P::BaseField::zero().serialize_with_flags(writer, flags)
81                        } else {
82                            let flags = snarkvm_utilities::serialize::SWFlags::from_y_sign(self.y > -self.y);
83                            self.x.serialize_with_flags(writer, flags)
84                        }
85                    }
86                    Compress::No => {
87                        let flags = if self.is_zero() {
88                            snarkvm_utilities::serialize::SWFlags::infinity()
89                        } else {
90                            snarkvm_utilities::serialize::SWFlags::default()
91                        };
92                        self.x.serialize_uncompressed(&mut writer)?;
93                        self.y.serialize_with_flags(&mut writer, flags)?;
94                        Ok(())
95                    }
96                }
97            }
98
99            #[inline]
100            fn serialized_size(&self, compress: Compress) -> usize {
101                match compress {
102                    Compress::Yes => self.x.serialized_size_with_flags::<SWFlags>(),
103                    Compress::No => self.x.serialized_size(compress) + self.y.serialized_size_with_flags::<SWFlags>(),
104                }
105            }
106        }
107
108        impl<P: $params> Valid for Affine<P> {
109            fn check(&self) -> Result<(), snarkvm_utilities::serialize::SerializationError> {
110                if self.is_on_curve() & self.is_in_correct_subgroup_assuming_on_curve() {
111                    Ok(())
112                } else {
113                    Err(snarkvm_utilities::serialize::SerializationError::InvalidData)
114                }
115            }
116        }
117
118        impl<P: $params> CanonicalDeserialize for Affine<P> {
119            #[allow(unused_qualifications)]
120            fn deserialize_with_mode<R: std::io::Read>(
121                mut reader: R,
122                compress: Compress,
123                validate: Validate,
124            ) -> Result<Self, snarkvm_utilities::serialize::SerializationError> {
125                use snarkvm_utilities::serialize::SWFlags;
126                let point = if let Compress::Yes = compress {
127                    let (x, flags) = P::BaseField::deserialize_with_flags::<_, SWFlags>(&mut reader)?;
128                    if flags.is_infinity() {
129                        Self::zero()
130                    } else {
131                        Affine::<P>::from_x_coordinate(x, flags.is_positive().unwrap())
132                            .ok_or(snarkvm_utilities::serialize::SerializationError::InvalidData)?
133                    }
134                } else {
135                    let x = P::BaseField::deserialize_uncompressed(&mut reader)?;
136                    let (y, flags) = P::BaseField::deserialize_with_flags::<_, SWFlags>(&mut reader)?;
137                    Affine::<P>::new(x, y, flags.is_infinity())
138                };
139                if validate == Validate::Yes {
140                    point.check()?;
141                }
142                Ok(point)
143            }
144        }
145    };
146}
147#[macro_export]
148macro_rules! impl_edwards_curve_serializer {
149    ($params: ident) => {
150        impl<P: $params> CanonicalSerialize for Projective<P> {
151            #[allow(unused_qualifications)]
152            #[inline]
153            fn serialize_with_mode<W: std::io::Write>(
154                &self,
155                writer: W,
156                compress: Compress,
157            ) -> Result<(), snarkvm_utilities::serialize::SerializationError> {
158                Affine::<P>::from(*self).serialize_with_mode(writer, compress)
159            }
160
161            #[inline]
162            fn serialized_size(&self, compress: Compress) -> usize {
163                Affine::<P>::from(*self).serialized_size(compress)
164            }
165        }
166
167        impl<P: $params> Valid for Projective<P> {
168            fn check(&self) -> Result<(), snarkvm_utilities::serialize::SerializationError> {
169                let point = Affine::<P>::from(*self);
170                if point.is_on_curve() & point.is_in_correct_subgroup_assuming_on_curve() {
171                    Ok(())
172                } else {
173                    Err(snarkvm_utilities::serialize::SerializationError::InvalidData)
174                }
175            }
176        }
177
178        impl<P: $params> CanonicalDeserialize for Projective<P> {
179            #[allow(unused_qualifications)]
180            fn deserialize_with_mode<R: std::io::Read>(
181                reader: R,
182                compress: Compress,
183                validate: Validate,
184            ) -> Result<Self, snarkvm_utilities::serialize::SerializationError> {
185                Affine::<P>::deserialize_with_mode(reader, compress, validate).map(Into::into)
186            }
187        }
188
189        impl<P: $params> CanonicalSerialize for Affine<P> {
190            #[allow(unused_qualifications)]
191            #[inline]
192            fn serialize_with_mode<W: std::io::Write>(
193                &self,
194                mut writer: W,
195                compress: Compress,
196            ) -> Result<(), snarkvm_utilities::serialize::SerializationError> {
197                if let Compress::Yes = compress {
198                    if self.is_zero() {
199                        let flags = snarkvm_utilities::serialize::EdwardsFlags::default();
200                        // Serialize 0.
201                        P::BaseField::zero().serialize_with_flags(&mut writer, flags)
202                    } else {
203                        let flags = snarkvm_utilities::serialize::EdwardsFlags::from_y_sign(self.y > -self.y);
204                        self.x.serialize_with_flags(writer, flags)
205                    }
206                } else {
207                    self.x.serialize_uncompressed(&mut writer)?;
208                    self.y.serialize_uncompressed(&mut writer)?;
209                    Ok(())
210                }
211            }
212
213            #[inline]
214            fn serialized_size(&self, compress: Compress) -> usize {
215                if let Compress::Yes = compress {
216                    use snarkvm_utilities::serialize::EdwardsFlags;
217                    self.x.serialized_size_with_flags::<EdwardsFlags>()
218                } else {
219                    self.x.uncompressed_size() + self.y.uncompressed_size()
220                }
221            }
222        }
223
224        impl<P: $params> Valid for Affine<P> {
225            #[allow(unused_qualifications)]
226            fn check(&self) -> Result<(), snarkvm_utilities::serialize::SerializationError> {
227                if self.is_on_curve() & self.is_in_correct_subgroup_assuming_on_curve() {
228                    Ok(())
229                } else {
230                    Err(snarkvm_utilities::serialize::SerializationError::InvalidData)
231                }
232            }
233        }
234
235        impl<P: $params> CanonicalDeserialize for Affine<P> {
236            #[allow(unused_qualifications)]
237            fn deserialize_with_mode<R: std::io::Read>(
238                mut reader: R,
239                compress: Compress,
240                validate: Validate,
241            ) -> Result<Self, snarkvm_utilities::serialize::SerializationError> {
242                use snarkvm_utilities::serialize::{EdwardsFlags, SerializationError};
243                let point = if let Compress::Yes = compress {
244                    let (x, flags): (P::BaseField, EdwardsFlags) = P::BaseField::deserialize_with_flags(&mut reader)?;
245
246                    if x == P::BaseField::zero() {
247                        Self::zero()
248                    } else {
249                        Affine::<P>::from_x_coordinate(x, flags.is_positive()).ok_or(SerializationError::InvalidData)?
250                    }
251                } else {
252                    let x = P::BaseField::deserialize_uncompressed(&mut reader)?;
253                    let y = P::BaseField::deserialize_uncompressed(&mut reader)?;
254                    Affine::<P>::new(x, y, x * y)
255                };
256
257                if let Validate::Yes = validate {
258                    Valid::check(&point)?;
259                }
260
261                Ok(point)
262            }
263        }
264    };
265}