halo2curves_axiom/secp256k1/
fp.rs

1use crate::arithmetic::{adc, bigint_geq, mac, macx, sbb};
2use crate::extend_field_legendre;
3use crate::ff::{FromUniformBytes, PrimeField, WithSmallOrderMulGroup};
4use crate::{
5    field_arithmetic, field_bits, field_common, field_specific, impl_add_binop_specify_output,
6    impl_binops_additive, impl_binops_additive_specify_output, impl_binops_multiplicative,
7    impl_binops_multiplicative_mixed, impl_from_u64, impl_sub_binop_specify_output, impl_sum_prod,
8};
9use core::convert::TryInto;
10use core::fmt;
11use core::ops::{Add, Mul, Neg, Sub};
12use rand::RngCore;
13use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
14
15/// This represents an element of $\mathbb{F}_p$ where
16///
17/// `p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f`
18///
19/// is the base field of the secp256k1 curve.
20// The internal representation of this type is four 64-bit unsigned
21// integers in little-endian order. `Fp` values are always in
22// Montgomery form; i.e., Fp(a) = aR mod p, with R = 2^256.
23#[derive(Clone, Copy, PartialEq, Eq, Hash)]
24pub struct Fp(pub(crate) [u64; 4]);
25
26#[cfg(feature = "derive_serde")]
27crate::serialize_deserialize_32_byte_primefield!(Fp);
28
29/// Constant representing the modulus
30/// p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
31const MODULUS: Fp = Fp([
32    0xfffffffefffffc2f,
33    0xffffffffffffffff,
34    0xffffffffffffffff,
35    0xffffffffffffffff,
36]);
37
38/// Constant representing the multiplicative generator of the modulus.
39/// It's derived with SageMath with: `GF(MODULUS).primitive_element()`.
40const MULTIPLICATIVE_GENERATOR: Fp = Fp::from_raw([0x03, 0x00, 0x00, 0x00]);
41
42/// The modulus as u32 limbs.
43#[cfg(not(target_pointer_width = "64"))]
44const MODULUS_LIMBS_32: [u32; 8] = [
45    0xffff_fc2f,
46    0xffff_fffe,
47    0xffff_ffff,
48    0xffff_ffff,
49    0xffff_ffff,
50    0xffff_ffff,
51    0xffff_ffff,
52    0xffff_ffff,
53];
54
55/// Constant representing the modolus as static str
56const MODULUS_STR: &str = "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f";
57
58/// INV = -(p^{-1} mod 2^64) mod 2^64
59const INV: u64 = 0xd838091dd2253531;
60
61/// R = 2^256 mod p
62/// 0x1000003d1
63const R: Fp = Fp([0x1000003d1, 0, 0, 0]);
64
65/// R^2 = 2^512 mod p
66/// 0x1000007a2000e90a1
67const R2: Fp = Fp([0x000007a2000e90a1, 0x1, 0, 0]);
68
69/// R^3 = 2^768 mod p
70/// 0x100000b73002bb1e33795f671
71const R3: Fp = Fp([0x002bb1e33795f671, 0x100000b73, 0, 0]);
72
73/// 1 / 2 mod p
74const TWO_INV: Fp = Fp::from_raw([
75    0xffffffff7ffffe18,
76    0xffffffffffffffff,
77    0xffffffffffffffff,
78    0x7fffffffffffffff,
79]);
80
81const ZETA: Fp = Fp::from_raw([
82    0xc1396c28719501ee,
83    0x9cf0497512f58995,
84    0x6e64479eac3434e9,
85    0x7ae96a2b657c0710,
86]);
87
88/// Generator of the t-order multiplicative subgroup.
89/// Computed by exponentiating Self::MULTIPLICATIVE_GENERATOR by 2^s, where s is Self::S.
90/// `0x0000000000000000000000000000000000000000000000000000000000000009`.
91const DELTA: Fp = Fp([0x900002259u64, 0, 0, 0]);
92
93/// Implementations of this trait MUST ensure that this is the generator used to derive Self::ROOT_OF_UNITY.
94/// Derived from:
95/// ```ignore
96/// Zp(Zp(mul_generator)^t) where t = (modulus - 1 )/ 2
97/// 115792089237316195423570985008687907853269984665640564039457584007908834671662
98/// ```
99const ROOT_OF_UNITY: Fp = Fp([
100    0xfffffffdfffff85eu64,
101    0xffffffffffffffffu64,
102    0xffffffffffffffffu64,
103    0xffffffffffffffffu64,
104]);
105
106/// Inverse of [`ROOT_OF_UNITY`].
107const ROOT_OF_UNITY_INV: Fp = Fp([
108    0xfffffffdfffff85eu64,
109    0xffffffffffffffffu64,
110    0xffffffffffffffffu64,
111    0xffffffffffffffffu64,
112]);
113
114impl_binops_additive!(Fp, Fp);
115impl_binops_multiplicative!(Fp, Fp);
116field_common!(
117    Fp,
118    MODULUS,
119    INV,
120    MODULUS_STR,
121    TWO_INV,
122    ROOT_OF_UNITY_INV,
123    DELTA,
124    ZETA,
125    R,
126    R2,
127    R3
128);
129impl_from_u64!(Fp, R2);
130field_arithmetic!(Fp, MODULUS, INV, dense);
131impl_sum_prod!(Fp);
132
133#[cfg(target_pointer_width = "64")]
134field_bits!(Fp, MODULUS);
135#[cfg(not(target_pointer_width = "64"))]
136field_bits!(Fp, MODULUS, MODULUS_LIMBS_32);
137
138impl Fp {
139    pub const fn size() -> usize {
140        32
141    }
142}
143
144impl ff::Field for Fp {
145    const ZERO: Self = Self::zero();
146    const ONE: Self = Self::one();
147
148    fn random(mut rng: impl RngCore) -> Self {
149        Self::from_u512([
150            rng.next_u64(),
151            rng.next_u64(),
152            rng.next_u64(),
153            rng.next_u64(),
154            rng.next_u64(),
155            rng.next_u64(),
156            rng.next_u64(),
157            rng.next_u64(),
158        ])
159    }
160
161    fn double(&self) -> Self {
162        self.double()
163    }
164
165    #[inline(always)]
166    fn square(&self) -> Self {
167        self.square()
168    }
169
170    /// Computes the square root of this element, if it exists.
171    fn sqrt(&self) -> CtOption<Self> {
172        let tmp = self.pow([
173            0xffffffffbfffff0c,
174            0xffffffffffffffff,
175            0xffffffffffffffff,
176            0x3fffffffffffffff,
177        ]);
178
179        CtOption::new(tmp, tmp.square().ct_eq(self))
180    }
181
182    /// Returns the multiplicative inverse of the
183    /// element. If it is zero, the method fails.
184    fn invert(&self) -> CtOption<Self> {
185        self.invert()
186    }
187
188    fn pow_vartime<S: AsRef<[u64]>>(&self, exp: S) -> Self {
189        let mut res = Self::one();
190        let mut found_one = false;
191        for e in exp.as_ref().iter().rev() {
192            for i in (0..64).rev() {
193                if found_one {
194                    res = res.square();
195                }
196
197                if ((*e >> i) & 1) == 1 {
198                    found_one = true;
199                    res *= self;
200                }
201            }
202        }
203        res
204    }
205
206    fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
207        ff::helpers::sqrt_ratio_generic(num, div)
208    }
209}
210
211impl ff::PrimeField for Fp {
212    type Repr = [u8; 32];
213
214    const MODULUS: &'static str = MODULUS_STR;
215    const MULTIPLICATIVE_GENERATOR: Self = MULTIPLICATIVE_GENERATOR;
216    const TWO_INV: Self = TWO_INV;
217    const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
218    const ROOT_OF_UNITY_INV: Self = ROOT_OF_UNITY_INV;
219    const DELTA: Self = DELTA;
220    const NUM_BITS: u32 = 256;
221    const CAPACITY: u32 = 255;
222    const S: u32 = 1;
223
224    fn from_repr(repr: Self::Repr) -> CtOption<Self> {
225        let mut tmp = Fp([0, 0, 0, 0]);
226
227        tmp.0[0] = u64::from_le_bytes(repr[0..8].try_into().unwrap());
228        tmp.0[1] = u64::from_le_bytes(repr[8..16].try_into().unwrap());
229        tmp.0[2] = u64::from_le_bytes(repr[16..24].try_into().unwrap());
230        tmp.0[3] = u64::from_le_bytes(repr[24..32].try_into().unwrap());
231
232        // Try to subtract the modulus
233        let (_, borrow) = sbb(tmp.0[0], MODULUS.0[0], 0);
234        let (_, borrow) = sbb(tmp.0[1], MODULUS.0[1], borrow);
235        let (_, borrow) = sbb(tmp.0[2], MODULUS.0[2], borrow);
236        let (_, borrow) = sbb(tmp.0[3], MODULUS.0[3], borrow);
237
238        // If the element is smaller than MODULUS then the
239        // subtraction will underflow, producing a borrow value
240        // of 0xffff...ffff. Otherwise, it'll be zero.
241        let is_some = (borrow as u8) & 1;
242
243        // Convert to Montgomery form by computing
244        // (a.R^0 * R^2) / R = a.R
245        tmp *= &R2;
246
247        CtOption::new(tmp, Choice::from(is_some))
248    }
249
250    fn to_repr(&self) -> Self::Repr {
251        let tmp: [u64; 4] = (*self).into();
252        let mut res = [0; 32];
253        res[0..8].copy_from_slice(&tmp[0].to_le_bytes());
254        res[8..16].copy_from_slice(&tmp[1].to_le_bytes());
255        res[16..24].copy_from_slice(&tmp[2].to_le_bytes());
256        res[24..32].copy_from_slice(&tmp[3].to_le_bytes());
257
258        res
259    }
260
261    fn from_u128(v: u128) -> Self {
262        Self::from_raw([v as u64, (v >> 64) as u64, 0, 0])
263    }
264
265    fn is_odd(&self) -> Choice {
266        Choice::from(self.to_repr()[0] & 1)
267    }
268}
269
270impl FromUniformBytes<64> for Fp {
271    /// Converts a 512-bit little endian integer into
272    /// an `Fp` by reducing by the modulus.
273    fn from_uniform_bytes(bytes: &[u8; 64]) -> Self {
274        Self::from_u512([
275            u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
276            u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
277            u64::from_le_bytes(bytes[16..24].try_into().unwrap()),
278            u64::from_le_bytes(bytes[24..32].try_into().unwrap()),
279            u64::from_le_bytes(bytes[32..40].try_into().unwrap()),
280            u64::from_le_bytes(bytes[40..48].try_into().unwrap()),
281            u64::from_le_bytes(bytes[48..56].try_into().unwrap()),
282            u64::from_le_bytes(bytes[56..64].try_into().unwrap()),
283        ])
284    }
285}
286
287impl WithSmallOrderMulGroup<3> for Fp {
288    const ZETA: Self = ZETA;
289}
290
291extend_field_legendre!(Fp);
292
293#[cfg(test)]
294mod test {
295    use super::*;
296    use ff::Field;
297    use rand_core::OsRng;
298
299    #[test]
300    fn test_sqrt() {
301        // NB: TWO_INV is standing in as a "random" field element
302        let v = (Fp::TWO_INV).square().sqrt().unwrap();
303        assert!(v == Fp::TWO_INV || (-v) == Fp::TWO_INV);
304
305        for _ in 0..10000 {
306            let a = Fp::random(OsRng);
307            let mut b = a;
308            b = b.square();
309
310            let b = b.sqrt().unwrap();
311            let mut negb = b;
312            negb = negb.neg();
313
314            assert!(a == b || a == negb);
315        }
316    }
317
318    #[test]
319    fn test_constants() {
320        assert_eq!(
321            Fp::MODULUS,
322            "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
323        );
324
325        assert_eq!(Fp::from(2) * Fp::TWO_INV, Fp::ONE);
326    }
327
328    #[test]
329    fn test_delta() {
330        assert_eq!(Fp::DELTA, MULTIPLICATIVE_GENERATOR.pow([1u64 << Fp::S]));
331    }
332
333    #[test]
334    fn test_root_of_unity() {
335        assert_eq!(Fp::ROOT_OF_UNITY.pow_vartime([1 << Fp::S]), Fp::one());
336    }
337
338    #[test]
339    fn test_inv_root_of_unity() {
340        assert_eq!(Fp::ROOT_OF_UNITY_INV, Fp::ROOT_OF_UNITY.invert().unwrap());
341    }
342
343    #[test]
344    fn test_field() {
345        crate::tests::field::random_field_tests::<Fp>("secp256k1 base".to_string());
346    }
347
348    #[test]
349    fn test_conversion() {
350        crate::tests::field::random_conversion_tests::<Fp>("secp256k1 base".to_string());
351    }
352
353    #[test]
354    #[cfg(feature = "bits")]
355    fn test_bits() {
356        crate::tests::field::random_bits_tests::<Fp>("secp256k1 base".to_string());
357    }
358
359    #[test]
360    fn test_serialization() {
361        crate::tests::field::random_serialization_test::<Fp>("secp256k1 base".to_string());
362        #[cfg(feature = "derive_serde")]
363        crate::tests::field::random_serde_test::<Fp>("secp256k1 base".to_string());
364    }
365
366    #[test]
367    fn test_quadratic_residue() {
368        crate::tests::field::random_quadratic_residue_test::<Fp>();
369    }
370}