decaf377/fields/fq/u64/
wrapper.rs1use ark_ed_on_bls12_377::Fq as ArkworksFq;
2use ark_ff::{biginteger::BigInt, Field, PrimeField};
3use ark_serialize::CanonicalSerialize;
4use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
5
6use super::super::{N_64, N_8};
7
8const N: usize = N_64;
9
10#[derive(Copy, Clone)]
11pub struct Fq(ArkworksFq);
12
13impl PartialEq for Fq {
14 fn eq(&self, other: &Self) -> bool {
15 match (self.is_sentinel(), other.is_sentinel()) {
16 (true, true) => true,
17 (true, false) => false,
18 (false, true) => false,
19 (false, false) => self.0 == other.0,
20 }
21 }
22}
23
24impl Eq for Fq {}
25
26impl zeroize::Zeroize for Fq {
27 fn zeroize(&mut self) {
28 self.0 .0.zeroize()
29 }
30}
31
32impl Fq {
33 pub(crate) fn from_le_limbs(limbs: [u64; N_64]) -> Fq {
34 let mut bytes = [0u8; N_8];
35 for i in 0..N_64 {
36 let this_byte = limbs[i].to_le_bytes();
37 for j in 0..8 {
38 bytes[8 * i + j] = this_byte[j];
39 }
40 }
41
42 Self::from_raw_bytes(&bytes)
43 }
44
45 pub(crate) fn from_raw_bytes(bytes: &[u8; N_8]) -> Fq {
46 Self(ArkworksFq::from_le_bytes_mod_order(bytes))
47 }
48
49 pub(crate) fn to_le_limbs(&self) -> [u64; N_64] {
50 debug_assert!(!self.is_sentinel());
51
52 let le_bytes = self.to_bytes_le();
53 let mut out = [0u64; N_64];
54 for i in 0..N_64 {
55 out[i] = u64::from_le_bytes([
56 le_bytes[8 * i],
57 le_bytes[8 * i + 1],
58 le_bytes[8 * i + 2],
59 le_bytes[8 * i + 3],
60 le_bytes[8 * i + 4],
61 le_bytes[8 * i + 5],
62 le_bytes[8 * i + 6],
63 le_bytes[8 * i + 7],
64 ]);
65 }
66 out
67 }
68
69 pub fn to_bytes_le(&self) -> [u8; N_8] {
70 debug_assert!(!self.is_sentinel());
71
72 let mut bytes = [0u8; 32];
73 self.0
74 .serialize_compressed(&mut bytes[..])
75 .expect("serialization into array should be infallible");
76 bytes
77 }
78
79 pub const fn from_montgomery_limbs(limbs: [u64; N]) -> Fq {
83 Self(ArkworksFq::new_unchecked(BigInt::new(limbs)))
85 }
86
87 pub const ZERO: Self = Self(ArkworksFq::new(BigInt::new([0; N])));
88 pub const ONE: Self = Self(ArkworksFq::new(BigInt::one()));
89
90 pub const SENTINEL: Self = Self::from_montgomery_limbs([u64::MAX; N_64]);
94
95 fn is_sentinel(&self) -> bool {
96 self.0 .0 == Self::SENTINEL.0 .0
97 }
98
99 pub fn square(&self) -> Fq {
100 debug_assert!(!self.is_sentinel());
101 Fq(self.0.square())
102 }
103
104 pub fn inverse(&self) -> Option<Fq> {
105 debug_assert!(!self.is_sentinel());
106
107 if self == &Fq::ZERO {
108 return None;
109 }
110
111 Some(Fq(self.0.inverse()?))
112 }
113
114 pub fn add(self, other: &Fq) -> Fq {
115 debug_assert!(!self.is_sentinel() && !other.is_sentinel());
116 Fq(self.0 + other.0)
117 }
118
119 pub fn sub(self, other: &Fq) -> Fq {
120 debug_assert!(!self.is_sentinel() && !other.is_sentinel());
121 Fq(self.0 - other.0)
122 }
123
124 pub fn mul(self, other: &Fq) -> Fq {
125 debug_assert!(!self.is_sentinel() && !other.is_sentinel());
126 Fq(self.0 * other.0)
127 }
128
129 pub fn neg(self) -> Fq {
130 debug_assert!(!self.is_sentinel());
131 Fq(-self.0)
132 }
133}
134
135impl ConditionallySelectable for Fq {
136 fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
137 let mut out = [0u64; 4];
138 let a_limbs = a.0 .0 .0;
139 let b_limbs = b.0 .0 .0;
140 for i in 0..4 {
141 out[i] = u64::conditional_select(&a_limbs[i], &b_limbs[i], choice);
142 }
143 let bigint = BigInt::new(out);
144 Self(ArkworksFq::new(bigint))
145 }
146}
147
148impl ConstantTimeEq for Fq {
149 fn ct_eq(&self, other: &Fq) -> Choice {
150 let self_limbs = self.0 .0 .0;
151 let other_limbs = other.0 .0 .0;
152 let mut is_equal = true;
153 for i in 0..4 {
154 is_equal &= self_limbs[i] == other_limbs[i];
155 }
156 Choice::from(is_equal as u8)
157 }
158}