1#[cfg(feature = "asm")]
2use crate::bn256::assembly::field_arithmetic_asm;
3#[cfg(not(feature = "asm"))]
4use crate::{arithmetic::macx, field_arithmetic, field_specific};
5
6#[cfg(feature = "bn256-table")]
7#[rustfmt::skip]
8mod table;
9#[cfg(feature = "bn256-table")]
10#[cfg(test)]
11mod table_tests;
12
13#[cfg(feature = "bn256-table")]
14pub use table::FR_TABLE;
17
18#[cfg(not(feature = "bn256-table"))]
19use crate::impl_from_u64;
20
21use crate::arithmetic::{adc, bigint_geq, mac, sbb};
22use crate::extend_field_legendre;
23use crate::ff::{FromUniformBytes, PrimeField, WithSmallOrderMulGroup};
24use crate::{
25 field_bits, field_common, impl_add_binop_specify_output, impl_binops_additive,
26 impl_binops_additive_specify_output, impl_binops_multiplicative,
27 impl_binops_multiplicative_mixed, impl_sub_binop_specify_output, impl_sum_prod,
28};
29use core::convert::TryInto;
30use core::fmt;
31use core::ops::{Add, Mul, Neg, Sub};
32use rand::RngCore;
33use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
34
35#[derive(Clone, Copy, PartialEq, Eq, Hash)]
44pub struct Fr(pub(crate) [u64; 4]);
45
46#[cfg(feature = "derive_serde")]
47crate::serialize_deserialize_32_byte_primefield!(Fr);
48
49const MODULUS: Fr = Fr([
52 0x43e1f593f0000001,
53 0x2833e84879b97091,
54 0xb85045b68181585d,
55 0x30644e72e131a029,
56]);
57
58#[cfg(not(target_pointer_width = "64"))]
60const MODULUS_LIMBS_32: [u32; 8] = [
61 0xf000_0001,
62 0x43e1_f593,
63 0x79b9_7091,
64 0x2833_e848,
65 0x8181_585d,
66 0xb850_45b6,
67 0xe131_a029,
68 0x3064_4e72,
69];
70
71const MODULUS_STR: &str = "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001";
72
73const INV: u64 = 0xc2e1f593efffffff;
75
76const R: Fr = Fr([
79 0xac96341c4ffffffb,
80 0x36fc76959f60cd29,
81 0x666ea36f7879462e,
82 0x0e0a77c19a07df2f,
83]);
84
85const R2: Fr = Fr([
88 0x1bb8e645ae216da7,
89 0x53fe3ab1e35c59e3,
90 0x8c49833d53bb8085,
91 0x0216d0b17f4e44a5,
92]);
93
94const R3: Fr = Fr([
97 0x5e94d8e1b4bf0040,
98 0x2a489cbe1cfbb6b8,
99 0x893cc664a19fcfed,
100 0x0cf8594b7fcc657c,
101]);
102
103const GENERATOR: Fr = Fr::from_raw([0x07, 0x00, 0x00, 0x00]);
106
107const S: u32 = 28;
108
109const ROOT_OF_UNITY: Fr = Fr::from_raw([
114 0xd34f1ed960c37c9c,
115 0x3215cf6dd39329c8,
116 0x98865ea93dd31f74,
117 0x03ddb9f5166d18b7,
118]);
119
120const TWO_INV: Fr = Fr::from_raw([
122 0xa1f0fac9f8000001,
123 0x9419f4243cdcb848,
124 0xdc2822db40c0ac2e,
125 0x183227397098d014,
126]);
127
128const ROOT_OF_UNITY_INV: Fr = Fr::from_raw([
130 0x0ed3e50a414e6dba,
131 0xb22625f59115aba7,
132 0x1bbe587180f34361,
133 0x048127174daabc26,
134]);
135
136const DELTA: Fr = Fr::from_raw([
139 0x870e56bbe533e9a2,
140 0x5b5f898e5e963f25,
141 0x64ec26aad4c86e71,
142 0x09226b6e22c6f0ca,
143]);
144
145const ZETA: Fr = Fr::from_raw([
147 0xb8ca0b2d36636f23,
148 0xcc37a73fec2bc5e9,
149 0x048b6e193fd84104,
150 0x30644e72e131a029,
151]);
152
153impl_binops_additive!(Fr, Fr);
154impl_binops_multiplicative!(Fr, Fr);
155field_common!(
156 Fr,
157 MODULUS,
158 INV,
159 MODULUS_STR,
160 TWO_INV,
161 ROOT_OF_UNITY_INV,
162 DELTA,
163 ZETA,
164 R,
165 R2,
166 R3
167);
168impl_sum_prod!(Fr);
169extend_field_legendre!(Fr);
170
171#[cfg(not(feature = "bn256-table"))]
172impl_from_u64!(Fr, R2);
173#[cfg(feature = "bn256-table")]
174impl From<u64> for Fr {
184 fn from(val: u64) -> Fr {
185 if val < 65536 {
186 FR_TABLE[val as usize]
187 } else {
188 Fr([val, 0, 0, 0]) * R2
189 }
190 }
191}
192
193#[cfg(not(feature = "asm"))]
194field_arithmetic!(Fr, MODULUS, INV, sparse);
195#[cfg(feature = "asm")]
196field_arithmetic_asm!(Fr, MODULUS, INV);
197
198#[cfg(target_pointer_width = "64")]
199field_bits!(Fr, MODULUS);
200#[cfg(not(target_pointer_width = "64"))]
201field_bits!(Fr, MODULUS, MODULUS_LIMBS_32);
202
203impl Fr {
204 pub const fn size() -> usize {
205 32
206 }
207}
208
209impl ff::Field for Fr {
210 const ZERO: Self = Self::zero();
211 const ONE: Self = Self::one();
212
213 fn random(mut rng: impl RngCore) -> Self {
214 Self::from_u512([
215 rng.next_u64(),
216 rng.next_u64(),
217 rng.next_u64(),
218 rng.next_u64(),
219 rng.next_u64(),
220 rng.next_u64(),
221 rng.next_u64(),
222 rng.next_u64(),
223 ])
224 }
225
226 fn double(&self) -> Self {
227 self.double()
228 }
229
230 #[inline(always)]
231 fn square(&self) -> Self {
232 self.square()
233 }
234
235 fn invert(&self) -> CtOption<Self> {
238 self.invert()
239 }
240
241 fn sqrt(&self) -> CtOption<Self> {
242 const T_MINUS1_OVER2: [u64; 4] = [
244 0xcdcb848a1f0fac9f,
245 0x0c0ac2e9419f4243,
246 0x098d014dc2822db4,
247 0x0000000183227397,
248 ];
249 ff::helpers::sqrt_tonelli_shanks(self, T_MINUS1_OVER2)
250 }
251
252 fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
253 ff::helpers::sqrt_ratio_generic(num, div)
254 }
255}
256
257impl ff::PrimeField for Fr {
258 type Repr = [u8; 32];
259
260 const NUM_BITS: u32 = 254;
261 const CAPACITY: u32 = 253;
262 const MODULUS: &'static str = MODULUS_STR;
263 const MULTIPLICATIVE_GENERATOR: Self = GENERATOR;
264 const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
265 const ROOT_OF_UNITY_INV: Self = ROOT_OF_UNITY_INV;
266 const TWO_INV: Self = TWO_INV;
267 const DELTA: Self = DELTA;
268 const S: u32 = S;
269
270 fn from_repr(repr: Self::Repr) -> CtOption<Self> {
271 let mut tmp = Fr([0, 0, 0, 0]);
272
273 tmp.0[0] = u64::from_le_bytes(repr[0..8].try_into().unwrap());
274 tmp.0[1] = u64::from_le_bytes(repr[8..16].try_into().unwrap());
275 tmp.0[2] = u64::from_le_bytes(repr[16..24].try_into().unwrap());
276 tmp.0[3] = u64::from_le_bytes(repr[24..32].try_into().unwrap());
277
278 let (_, borrow) = sbb(tmp.0[0], MODULUS.0[0], 0);
280 let (_, borrow) = sbb(tmp.0[1], MODULUS.0[1], borrow);
281 let (_, borrow) = sbb(tmp.0[2], MODULUS.0[2], borrow);
282 let (_, borrow) = sbb(tmp.0[3], MODULUS.0[3], borrow);
283
284 let is_some = (borrow as u8) & 1;
288
289 tmp *= &R2;
292
293 CtOption::new(tmp, Choice::from(is_some))
294 }
295
296 fn to_repr(&self) -> Self::Repr {
297 let tmp: [u64; 4] = (*self).into();
298 let mut res = [0; 32];
299 res[0..8].copy_from_slice(&tmp[0].to_le_bytes());
300 res[8..16].copy_from_slice(&tmp[1].to_le_bytes());
301 res[16..24].copy_from_slice(&tmp[2].to_le_bytes());
302 res[24..32].copy_from_slice(&tmp[3].to_le_bytes());
303
304 res
305 }
306
307 fn is_odd(&self) -> Choice {
308 Choice::from(self.to_repr()[0] & 1)
309 }
310}
311
312impl FromUniformBytes<64> for Fr {
313 fn from_uniform_bytes(bytes: &[u8; 64]) -> Self {
316 Self::from_u512([
317 u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
318 u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
319 u64::from_le_bytes(bytes[16..24].try_into().unwrap()),
320 u64::from_le_bytes(bytes[24..32].try_into().unwrap()),
321 u64::from_le_bytes(bytes[32..40].try_into().unwrap()),
322 u64::from_le_bytes(bytes[40..48].try_into().unwrap()),
323 u64::from_le_bytes(bytes[48..56].try_into().unwrap()),
324 u64::from_le_bytes(bytes[56..64].try_into().unwrap()),
325 ])
326 }
327}
328
329impl WithSmallOrderMulGroup<3> for Fr {
330 const ZETA: Self = ZETA;
331}
332
333#[cfg(test)]
334mod test {
335 use crate::serde::SerdeObject;
336
337 use super::*;
338 use ark_std::{end_timer, start_timer};
339 use ff::Field;
340 use rand::SeedableRng;
341 use rand_core::OsRng;
342 use rand_xorshift::XorShiftRng;
343
344 #[test]
345 fn test_sqrt() {
346 let v = (Fr::TWO_INV).square().sqrt().unwrap();
347 assert!(v == Fr::TWO_INV || (-v) == Fr::TWO_INV);
348
349 for _ in 0..10000 {
350 let a = Fr::random(OsRng);
351 let mut b = a;
352 b = b.square();
353
354 let b = b.sqrt().unwrap();
355 let mut negb = b;
356 negb = negb.neg();
357
358 assert!(a == b || a == negb);
359 }
360 }
361
362 #[test]
363 fn test_field() {
364 crate::tests::field::random_field_tests::<Fr>("bn256 scalar".to_string());
365 }
366
367 #[test]
368 fn test_delta() {
369 assert_eq!(Fr::DELTA, GENERATOR.pow([1u64 << Fr::S]));
370 assert_eq!(Fr::DELTA, Fr::MULTIPLICATIVE_GENERATOR.pow([1u64 << Fr::S]));
371 }
372
373 #[test]
374 fn test_from_u512() {
375 assert_eq!(
376 Fr::from_raw([
377 0x7e7140b5196b9e6f,
378 0x9abac9e4157b6172,
379 0xf04bc41062fd7322,
380 0x1185fa9c9fef6326,
381 ]),
382 Fr::from_u512([
383 0xaaaaaaaaaaaaaaaa,
384 0xaaaaaaaaaaaaaaaa,
385 0xaaaaaaaaaaaaaaaa,
386 0xaaaaaaaaaaaaaaaa,
387 0xaaaaaaaaaaaaaaaa,
388 0xaaaaaaaaaaaaaaaa,
389 0xaaaaaaaaaaaaaaaa,
390 0xaaaaaaaaaaaaaaaa
391 ])
392 );
393 }
394
395 #[test]
396 fn test_conversion() {
397 crate::tests::field::random_conversion_tests::<Fr>("fr".to_string());
398 }
399
400 #[test]
401 #[cfg(feature = "bits")]
402 fn test_bits() {
403 crate::tests::field::random_bits_tests::<Fr>("fr".to_string());
404 }
405
406 #[test]
407 fn test_serialization() {
408 crate::tests::field::random_serialization_test::<Fr>("fr".to_string());
409 #[cfg(feature = "derive_serde")]
410 crate::tests::field::random_serde_test::<Fr>("fr".to_string());
411 }
412
413 fn is_less_than(x: &[u64; 4], y: &[u64; 4]) -> bool {
414 match x[3].cmp(&y[3]) {
415 core::cmp::Ordering::Less => return true,
416 core::cmp::Ordering::Greater => return false,
417 _ => {}
418 }
419 match x[2].cmp(&y[2]) {
420 core::cmp::Ordering::Less => return true,
421 core::cmp::Ordering::Greater => return false,
422 _ => {}
423 }
424 match x[1].cmp(&y[1]) {
425 core::cmp::Ordering::Less => return true,
426 core::cmp::Ordering::Greater => return false,
427 _ => {}
428 }
429 x[0].lt(&y[0])
430 }
431
432 #[test]
433 fn test_serialization_check() {
434 let mut rng = XorShiftRng::from_seed([
435 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06,
436 0xbc, 0xe5,
437 ]);
438 let start = start_timer!(|| "serialize fr");
439 for _ in 0..1000000 {
441 let rand_word = [(); 4].map(|_| rng.next_u64());
442 let a = Fr(rand_word);
443 let rand_bytes = a.to_raw_bytes();
444 match is_less_than(&rand_word, &MODULUS.0) {
445 false => {
446 assert!(Fr::from_raw_bytes(&rand_bytes).is_none());
447 }
448 _ => {
449 assert_eq!(Fr::from_raw_bytes(&rand_bytes), Some(a));
450 }
451 }
452 }
453 end_timer!(start);
454 }
455
456 #[test]
457 fn bench_fr_from_u16() {
458 let repeat = 10000000;
459 let mut rng = ark_std::test_rng();
460 let base = (0..repeat).map(|_| (rng.next_u32() % (1 << 16)) as u64);
461
462 let timer = start_timer!(|| format!("generate {repeat} Bn256 scalar field elements"));
463 let _res: Vec<_> = base.map(Fr::from).collect();
464
465 end_timer!(timer);
466 }
467
468 #[test]
469 fn test_quadratic_residue() {
470 crate::tests::field::random_quadratic_residue_test::<Fr>();
471 }
472}