stark_curve/core/
wrapper.rs

1use core::iter::{Product, Sum};
2use core::ops::{
3    Add, AddAssign, Deref, DerefMut, Mul, MulAssign, Neg, ShlAssign, ShrAssign, Sub, SubAssign,
4};
5
6use primeorder::elliptic_curve::ops::Invert;
7use subtle::{ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, CtOption};
8
9use crate::bigint::{Encoding, Uint, U256};
10use crate::elliptic_curve::{
11    self,
12    scalar::{FromUintUnchecked, IsHigh, ScalarPrimitive},
13    Field, PrimeField,
14};
15use crate::generic_array::GenericArray;
16use crate::typenum;
17
18/// Wraps scalar or field element
19///
20/// Field element and scalar, derived by [ff], initially are not compatible with [elliptic-curve] crate
21/// and cannot be used together. This struct wraps scalar or field element, and implements required traits.
22#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
23pub struct W<F>(F);
24
25impl<F> W<F> {
26    /// Wraps `n`
27    pub const fn new(n: F) -> Self {
28        Self(n)
29    }
30}
31
32impl<F> Deref for W<F> {
33    type Target = F;
34    fn deref(&self) -> &Self::Target {
35        &self.0
36    }
37}
38
39impl<F> DerefMut for W<F> {
40    fn deref_mut(&mut self) -> &mut Self::Target {
41        &mut self.0
42    }
43}
44
45impl<F: PrimeField> W<F> {
46    /// Converts integer to byte array in big-endian
47    pub fn to_be_bytes(&self) -> F::Repr {
48        self.0.to_repr()
49    }
50
51    /// Converts integer to byte array in little-endian
52    pub fn to_le_bytes(&self) -> F::Repr {
53        let mut bytes = self.to_be_bytes();
54        bytes.as_mut().reverse();
55        bytes
56    }
57
58    /// Constructs integer from its bytes representation in big-endian
59    ///
60    /// Returns `None` if it overflows maximum allowed value
61    pub fn from_be_bytes(bytes: F::Repr) -> CtOption<Self> {
62        F::from_repr(bytes).map(Self)
63    }
64
65    /// Constructs integer from its bytes representation in little-endian
66    ///
67    /// Returns `None` if it overflows maximum allowed value
68    pub fn from_le_bytes(mut bytes: F::Repr) -> CtOption<Self> {
69        bytes.as_mut().reverse();
70        Self::from_be_bytes(bytes)
71    }
72
73    /// Constructs integer from bytes in big-endian
74    ///
75    /// Integer is reduced modulo max allowed value ($p$ if it's field element, $n$ if it's a scalar)
76    pub fn from_be_bytes_mod_order(bytes: &[u8]) -> Self {
77        Self(
78            bytes
79                .iter()
80                .fold(F::ZERO, |s, b| s * F::from(256) + F::from(u64::from(*b))),
81        )
82    }
83
84    /// Constructs integer from bytes in little-endian
85    ///
86    /// Integer is reduced modulo max allowed value ($p$ if it's field element, $n$ if it's a scalar)
87    pub fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
88        Self(
89            bytes
90                .iter()
91                .rev()
92                .fold(F::ZERO, |s, b| s * F::from(256) + F::from(u64::from(*b))),
93        )
94    }
95
96    /// Constructs integer from [U256]
97    ///
98    /// Integer is reduced modulo max allowed value ($p$ if it's field element, $n$ if it's a scalar)
99    pub fn from_uint_mod_order(uint: &U256) -> Self {
100        Self::from_be_bytes_mod_order(&uint.to_be_bytes())
101    }
102}
103
104impl<F: PrimeField> W<F>
105where
106    [u8; 32]: From<F::Repr>,
107{
108    /// Converts integer to [U256]
109    pub fn to_uint(&self) -> U256 {
110        U256::from_be_bytes(self.to_be_bytes().into())
111    }
112}
113
114impl<F> AsRef<W<F>> for W<F> {
115    fn as_ref(&self) -> &W<F> {
116        self
117    }
118}
119
120impl<F: From<u64>> From<u64> for W<F> {
121    fn from(n: u64) -> Self {
122        Self(F::from(n))
123    }
124}
125
126impl<F: PrimeField, const LIMBS: usize> From<W<F>> for Uint<LIMBS>
127where
128    Uint<LIMBS>: Encoding,
129    <Uint<LIMBS> as Encoding>::Repr: From<F::Repr>,
130{
131    fn from(s: W<F>) -> Self {
132        Uint::from_be_bytes(s.to_be_bytes().into())
133    }
134}
135
136impl<F: PrimeField> FromUintUnchecked for W<F> {
137    type Uint = U256;
138
139    fn from_uint_unchecked(uint: Self::Uint) -> Self {
140        let bytes_be = uint.to_be_bytes();
141        Self::from_be_bytes_mod_order(&bytes_be)
142    }
143}
144
145impl<F: ConditionallySelectable> ConditionallySelectable for W<F> {
146    fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
147        Self(F::conditional_select(&a.0, &b.0, choice))
148    }
149}
150
151impl<F: ConstantTimeEq> ConstantTimeEq for W<F> {
152    fn ct_eq(&self, other: &Self) -> subtle::Choice {
153        self.0.ct_eq(&other.0)
154    }
155}
156
157impl<F: Sum> Sum for W<F> {
158    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
159        Self(iter.map(|f| f.0).sum())
160    }
161}
162
163impl<'f, F: Sum<&'f F>> Sum<&'f W<F>> for W<F> {
164    fn sum<I: Iterator<Item = &'f W<F>>>(iter: I) -> Self {
165        Self(iter.map(|f| &f.0).sum())
166    }
167}
168
169impl<F: Product> Product for W<F> {
170    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
171        Self(iter.map(|f| f.0).product())
172    }
173}
174
175impl<'f, F: Product<&'f F>> Product<&'f W<F>> for W<F> {
176    fn product<I: Iterator<Item = &'f W<F>>>(iter: I) -> Self {
177        Self(iter.map(|f| &f.0).product())
178    }
179}
180
181impl<F: Add<Output = F>> Add for W<F> {
182    type Output = Self;
183
184    fn add(self, rhs: Self) -> Self::Output {
185        Self(self.0 + rhs.0)
186    }
187}
188
189impl<F: Sub<Output = F>> Sub for W<F> {
190    type Output = W<F>;
191
192    fn sub(self, rhs: Self) -> Self::Output {
193        Self(self.0 - rhs.0)
194    }
195}
196
197impl<F: Mul<Output = F>> Mul for W<F> {
198    type Output = W<F>;
199
200    fn mul(self, rhs: Self) -> Self::Output {
201        Self(self.0 * rhs.0)
202    }
203}
204
205impl<F: Neg<Output = F>> Neg for W<F> {
206    type Output = W<F>;
207
208    fn neg(self) -> Self::Output {
209        Self(-self.0)
210    }
211}
212
213impl<'r, F: Add<&'r F, Output = F>> Add<&'r W<F>> for W<F> {
214    type Output = W<F>;
215
216    fn add(self, rhs: &'r W<F>) -> Self::Output {
217        Self(self.0 + &rhs.0)
218    }
219}
220
221impl<'r, F: Mul<&'r F, Output = F>> Mul<&'r W<F>> for W<F> {
222    type Output = W<F>;
223
224    fn mul(self, rhs: &'r W<F>) -> Self::Output {
225        Self(self.0 * &rhs.0)
226    }
227}
228
229impl<'r, F: Sub<&'r F, Output = F>> Sub<&'r W<F>> for W<F> {
230    type Output = W<F>;
231
232    fn sub(self, rhs: &'r W<F>) -> Self::Output {
233        Self(self.0 - &rhs.0)
234    }
235}
236
237impl<F: MulAssign> MulAssign for W<F> {
238    fn mul_assign(&mut self, rhs: Self) {
239        self.0 *= rhs.0
240    }
241}
242
243impl<F: AddAssign> AddAssign for W<F> {
244    fn add_assign(&mut self, rhs: Self) {
245        self.0 += rhs.0
246    }
247}
248
249impl<F: SubAssign> SubAssign for W<F> {
250    fn sub_assign(&mut self, rhs: Self) {
251        self.0 -= rhs.0
252    }
253}
254
255impl<'r, F: MulAssign<&'r F>> MulAssign<&'r W<F>> for W<F> {
256    fn mul_assign(&mut self, rhs: &'r W<F>) {
257        self.0 *= &rhs.0
258    }
259}
260
261impl<'r, F: AddAssign<&'r F>> AddAssign<&'r W<F>> for W<F> {
262    fn add_assign(&mut self, rhs: &'r W<F>) {
263        self.0 += &rhs.0
264    }
265}
266
267impl<'r, F: SubAssign<&'r F>> SubAssign<&'r W<F>> for W<F> {
268    fn sub_assign(&mut self, rhs: &'r W<F>) {
269        self.0 -= &rhs.0
270    }
271}
272
273impl<F: ShlAssign<usize>> ShlAssign<usize> for W<F> {
274    fn shl_assign(&mut self, rhs: usize) {
275        self.0 <<= rhs
276    }
277}
278
279impl<F> ShrAssign<usize> for W<F>
280where
281    [u8; 32]: From<F::Repr>,
282    F: PrimeField,
283{
284    fn shr_assign(&mut self, rhs: usize) {
285        let n = self.to_uint();
286        *self = Self::from_uint_mod_order(&(n >> rhs))
287    }
288}
289
290impl<F: Field> Invert for W<F> {
291    type Output = CtOption<Self>;
292
293    fn invert(&self) -> Self::Output {
294        self.0.invert().map(Self)
295    }
296}
297
298impl<F> elliptic_curve::ops::Reduce<U256> for W<F>
299where
300    F: PrimeField,
301    W<F>: PrimeField,
302{
303    type Bytes = <W<F> as PrimeField>::Repr;
304
305    fn reduce(n: U256) -> Self {
306        Self::from_be_bytes_mod_order(&n.to_be_bytes())
307    }
308
309    fn reduce_bytes(bytes: &Self::Bytes) -> Self {
310        Self::from_be_bytes_mod_order(bytes.as_ref())
311    }
312}
313
314impl<F: Field> Field for W<F> {
315    const ZERO: Self = W(F::ZERO);
316    const ONE: Self = W(F::ONE);
317
318    fn random(rng: impl crate::rand_core::RngCore) -> Self {
319        Self(F::random(rng))
320    }
321
322    fn square(&self) -> Self {
323        Self(self.0.square())
324    }
325
326    fn double(&self) -> Self {
327        Self(self.0.double())
328    }
329
330    fn invert(&self) -> CtOption<Self> {
331        self.0.invert().map(Self)
332    }
333
334    fn sqrt(&self) -> CtOption<Self> {
335        self.0.sqrt().map(Self)
336    }
337
338    fn sqrt_ratio(num: &Self, div: &Self) -> (subtle::Choice, Self) {
339        let (choice, res) = F::sqrt_ratio(num, div);
340        (choice, Self(res))
341    }
342}
343
344impl<F> PrimeField for W<F>
345where
346    F: PrimeField,
347    F::Repr: From<GenericArray<u8, typenum::U32>>,
348    GenericArray<u8, typenum::U32>: From<F::Repr>,
349{
350    type Repr = GenericArray<u8, typenum::U32>;
351
352    const MODULUS: &'static str = F::MODULUS;
353    const NUM_BITS: u32 = F::NUM_BITS;
354    const CAPACITY: u32 = F::CAPACITY;
355    const TWO_INV: Self = Self(F::TWO_INV);
356    const MULTIPLICATIVE_GENERATOR: Self = Self(F::MULTIPLICATIVE_GENERATOR);
357    const S: u32 = F::S;
358    const ROOT_OF_UNITY: Self = Self(F::ROOT_OF_UNITY);
359    const ROOT_OF_UNITY_INV: Self = Self(F::ROOT_OF_UNITY_INV);
360    const DELTA: Self = Self(F::DELTA);
361
362    fn from_repr(repr: Self::Repr) -> CtOption<Self> {
363        F::from_repr(repr.into()).map(Self)
364    }
365
366    fn to_repr(&self) -> Self::Repr {
367        self.0.to_repr().into()
368    }
369
370    fn is_odd(&self) -> subtle::Choice {
371        self.0.is_odd()
372    }
373}
374
375impl<F: Default + Copy> zeroize::DefaultIsZeroes for W<F> {}
376
377impl<F: PrimeField, C: elliptic_curve::Curve> From<ScalarPrimitive<C>> for W<F> {
378    fn from(s: ScalarPrimitive<C>) -> Self {
379        let bytes_be = s.as_uint().to_be_bytes();
380        Self::from_be_bytes_mod_order(bytes_be.as_ref())
381    }
382}
383
384impl<F> From<W<F>> for GenericArray<u8, typenum::U32>
385where
386    W<F>: PrimeField<Repr = GenericArray<u8, typenum::U32>>,
387{
388    fn from(s: W<F>) -> Self {
389        s.to_repr()
390    }
391}
392
393impl<F> IsHigh for W<F>
394where
395    F: PrimeField,
396    W<F>: Sub<Output = W<F>>,
397    U256: From<W<F>>,
398{
399    fn is_high(&self) -> subtle::Choice {
400        let n = Self::ZERO - Self::ONE;
401        let n_2 = U256::from(n) >> 1;
402
403        let s = U256::from(*self);
404
405        s.ct_gt(&n_2)
406    }
407}