1use cfg_if::cfg_if;
2use rand_core::CryptoRngCore;
3
4use crate::EncodingError;
5
6#[cfg(feature = "arkworks")]
7pub mod arkworks;
8mod ops;
9pub mod u32;
10
11#[cfg(feature = "arkworks")]
13pub mod u64;
14
15cfg_if! {
16 if #[cfg(feature = "arkworks")] {
17 pub type Fr = u64::Fr;
18 } else {
19 pub type Fr = u32::Fr;
20 }
21}
22
23const B: usize = 251;
24const N_8: usize = (B + 7) / 8;
25const N_32: usize = (B + 31) / 32;
26const N_64: usize = (B + 63) / 64;
27
28impl Fr {
29 pub const MODULUS_LIMBS: [u64; N_64] = [
30 13356249993388743167,
31 5950279507993463550,
32 10965441865914903552,
33 336320092672043349,
34 ];
35
36 pub const MODULUS_MINUS_ONE_DIV_TWO_LIMBS: [u64; N_64] = [
37 6678124996694371583,
38 2975139753996731775,
39 14706092969812227584,
40 168160046336021674,
41 ];
42
43 pub const MODULUS_BIT_SIZE: u32 = 0xfb;
44
45 pub const TRACE_LIMBS: [u64; N_64] = [
46 4478124994494371583,
47 2975139753994731775,
48 14704092949812227584,
49 148140044334021474,
50 ];
51
52 pub const TRACE_MINUS_ONE_DIV_TWO_LIMBS: [u64; N_64] = [
53 12542434535201941599,
54 1487549874998345887,
55 7353044484904113792,
56 84080023148010837,
57 ];
58
59 pub const TWO_ADICITY: u32 = 0x1;
60
61 pub const MULTIPLICATIVE_GENERATOR: Self = Self::from_montgomery_limbs([
62 11289572479485143824,
63 11383437349941080925,
64 2288212753973340071,
65 82014974407880291,
66 ]);
67
68 pub const TWO_ADIC_ROOT_OF_UNITY: Self = Self::from_montgomery_limbs([
69 15170730741708341141,
70 13470723484578117817,
71 12803492244414043445,
72 50841023252832411,
73 ]);
74
75 pub const FIELD_SIZE_POWER_OF_TWO: Self = Self::from_montgomery_limbs([
76 3987543627614508126,
77 17742427666091596403,
78 14557327917022607905,
79 322810149704226881,
80 ]);
81
82 pub fn from_le_bytes_mod_order(bytes: &[u8]) -> Self {
83 bytes
84 .chunks(N_8)
85 .map(|x| {
86 let mut padded = [0u8; N_8];
87 padded[..x.len()].copy_from_slice(x);
88 Self::from_raw_bytes(&padded)
89 }) .rev()
91 .fold(Self::ZERO, |acc, x| {
92 acc * (Self::FIELD_SIZE_POWER_OF_TWO) + x
93 }) }
95
96 pub fn from_bytes_checked(bytes: &[u8; N_8]) -> Result<Self, EncodingError> {
101 let reduced = Self::from_raw_bytes(bytes);
102 if reduced.to_bytes_le() == *bytes {
103 Ok(reduced)
104 } else {
105 Err(EncodingError::InvalidEncoding)
106 }
107 }
108
109 pub fn to_bytes(&self) -> [u8; N_8] {
110 self.to_bytes_le()
111 }
112
113 pub fn rand<R: CryptoRngCore>(rng: &mut R) -> Self {
115 let bytes = {
117 let mut out = [0u8; N_8 + 16];
118 rng.fill_bytes(&mut out);
119 out
120 };
121 Self::from_le_bytes_mod_order(&bytes)
122 }
123}
124
125#[cfg(test)]
126mod test {
127 use super::*;
128
129 #[test]
130 fn test_from_bytes_checked() {
131 assert_eq!(Fr::from_bytes_checked(&[0; N_8]), Ok(Fr::ZERO));
132 assert!(Fr::from_bytes_checked(&[0xFF; N_8]).is_err());
133 }
134}