1pub mod edwards;
2pub mod params;
3pub mod scalar_mul;
5pub mod uint256;
6pub mod utils;
7pub mod weierstrass;
8
9pub mod curve25519_dalek {
10 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
18 pub struct CompressedEdwardsY(pub [u8; 32]);
19
20 impl CompressedEdwardsY {
21 pub fn as_bytes(&self) -> &[u8; 32] {
23 &self.0
24 }
25
26 pub fn to_bytes(&self) -> [u8; 32] {
28 self.0
29 }
30
31 pub fn from_slice(
38 bytes: &[u8],
39 ) -> Result<CompressedEdwardsY, core::array::TryFromSliceError> {
40 bytes.try_into().map(CompressedEdwardsY)
41 }
42 }
43}
44
45pub use k256;
46pub use p256;
47
48use params::{FieldParameters, NumWords};
49use sp1_primitives::consts::WORD_SIZE;
50use std::{
51 fmt::{Debug, Display, Formatter, Result},
52 ops::{Add, Neg},
53};
54use typenum::Unsigned;
55
56pub use num::{BigUint, Integer, One, Zero};
57use serde::{de::DeserializeOwned, Serialize};
58
59pub const NUM_WORDS_FIELD_ELEMENT: usize = 8;
60pub const NUM_BYTES_FIELD_ELEMENT: usize = NUM_WORDS_FIELD_ELEMENT * WORD_SIZE;
61pub const COMPRESSED_POINT_BYTES: usize = 32;
62
63pub const NUM_WORDS_EC_POINT: usize = 2 * NUM_WORDS_FIELD_ELEMENT;
66
67#[derive(Debug, PartialEq, Eq)]
68pub enum CurveType {
69 Secp256k1,
70 Secp256r1,
71 Bn254,
72 Ed25519,
73 Bls12381,
74}
75
76impl Display for CurveType {
77 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
78 match self {
79 CurveType::Secp256k1 => write!(f, "Secp256k1"),
80 CurveType::Secp256r1 => write!(f, "Secp256r1"),
81 CurveType::Bn254 => write!(f, "Bn254"),
82 CurveType::Ed25519 => write!(f, "Ed25519"),
83 CurveType::Bls12381 => write!(f, "Bls12381"),
84 }
85 }
86}
87
88#[derive(Debug, Clone, PartialEq, Eq)]
89pub struct AffinePoint<E> {
90 pub x: BigUint,
91 pub y: BigUint,
92 _marker: std::marker::PhantomData<E>,
93}
94
95impl<E: EllipticCurveParameters> AffinePoint<E> {
96 #[allow(dead_code)]
97 pub const fn new(x: BigUint, y: BigUint) -> Self {
98 Self { x, y, _marker: std::marker::PhantomData }
99 }
100
101 pub fn from_words_le(words: &[u32]) -> Self {
102 let x_bytes =
103 words[0..words.len() / 2].iter().flat_map(|n| n.to_le_bytes()).collect::<Vec<_>>();
104 let y_bytes =
105 &words[words.len() / 2..].iter().flat_map(|n| n.to_le_bytes()).collect::<Vec<_>>();
106 let x = BigUint::from_bytes_le(x_bytes.as_slice());
107 let y = BigUint::from_bytes_le(y_bytes.as_slice());
108 Self { x, y, _marker: std::marker::PhantomData }
109 }
110
111 pub fn to_words_le(&self) -> Vec<u32> {
112 let num_words = <E::BaseField as NumWords>::WordsCurvePoint::USIZE;
113 let num_bytes = num_words * 4;
114 let half_words = num_words / 2;
115
116 let mut x_bytes = self.x.to_bytes_le();
117 x_bytes.resize(num_bytes / 2, 0u8);
118 let mut y_bytes = self.y.to_bytes_le();
119 y_bytes.resize(num_bytes / 2, 0u8);
120
121 let mut words = vec![0u32; num_words];
122
123 for i in 0..half_words {
124 let x = u32::from_le_bytes([
125 x_bytes[4 * i],
126 x_bytes[4 * i + 1],
127 x_bytes[4 * i + 2],
128 x_bytes[4 * i + 3],
129 ]);
130 let y = u32::from_le_bytes([
131 y_bytes[4 * i],
132 y_bytes[4 * i + 1],
133 y_bytes[4 * i + 2],
134 y_bytes[4 * i + 3],
135 ]);
136
137 words[i] = x;
138 words[half_words + i] = y;
139 }
140
141 words
142 }
143}
144
145pub trait EllipticCurveParameters:
146 Debug + Send + Sync + Copy + Serialize + DeserializeOwned + 'static
147{
148 type BaseField: FieldParameters + NumWords;
149
150 const CURVE_TYPE: CurveType;
151}
152
153pub trait EllipticCurve: EllipticCurveParameters {
155 const NB_LIMBS: usize = Self::BaseField::NB_LIMBS;
156
157 const NB_WITNESS_LIMBS: usize = Self::BaseField::NB_WITNESS_LIMBS;
158 fn ec_add(p: &AffinePoint<Self>, q: &AffinePoint<Self>) -> AffinePoint<Self>;
162
163 fn ec_double(p: &AffinePoint<Self>) -> AffinePoint<Self>;
165
166 fn ec_generator() -> AffinePoint<Self>;
168
169 fn ec_neutral() -> Option<AffinePoint<Self>>;
172
173 fn ec_neg(p: &AffinePoint<Self>) -> AffinePoint<Self>;
175
176 fn nb_scalar_bits() -> usize {
178 Self::BaseField::NB_LIMBS * Self::BaseField::NB_BITS_PER_LIMB
179 }
180}
181
182impl<E: EllipticCurve> Add<&AffinePoint<E>> for &AffinePoint<E> {
183 type Output = AffinePoint<E>;
184
185 fn add(self, other: &AffinePoint<E>) -> AffinePoint<E> {
186 E::ec_add(self, other)
187 }
188}
189
190impl<E: EllipticCurve> Add<AffinePoint<E>> for AffinePoint<E> {
191 type Output = AffinePoint<E>;
192
193 fn add(self, other: AffinePoint<E>) -> AffinePoint<E> {
194 &self + &other
195 }
196}
197
198impl<E: EllipticCurve> Add<&AffinePoint<E>> for AffinePoint<E> {
199 type Output = AffinePoint<E>;
200
201 fn add(self, other: &AffinePoint<E>) -> AffinePoint<E> {
202 &self + other
203 }
204}
205
206impl<E: EllipticCurve> Neg for &AffinePoint<E> {
207 type Output = AffinePoint<E>;
208
209 fn neg(self) -> AffinePoint<E> {
210 E::ec_neg(self)
211 }
212}
213
214impl<E: EllipticCurve> Neg for AffinePoint<E> {
215 type Output = AffinePoint<E>;
216
217 fn neg(self) -> AffinePoint<E> {
218 -&self
219 }
220}