Skip to main content

primitives/algebra/field/
subfield_element.rs

1use std::{
2    fmt::{Display, Formatter, Result as FmtResult},
3    iter::{Product, Sum},
4    ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign},
5};
6
7use derive_more::derive::{AsMut, AsRef};
8use ff::Field;
9use hybrid_array::Array;
10use num_traits::{One, Zero};
11use rand::RngCore;
12use serde::{Deserialize, Serialize};
13use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
14use wincode::{SchemaRead, SchemaWrite};
15
16use crate::{
17    algebra::{
18        field::{
19            binary::Gf2_128,
20            mersenne::Mersenne107,
21            ByteSize,
22            FieldElement,
23            FieldExtension,
24            PrimeFieldExtension,
25        },
26        ops::{AccReduce, DefaultDotProduct, IntoWide, MulAccReduce, ReduceWide},
27        uniform_bytes::FromUniformBytes,
28    },
29    errors::PrimitiveError,
30    random::{CryptoRngCore, Random, RandomNonZero},
31    sharing::unauthenticated::AdditiveShares,
32    types::{HeapArray, Positive},
33};
34
35pub type Bit = SubfieldElement<Gf2_128>;
36pub type Bits<N> = HeapArray<Bit, N>;
37
38pub type Mersenne107Element = SubfieldElement<Mersenne107>;
39pub type Mersenne107Elements<N> = HeapArray<Mersenne107Element, N>;
40
41/// A subfield element wrapper.
42#[derive(
43    Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Hash, AsRef, AsMut, SchemaRead, SchemaWrite,
44)]
45#[repr(transparent)]
46pub struct SubfieldElement<F: FieldExtension>(pub F::Subfield);
47
48// SAFETY: SubfieldElement<F> is #[repr(transparent)] over F::Subfield.
49unsafe impl<F: FieldExtension> bytemuck::TransparentWrapper<F::Subfield> for SubfieldElement<F> {}
50
51impl<F: FieldExtension> SubfieldElement<F> {
52    /// Construct a subfield element from an inner subfield element
53    #[inline]
54    pub fn new(inner: F::Subfield) -> Self {
55        SubfieldElement(inner)
56    }
57
58    /// Get the inner value of the subfield element
59    #[inline]
60    pub fn inner(&self) -> F::Subfield {
61        self.0
62    }
63
64    /// Compute the exponentiation of the given subfield element
65    #[inline]
66    pub fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
67        SubfieldElement::new(self.0.pow(exp))
68    }
69
70    /// Construct a subfield element from the given bytes
71    #[inline]
72    pub fn from_be_bytes(bytes: &[u8]) -> Result<SubfieldElement<F>, PrimitiveError> {
73        let mut bytes = bytes.to_vec();
74        bytes.reverse();
75        Ok(SubfieldElement(
76            F::Subfield::from_le_bytes(&bytes).ok_or_else(|| {
77                PrimitiveError::DeserializationFailed(
78                    "Invalid subfield element encoding".to_string(),
79                )
80            })?,
81        ))
82    }
83
84    pub fn from_le_bytes(bytes: &[u8]) -> Result<SubfieldElement<F>, PrimitiveError> {
85        Ok(SubfieldElement(
86            F::Subfield::from_le_bytes(bytes).ok_or_else(|| {
87                PrimitiveError::DeserializationFailed(
88                    "Invalid subfield element encoding".to_string(),
89                )
90            })?,
91        ))
92    }
93
94    /// Convert the subfield element to little-endian bytes
95    #[inline]
96    pub fn to_le_bytes(&self) -> Array<u8, ByteSize<F::Subfield>> {
97        self.0.to_le_bytes()
98    }
99
100    /// Convert the subfield element to big-endian bytes
101    #[inline]
102    pub fn to_be_bytes(&self) -> Array<u8, ByteSize<F::Subfield>> {
103        let mut rev = self.0.to_le_bytes();
104        rev.as_mut().reverse();
105        rev
106    }
107
108    pub fn to_biguint(&self) -> num_bigint::BigUint {
109        num_bigint::BigUint::from_bytes_le(self.to_le_bytes().as_ref())
110    }
111
112    pub fn to_bigint(&self) -> num_bigint::BigInt {
113        self.to_biguint().into()
114    }
115
116    pub fn random_elements<M: Positive>(rng: impl CryptoRngCore) -> HeapArray<Self, M> {
117        F::Subfield::random_array(rng).wrap_transparent()
118    }
119}
120
121impl<F: FieldExtension> Random for SubfieldElement<F> {
122    fn random(mut rng: impl CryptoRngCore) -> Self {
123        SubfieldElement(Random::random(&mut rng))
124    }
125}
126
127impl<F: FieldExtension> RandomNonZero for SubfieldElement<F> {
128    fn random_non_zero(mut rng: impl CryptoRngCore) -> Result<Self, PrimitiveError> {
129        Ok(SubfieldElement(F::Subfield::random_non_zero(&mut rng)?))
130    }
131}
132
133impl<F: FieldExtension> Default for SubfieldElement<F> {
134    fn default() -> Self {
135        Self::zero()
136    }
137}
138
139impl<F: FieldExtension> Serialize for SubfieldElement<F> {
140    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
141        let bytes = self
142            .to_le_bytes()
143            .into_iter()
144            .collect::<Array<u8, ByteSize<F::Subfield>>>();
145        serde_bytes::serialize(AsRef::<[u8]>::as_ref(&bytes), serializer)
146    }
147}
148
149impl<'de, F: FieldExtension> Deserialize<'de> for SubfieldElement<F> {
150    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
151        let bytes: &[u8] = serde_bytes::deserialize(deserializer)?;
152        let field_elem = SubfieldElement::from_le_bytes(bytes).map_err(|err| {
153            serde::de::Error::custom(format!("Failed to deserialize field element: {err:?}"))
154        })?;
155        Ok(field_elem)
156    }
157}
158
159impl<F: FieldExtension> Display for SubfieldElement<F> {
160    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
161        write!(f, "{self:?}")
162    }
163}
164
165// --------------
166// | Arithmetic |
167// --------------
168
169// === Addition === //
170
171#[macros::op_variants(owned, borrowed, flipped_commutative)]
172impl<F: FieldExtension> Add<&SubfieldElement<F>> for SubfieldElement<F> {
173    type Output = SubfieldElement<F>;
174
175    #[inline]
176    fn add(self, rhs: &SubfieldElement<F>) -> Self::Output {
177        SubfieldElement(self.0 + rhs.0)
178    }
179}
180
181#[macros::op_variants(owned)]
182impl<'a, F: FieldExtension> AddAssign<&'a SubfieldElement<F>> for SubfieldElement<F> {
183    #[inline]
184    fn add_assign(&mut self, rhs: &'a SubfieldElement<F>) {
185        *self = *self + rhs;
186    }
187}
188
189// === Subtraction === //
190
191#[macros::op_variants(owned, borrowed, flipped)]
192impl<F: FieldExtension> Sub<&SubfieldElement<F>> for SubfieldElement<F> {
193    type Output = SubfieldElement<F>;
194
195    #[inline]
196    fn sub(self, rhs: &SubfieldElement<F>) -> Self::Output {
197        SubfieldElement(self.0 - rhs.0)
198    }
199}
200
201#[macros::op_variants(owned)]
202impl<'a, F: FieldExtension> SubAssign<&'a SubfieldElement<F>> for SubfieldElement<F> {
203    #[inline]
204    fn sub_assign(&mut self, rhs: &'a SubfieldElement<F>) {
205        *self = *self - rhs;
206    }
207}
208
209// === Multiplication === //
210
211#[macros::op_variants(owned, borrowed, flipped_commutative)]
212impl<F: FieldExtension> Mul<&SubfieldElement<F>> for SubfieldElement<F> {
213    type Output = SubfieldElement<F>;
214
215    #[inline]
216    fn mul(self, rhs: &SubfieldElement<F>) -> Self::Output {
217        SubfieldElement(self.0 * rhs.0)
218    }
219}
220
221#[macros::op_variants(owned, borrowed, flipped_commutative)]
222impl<F: FieldExtension> Mul<&FieldElement<F>> for SubfieldElement<F> {
223    type Output = FieldElement<F>;
224
225    #[inline]
226    fn mul(self, rhs: &FieldElement<F>) -> Self::Output {
227        FieldElement(rhs.0 * self.0)
228    }
229}
230
231#[macros::op_variants(owned)]
232impl<'a, F: FieldExtension> MulAssign<&'a SubfieldElement<F>> for SubfieldElement<F> {
233    #[inline]
234    fn mul_assign(&mut self, rhs: &'a SubfieldElement<F>) {
235        *self = *self * rhs;
236    }
237}
238
239// === Negation === //
240
241#[macros::op_variants(borrowed)]
242impl<F: FieldExtension> Neg for SubfieldElement<F> {
243    type Output = SubfieldElement<F>;
244
245    #[inline]
246    fn neg(self) -> Self::Output {
247        SubfieldElement(-self.0)
248    }
249}
250
251// === Division === //
252
253#[macros::op_variants(owned, borrowed, flipped)]
254impl<F: FieldExtension> Div<&SubfieldElement<F>> for SubfieldElement<F> {
255    type Output = CtOption<SubfieldElement<F>>;
256
257    #[inline]
258    fn div(self, rhs: &SubfieldElement<F>) -> Self::Output {
259        rhs.0.invert().map(|inv| SubfieldElement(self.0 * inv))
260    }
261}
262
263// === Equality === //
264
265impl<F: FieldExtension> ConstantTimeEq for SubfieldElement<F> {
266    #[inline]
267    fn ct_eq(&self, other: &Self) -> Choice {
268        self.0.ct_eq(&other.0)
269    }
270}
271
272impl<F: FieldExtension> ConditionallySelectable for SubfieldElement<F> {
273    #[inline]
274    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
275        let selected = F::Subfield::conditional_select(&a.0, &b.0, choice);
276        SubfieldElement(selected)
277    }
278}
279
280// === Other === //
281
282impl<F: FieldExtension> AdditiveShares for SubfieldElement<F> {}
283
284// ---------------
285// | Conversions |
286// ---------------
287
288impl<F: FieldExtension> From<bool> for SubfieldElement<F> {
289    #[inline]
290    fn from(value: bool) -> Self {
291        SubfieldElement(F::Subfield::from(value as u64))
292    }
293}
294
295impl<F: FieldExtension> From<u8> for SubfieldElement<F> {
296    #[inline]
297    fn from(value: u8) -> Self {
298        SubfieldElement(F::Subfield::from(value as u64))
299    }
300}
301
302impl<F: FieldExtension> From<u16> for SubfieldElement<F> {
303    #[inline]
304    fn from(value: u16) -> Self {
305        SubfieldElement(F::Subfield::from(value as u64))
306    }
307}
308
309impl<F: FieldExtension> From<u32> for SubfieldElement<F> {
310    #[inline]
311    fn from(value: u32) -> Self {
312        SubfieldElement(F::Subfield::from(value as u64))
313    }
314}
315
316impl<F: FieldExtension> From<u64> for SubfieldElement<F> {
317    #[inline]
318    fn from(value: u64) -> Self {
319        SubfieldElement(F::Subfield::from(value))
320    }
321}
322
323impl<F: FieldExtension> From<u128> for SubfieldElement<F> {
324    #[inline]
325    fn from(value: u128) -> Self {
326        SubfieldElement(F::Subfield::from(value))
327    }
328}
329
330impl<F: PrimeFieldExtension> From<FieldElement<F>> for SubfieldElement<F> {
331    #[inline]
332    fn from(value: FieldElement<F>) -> Self {
333        SubfieldElement(value.0)
334    }
335}
336
337// -------------------
338// | Iterator Traits |
339// -------------------
340
341impl<F: FieldExtension> Sum for SubfieldElement<F> {
342    #[inline]
343    fn sum<I: Iterator<Item = SubfieldElement<F>>>(iter: I) -> Self {
344        let tmp = iter.fold(<F::Subfield as AccReduce>::zero_wide(), |mut acc, x| {
345            F::Subfield::acc(&mut acc, x.0);
346            acc
347        });
348        SubfieldElement(F::Subfield::reduce_mod_order(tmp))
349    }
350}
351
352impl<'a, F: FieldExtension> Sum<&'a SubfieldElement<F>> for SubfieldElement<F> {
353    #[inline]
354    fn sum<I: Iterator<Item = &'a SubfieldElement<F>>>(iter: I) -> Self {
355        let tmp = iter.fold(<F::Subfield as AccReduce>::zero_wide(), |mut acc, x| {
356            F::Subfield::acc(&mut acc, x.0);
357            acc
358        });
359        SubfieldElement(F::Subfield::reduce_mod_order(tmp))
360    }
361}
362
363impl<F: FieldExtension> Product for SubfieldElement<F> {
364    #[inline]
365    fn product<I: Iterator<Item = SubfieldElement<F>>>(iter: I) -> Self {
366        iter.fold(SubfieldElement::one(), |acc, x| acc * x)
367    }
368}
369
370impl<'a, F: FieldExtension> Product<&'a SubfieldElement<F>> for SubfieldElement<F> {
371    #[inline]
372    fn product<I: Iterator<Item = &'a SubfieldElement<F>>>(iter: I) -> Self {
373        iter.fold(SubfieldElement::one(), |acc, x| acc * x)
374    }
375}
376
377impl<F: FieldExtension> FromUniformBytes for SubfieldElement<F> {
378    type UniformBytes = <F::Subfield as FromUniformBytes>::UniformBytes;
379
380    fn from_uniform_bytes(bytes: &Array<u8, Self::UniformBytes>) -> Self {
381        Self(F::Subfield::from_uniform_bytes(bytes))
382    }
383}
384
385// Dot product: Subfield<F> x Subfield<F>
386impl<F: FieldExtension> IntoWide<<F::Subfield as MulAccReduce>::WideType> for SubfieldElement<F> {
387    #[inline]
388    fn to_wide(&self) -> <F::Subfield as MulAccReduce>::WideType {
389        <F::Subfield as MulAccReduce>::to_wide(&self.0)
390    }
391
392    #[inline]
393    fn zero_wide() -> <F::Subfield as MulAccReduce>::WideType {
394        <F::Subfield as MulAccReduce>::zero_wide()
395    }
396}
397
398impl<F: FieldExtension> ReduceWide<<F::Subfield as MulAccReduce>::WideType> for SubfieldElement<F> {
399    #[inline]
400    fn reduce_mod_order(a: <F::Subfield as MulAccReduce>::WideType) -> Self {
401        Self(F::Subfield::reduce_mod_order(a))
402    }
403}
404
405impl<F: FieldExtension> MulAccReduce for SubfieldElement<F> {
406    type WideType = <F::Subfield as MulAccReduce>::WideType;
407
408    #[inline]
409    fn mul_acc(acc: &mut Self::WideType, a: Self, b: Self) {
410        F::Subfield::mul_acc(acc, a.0, b.0);
411    }
412}
413
414impl<F: FieldExtension> DefaultDotProduct for SubfieldElement<F> {}
415
416// Dot product: &Subfield<F> x Subfield<F>
417impl<'a, F: FieldExtension> MulAccReduce<&'a Self, Self> for SubfieldElement<F> {
418    type WideType = <F::Subfield as MulAccReduce>::WideType;
419
420    #[inline]
421    fn mul_acc(acc: &mut Self::WideType, a: &'a Self, b: Self) {
422        F::Subfield::mul_acc(acc, a.0, b.0);
423    }
424}
425
426impl<F: FieldExtension> DefaultDotProduct<&Self, Self> for SubfieldElement<F> {}
427
428// Dot product: Subfield<F> x &Subfield<F>
429impl<'a, F: FieldExtension> MulAccReduce<Self, &'a Self> for SubfieldElement<F> {
430    type WideType = <F::Subfield as MulAccReduce>::WideType;
431
432    #[inline]
433    fn mul_acc(acc: &mut Self::WideType, a: Self, b: &'a Self) {
434        F::Subfield::mul_acc(acc, a.0, b.0);
435    }
436}
437
438impl<F: FieldExtension> DefaultDotProduct<Self, &Self> for SubfieldElement<F> {}
439
440// Dot product: &Subfield<F> x &Subfield<F>
441impl<'a, 'b, F: FieldExtension> MulAccReduce<&'a Self, &'b Self> for SubfieldElement<F> {
442    type WideType = <F::Subfield as MulAccReduce>::WideType;
443
444    #[inline]
445    fn mul_acc(acc: &mut Self::WideType, a: &'a Self, b: &'b Self) {
446        F::Subfield::mul_acc(acc, a.0, b.0);
447    }
448}
449
450impl<F: FieldExtension> DefaultDotProduct<&Self, &Self> for SubfieldElement<F> {}
451
452// ----------------
453// | Zero and One |
454// ----------------
455
456impl<F: FieldExtension> Zero for SubfieldElement<F> {
457    /// The subfield's additive identity
458    fn zero() -> Self {
459        SubfieldElement(F::Subfield::ZERO)
460    }
461
462    fn is_zero(&self) -> bool {
463        self.0.is_zero().into()
464    }
465}
466
467impl<F: FieldExtension> One for SubfieldElement<F> {
468    /// The subfield's multiplicative identity
469    fn one() -> Self {
470        SubfieldElement(F::Subfield::ONE)
471    }
472}
473
474// ---------------
475// | Field trait |
476// ---------------
477
478impl<F: FieldExtension> Field for SubfieldElement<F> {
479    const ZERO: Self = SubfieldElement(F::Subfield::ZERO);
480    const ONE: Self = SubfieldElement(F::Subfield::ONE);
481
482    fn random(rng: impl RngCore) -> Self {
483        Self(<F::Subfield as Field>::random(rng))
484    }
485
486    fn square(&self) -> Self {
487        SubfieldElement(self.0.square())
488    }
489
490    fn double(&self) -> Self {
491        SubfieldElement(self.0.double())
492    }
493
494    fn invert(&self) -> CtOption<Self> {
495        self.0.invert().map(SubfieldElement)
496    }
497
498    fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
499        let (choice, sqrt) = F::Subfield::sqrt_ratio(&num.0, &div.0);
500        (choice, SubfieldElement(sqrt))
501    }
502}
503
504#[cfg(test)]
505mod tests {
506    use super::*;
507
508    #[test]
509    fn test_subfield_mersenne107_wincode() {
510        let elem = SubfieldElement::<Mersenne107>::new(Mersenne107::from(42u64));
511        let bytes = wincode::serialize(&elem).unwrap();
512
513        let decoded: SubfieldElement<Mersenne107> = wincode::deserialize(&bytes).unwrap();
514
515        assert_eq!(elem, decoded);
516    }
517}