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},
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> Default for SubfieldElement<F> {
128    fn default() -> Self {
129        Self::zero()
130    }
131}
132
133impl<F: FieldExtension> Serialize for SubfieldElement<F> {
134    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
135        let bytes = self
136            .to_le_bytes()
137            .into_iter()
138            .collect::<Array<u8, ByteSize<F::Subfield>>>();
139        serde_bytes::serialize(AsRef::<[u8]>::as_ref(&bytes), serializer)
140    }
141}
142
143impl<'de, F: FieldExtension> Deserialize<'de> for SubfieldElement<F> {
144    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
145        let bytes: &[u8] = serde_bytes::deserialize(deserializer)?;
146        let field_elem = SubfieldElement::from_le_bytes(bytes).map_err(|err| {
147            serde::de::Error::custom(format!("Failed to deserialize field element: {err:?}"))
148        })?;
149        Ok(field_elem)
150    }
151}
152
153impl<F: FieldExtension> Display for SubfieldElement<F> {
154    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
155        write!(f, "{self:?}")
156    }
157}
158
159// --------------
160// | Arithmetic |
161// --------------
162
163// === Addition === //
164
165#[macros::op_variants(owned, borrowed, flipped_commutative)]
166impl<F: FieldExtension> Add<&SubfieldElement<F>> for SubfieldElement<F> {
167    type Output = SubfieldElement<F>;
168
169    #[inline]
170    fn add(self, rhs: &SubfieldElement<F>) -> Self::Output {
171        SubfieldElement(self.0 + rhs.0)
172    }
173}
174
175#[macros::op_variants(owned)]
176impl<'a, F: FieldExtension> AddAssign<&'a SubfieldElement<F>> for SubfieldElement<F> {
177    #[inline]
178    fn add_assign(&mut self, rhs: &'a SubfieldElement<F>) {
179        *self = *self + rhs;
180    }
181}
182
183// === Subtraction === //
184
185#[macros::op_variants(owned, borrowed, flipped)]
186impl<F: FieldExtension> Sub<&SubfieldElement<F>> for SubfieldElement<F> {
187    type Output = SubfieldElement<F>;
188
189    #[inline]
190    fn sub(self, rhs: &SubfieldElement<F>) -> Self::Output {
191        SubfieldElement(self.0 - rhs.0)
192    }
193}
194
195#[macros::op_variants(owned)]
196impl<'a, F: FieldExtension> SubAssign<&'a SubfieldElement<F>> for SubfieldElement<F> {
197    #[inline]
198    fn sub_assign(&mut self, rhs: &'a SubfieldElement<F>) {
199        *self = *self - rhs;
200    }
201}
202
203// === Multiplication === //
204
205#[macros::op_variants(owned, borrowed, flipped_commutative)]
206impl<F: FieldExtension> Mul<&SubfieldElement<F>> for SubfieldElement<F> {
207    type Output = SubfieldElement<F>;
208
209    #[inline]
210    fn mul(self, rhs: &SubfieldElement<F>) -> Self::Output {
211        SubfieldElement(self.0 * rhs.0)
212    }
213}
214
215#[macros::op_variants(owned, borrowed, flipped_commutative)]
216impl<F: FieldExtension> Mul<&FieldElement<F>> for SubfieldElement<F> {
217    type Output = FieldElement<F>;
218
219    #[inline]
220    fn mul(self, rhs: &FieldElement<F>) -> Self::Output {
221        FieldElement(rhs.0 * self.0)
222    }
223}
224
225#[macros::op_variants(owned)]
226impl<'a, F: FieldExtension> MulAssign<&'a SubfieldElement<F>> for SubfieldElement<F> {
227    #[inline]
228    fn mul_assign(&mut self, rhs: &'a SubfieldElement<F>) {
229        *self = *self * rhs;
230    }
231}
232
233// === Negation === //
234
235#[macros::op_variants(borrowed)]
236impl<F: FieldExtension> Neg for SubfieldElement<F> {
237    type Output = SubfieldElement<F>;
238
239    #[inline]
240    fn neg(self) -> Self::Output {
241        SubfieldElement(-self.0)
242    }
243}
244
245// === Division === //
246
247#[macros::op_variants(owned, borrowed, flipped)]
248impl<F: FieldExtension> Div<&SubfieldElement<F>> for SubfieldElement<F> {
249    type Output = CtOption<SubfieldElement<F>>;
250
251    #[inline]
252    fn div(self, rhs: &SubfieldElement<F>) -> Self::Output {
253        rhs.0.invert().map(|inv| SubfieldElement(self.0 * inv))
254    }
255}
256
257// === Equality === //
258
259impl<F: FieldExtension> ConstantTimeEq for SubfieldElement<F> {
260    #[inline]
261    fn ct_eq(&self, other: &Self) -> Choice {
262        self.0.ct_eq(&other.0)
263    }
264}
265
266impl<F: FieldExtension> ConditionallySelectable for SubfieldElement<F> {
267    #[inline]
268    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
269        let selected = F::Subfield::conditional_select(&a.0, &b.0, choice);
270        SubfieldElement(selected)
271    }
272}
273
274// === Other === //
275
276impl<F: FieldExtension> AdditiveShares for SubfieldElement<F> {}
277
278// ---------------
279// | Conversions |
280// ---------------
281
282impl<F: FieldExtension> From<bool> for SubfieldElement<F> {
283    #[inline]
284    fn from(value: bool) -> Self {
285        SubfieldElement(F::Subfield::from(value as u64))
286    }
287}
288
289impl<F: FieldExtension> From<u8> for SubfieldElement<F> {
290    #[inline]
291    fn from(value: u8) -> Self {
292        SubfieldElement(F::Subfield::from(value as u64))
293    }
294}
295
296impl<F: FieldExtension> From<u16> for SubfieldElement<F> {
297    #[inline]
298    fn from(value: u16) -> Self {
299        SubfieldElement(F::Subfield::from(value as u64))
300    }
301}
302
303impl<F: FieldExtension> From<u32> for SubfieldElement<F> {
304    #[inline]
305    fn from(value: u32) -> Self {
306        SubfieldElement(F::Subfield::from(value as u64))
307    }
308}
309
310impl<F: FieldExtension> From<u64> for SubfieldElement<F> {
311    #[inline]
312    fn from(value: u64) -> Self {
313        SubfieldElement(F::Subfield::from(value))
314    }
315}
316
317impl<F: FieldExtension> From<u128> for SubfieldElement<F> {
318    #[inline]
319    fn from(value: u128) -> Self {
320        SubfieldElement(F::Subfield::from(value))
321    }
322}
323
324impl<F: PrimeFieldExtension> From<FieldElement<F>> for SubfieldElement<F> {
325    #[inline]
326    fn from(value: FieldElement<F>) -> Self {
327        SubfieldElement(value.0)
328    }
329}
330
331// -------------------
332// | Iterator Traits |
333// -------------------
334
335impl<F: FieldExtension> Sum for SubfieldElement<F> {
336    #[inline]
337    fn sum<I: Iterator<Item = SubfieldElement<F>>>(iter: I) -> Self {
338        let tmp = iter.fold(<F::Subfield as AccReduce>::zero_wide(), |mut acc, x| {
339            F::Subfield::acc(&mut acc, x.0);
340            acc
341        });
342        SubfieldElement(F::Subfield::reduce_mod_order(tmp))
343    }
344}
345
346impl<'a, F: FieldExtension> Sum<&'a SubfieldElement<F>> for SubfieldElement<F> {
347    #[inline]
348    fn sum<I: Iterator<Item = &'a SubfieldElement<F>>>(iter: I) -> Self {
349        let tmp = iter.fold(<F::Subfield as AccReduce>::zero_wide(), |mut acc, x| {
350            F::Subfield::acc(&mut acc, x.0);
351            acc
352        });
353        SubfieldElement(F::Subfield::reduce_mod_order(tmp))
354    }
355}
356
357impl<F: FieldExtension> Product for SubfieldElement<F> {
358    #[inline]
359    fn product<I: Iterator<Item = SubfieldElement<F>>>(iter: I) -> Self {
360        iter.fold(SubfieldElement::one(), |acc, x| acc * x)
361    }
362}
363
364impl<'a, F: FieldExtension> Product<&'a SubfieldElement<F>> for SubfieldElement<F> {
365    #[inline]
366    fn product<I: Iterator<Item = &'a SubfieldElement<F>>>(iter: I) -> Self {
367        iter.fold(SubfieldElement::one(), |acc, x| acc * x)
368    }
369}
370
371impl<F: FieldExtension> FromUniformBytes for SubfieldElement<F> {
372    type UniformBytes = <F::Subfield as FromUniformBytes>::UniformBytes;
373
374    fn from_uniform_bytes(bytes: &Array<u8, Self::UniformBytes>) -> Self {
375        Self(F::Subfield::from_uniform_bytes(bytes))
376    }
377}
378
379// Dot product: Subfield<F> x Subfield<F>
380impl<F: FieldExtension> IntoWide<<F::Subfield as MulAccReduce>::WideType> for SubfieldElement<F> {
381    #[inline]
382    fn to_wide(&self) -> <F::Subfield as MulAccReduce>::WideType {
383        <F::Subfield as MulAccReduce>::to_wide(&self.0)
384    }
385
386    #[inline]
387    fn zero_wide() -> <F::Subfield as MulAccReduce>::WideType {
388        <F::Subfield as MulAccReduce>::zero_wide()
389    }
390}
391
392impl<F: FieldExtension> ReduceWide<<F::Subfield as MulAccReduce>::WideType> for SubfieldElement<F> {
393    #[inline]
394    fn reduce_mod_order(a: <F::Subfield as MulAccReduce>::WideType) -> Self {
395        Self(F::Subfield::reduce_mod_order(a))
396    }
397}
398
399impl<F: FieldExtension> MulAccReduce for SubfieldElement<F> {
400    type WideType = <F::Subfield as MulAccReduce>::WideType;
401
402    #[inline]
403    fn mul_acc(acc: &mut Self::WideType, a: Self, b: Self) {
404        F::Subfield::mul_acc(acc, a.0, b.0);
405    }
406}
407
408impl<F: FieldExtension> DefaultDotProduct for SubfieldElement<F> {}
409
410// Dot product: &Subfield<F> x Subfield<F>
411impl<'a, F: FieldExtension> MulAccReduce<&'a Self, Self> for SubfieldElement<F> {
412    type WideType = <F::Subfield as MulAccReduce>::WideType;
413
414    #[inline]
415    fn mul_acc(acc: &mut Self::WideType, a: &'a Self, b: Self) {
416        F::Subfield::mul_acc(acc, a.0, b.0);
417    }
418}
419
420impl<F: FieldExtension> DefaultDotProduct<&Self, Self> for SubfieldElement<F> {}
421
422// Dot product: Subfield<F> x &Subfield<F>
423impl<'a, F: FieldExtension> MulAccReduce<Self, &'a Self> for SubfieldElement<F> {
424    type WideType = <F::Subfield as MulAccReduce>::WideType;
425
426    #[inline]
427    fn mul_acc(acc: &mut Self::WideType, a: Self, b: &'a Self) {
428        F::Subfield::mul_acc(acc, a.0, b.0);
429    }
430}
431
432impl<F: FieldExtension> DefaultDotProduct<Self, &Self> for SubfieldElement<F> {}
433
434// Dot product: &Subfield<F> x &Subfield<F>
435impl<'a, 'b, F: FieldExtension> MulAccReduce<&'a Self, &'b Self> for SubfieldElement<F> {
436    type WideType = <F::Subfield as MulAccReduce>::WideType;
437
438    #[inline]
439    fn mul_acc(acc: &mut Self::WideType, a: &'a Self, b: &'b Self) {
440        F::Subfield::mul_acc(acc, a.0, b.0);
441    }
442}
443
444impl<F: FieldExtension> DefaultDotProduct<&Self, &Self> for SubfieldElement<F> {}
445
446// ----------------
447// | Zero and One |
448// ----------------
449
450impl<F: FieldExtension> Zero for SubfieldElement<F> {
451    /// The subfield's additive identity
452    fn zero() -> Self {
453        SubfieldElement(F::Subfield::ZERO)
454    }
455
456    fn is_zero(&self) -> bool {
457        self.0.is_zero().into()
458    }
459}
460
461impl<F: FieldExtension> One for SubfieldElement<F> {
462    /// The subfield's multiplicative identity
463    fn one() -> Self {
464        SubfieldElement(F::Subfield::ONE)
465    }
466}
467
468// ---------------
469// | Field trait |
470// ---------------
471
472impl<F: FieldExtension> Field for SubfieldElement<F> {
473    const ZERO: Self = SubfieldElement(F::Subfield::ZERO);
474    const ONE: Self = SubfieldElement(F::Subfield::ONE);
475
476    fn random(rng: impl RngCore) -> Self {
477        Self(<F::Subfield as Field>::random(rng))
478    }
479
480    fn square(&self) -> Self {
481        SubfieldElement(self.0.square())
482    }
483
484    fn double(&self) -> Self {
485        SubfieldElement(self.0.double())
486    }
487
488    fn invert(&self) -> CtOption<Self> {
489        self.0.invert().map(SubfieldElement)
490    }
491
492    fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
493        let (choice, sqrt) = F::Subfield::sqrt_ratio(&num.0, &div.0);
494        (choice, SubfieldElement(sqrt))
495    }
496}
497
498#[cfg(test)]
499mod tests {
500    use super::*;
501
502    #[test]
503    fn test_subfield_mersenne107_wincode() {
504        let elem = SubfieldElement::<Mersenne107>::new(Mersenne107::from(42u64));
505        let bytes = wincode::serialize(&elem).unwrap();
506
507        let decoded: SubfieldElement<Mersenne107> = wincode::deserialize(&bytes).unwrap();
508
509        assert_eq!(elem, decoded);
510    }
511}