From 522f655cc019c35180c62f4019679303702a528a Mon Sep 17 00:00:00 2001 From: Charles Edward Gagnon Date: Wed, 18 Jun 2025 18:19:33 -0400 Subject: [PATCH 1/5] move methods and constant to `Field` --- src/lib.rs | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f9eee3c..9b333ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,12 +67,34 @@ pub trait Field: + for<'a> AddAssign<&'a Self> + for<'a> SubAssign<&'a Self> + for<'a> MulAssign<&'a Self> + + From { + /// The prime field can be converted back and forth into this binary + /// representation. + type Repr: Copy + Default + Send + Sync + 'static + AsRef<[u8]> + AsMut<[u8]>; + /// The zero element of the field, the additive identity. const ZERO: Self; /// The one element of the field, the multiplicative identity. const ONE: Self; + + /// Modulus of the field written as a string for debugging purposes. + /// + /// The encoding of the modulus is implementation-specific. Generic users of the + /// `PrimeField` trait should treat this string as opaque. + const MODULUS: &'static str; + + /// How many bits are needed to represent an element of this field. + const NUM_BITS: u32; + + /// How many bits of information can be reliably stored in the field element. + /// + /// This is usually `Self::NUM_BITS - 1`. + const CAPACITY: u32; + + /// Inverse of $2$ in the field. + const TWO_INV: Self; /// Returns an element chosen uniformly at random using a user-provided RNG. fn random(rng: impl RngCore) -> Self; @@ -189,13 +211,6 @@ pub trait Field: res } -} - -/// This represents an element of a non-binary prime field. -pub trait PrimeField: Field + From { - /// The prime field can be converted back and forth into this binary - /// representation. - type Repr: Copy + Default + Send + Sync + 'static + AsRef<[u8]> + AsMut<[u8]>; /// Interpret a string of numbers as a (congruent) prime field element. /// Does not accept unnecessary leading zeroes or a blank string. @@ -300,23 +315,10 @@ pub trait PrimeField: Field + From { !self.is_odd() } - /// Modulus of the field written as a string for debugging purposes. - /// - /// The encoding of the modulus is implementation-specific. Generic users of the - /// `PrimeField` trait should treat this string as opaque. - const MODULUS: &'static str; - - /// How many bits are needed to represent an element of this field. - const NUM_BITS: u32; - - /// How many bits of information can be reliably stored in the field element. - /// - /// This is usually `Self::NUM_BITS - 1`. - const CAPACITY: u32; - - /// Inverse of $2$ in the field. - const TWO_INV: Self; +} +/// This represents an element of a non-binary prime field. +pub trait PrimeField: Field { /// A fixed multiplicative generator of `modulus - 1` order. This element must also be /// a quadratic nonresidue. /// From 30cc942adbb728b65990f5a7a262c11fbf9aeba0 Mon Sep 17 00:00:00 2001 From: Charles Edward Gagnon Date: Wed, 18 Jun 2025 18:33:49 -0400 Subject: [PATCH 2/5] Update documentation --- src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9b333ac..75ed7d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,7 +69,7 @@ pub trait Field: + for<'a> MulAssign<&'a Self> + From { - /// The prime field can be converted back and forth into this binary + /// The field can be converted back and forth into this binary /// representation. type Repr: Copy + Default + Send + Sync + 'static + AsRef<[u8]> + AsMut<[u8]>; @@ -82,7 +82,7 @@ pub trait Field: /// Modulus of the field written as a string for debugging purposes. /// /// The encoding of the modulus is implementation-specific. Generic users of the - /// `PrimeField` trait should treat this string as opaque. + /// `Field` trait should treat this string as opaque. const MODULUS: &'static str; /// How many bits are needed to represent an element of this field. @@ -212,7 +212,7 @@ pub trait Field: res } - /// Interpret a string of numbers as a (congruent) prime field element. + /// Interpret a string of numbers as a (congruent) field element. /// Does not accept unnecessary leading zeroes or a blank string. /// /// # Security @@ -277,7 +277,7 @@ pub trait Field: } /// Attempts to convert a byte representation of a field element into an element of - /// this prime field, failing if the input is not canonical (is not smaller than the + /// this field, failing if the input is not canonical (is not smaller than the /// field's modulus). /// /// The byte representation is interpreted with the same endianness as elements @@ -285,7 +285,7 @@ pub trait Field: fn from_repr(repr: Self::Repr) -> CtOption; /// Attempts to convert a byte representation of a field element into an element of - /// this prime field, failing if the input is not canonical (is not smaller than the + /// this field, failing if the input is not canonical (is not smaller than the /// field's modulus). /// /// The byte representation is interpreted with the same endianness as elements @@ -299,7 +299,7 @@ pub trait Field: Self::from_repr(repr).into() } - /// Converts an element of the prime field into the standard byte representation for + /// Converts an element of the field into the standard byte representation for /// this field. /// /// The endianness of the byte representation is implementation-specific. Generic From 35c353d5bbb656af14690b9d0fbc491a2718ae5b Mon Sep 17 00:00:00 2001 From: Charles Edward Gagnon Date: Wed, 18 Jun 2025 18:33:57 -0400 Subject: [PATCH 3/5] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 955e6a8..7f3abfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this library adheres to Rust's notion of ## [Unreleased] +### Changed +- Some of the methods and constants behind the `PrimeField` trait were moved to + the `Field` trait, because they did not require the field to be prime. + ## [0.13.1] - 2025-03-09 ### Changed - `ff_derive` now works with all odd primes, not just primes that are either From 002470c5026a1f364c4758b281509f423ca4547c Mon Sep 17 00:00:00 2001 From: Charles Edward Gagnon Date: Tue, 23 Sep 2025 10:17:41 -0400 Subject: [PATCH 4/5] make PrimeField a marker --- src/lib.rs | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 75ed7d7..c9ca3a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,6 +95,38 @@ pub trait Field: /// Inverse of $2$ in the field. const TWO_INV: Self; + + /// A fixed multiplicative generator of `modulus - 1` order. This element must also be + /// a quadratic nonresidue. + /// + /// It can be calculated using [SageMath] as `GF(modulus).primitive_element()`. + /// + /// Implementations of this trait MUST ensure that this is the generator used to + /// derive `Self::ROOT_OF_UNITY`. + /// + /// [SageMath]: https://www.sagemath.org/ + const MULTIPLICATIVE_GENERATOR: Self; + + /// An integer `s` satisfying the equation `2^s * t = modulus - 1` with `t` odd. + /// + /// This is the number of leading zero bits in the little-endian bit representation of + /// `modulus - 1`. + const S: u32; + + /// The `2^s` root of unity. + /// + /// It can be calculated by exponentiating `Self::MULTIPLICATIVE_GENERATOR` by `t`, + /// where `t = (modulus - 1) >> Self::S`. + const ROOT_OF_UNITY: Self; + + /// Inverse of [`Self::ROOT_OF_UNITY`]. + const ROOT_OF_UNITY_INV: Self; + + /// Generator of the `t-order` multiplicative subgroup. + /// + /// It can be calculated by exponentiating [`Self::MULTIPLICATIVE_GENERATOR`] by `2^s`, + /// where `s` is [`Self::S`]. + const DELTA: Self; /// Returns an element chosen uniformly at random using a user-provided RNG. fn random(rng: impl RngCore) -> Self; @@ -318,39 +350,7 @@ pub trait Field: } /// This represents an element of a non-binary prime field. -pub trait PrimeField: Field { - /// A fixed multiplicative generator of `modulus - 1` order. This element must also be - /// a quadratic nonresidue. - /// - /// It can be calculated using [SageMath] as `GF(modulus).primitive_element()`. - /// - /// Implementations of this trait MUST ensure that this is the generator used to - /// derive `Self::ROOT_OF_UNITY`. - /// - /// [SageMath]: https://www.sagemath.org/ - const MULTIPLICATIVE_GENERATOR: Self; - - /// An integer `s` satisfying the equation `2^s * t = modulus - 1` with `t` odd. - /// - /// This is the number of leading zero bits in the little-endian bit representation of - /// `modulus - 1`. - const S: u32; - - /// The `2^s` root of unity. - /// - /// It can be calculated by exponentiating `Self::MULTIPLICATIVE_GENERATOR` by `t`, - /// where `t = (modulus - 1) >> Self::S`. - const ROOT_OF_UNITY: Self; - - /// Inverse of [`Self::ROOT_OF_UNITY`]. - const ROOT_OF_UNITY_INV: Self; - - /// Generator of the `t-order` multiplicative subgroup. - /// - /// It can be calculated by exponentiating [`Self::MULTIPLICATIVE_GENERATOR`] by `2^s`, - /// where `s` is [`Self::S`]. - const DELTA: Self; -} +pub trait PrimeField: Field {} /// The subset of prime-order fields such that `(modulus - 1)` is divisible by `N`. /// From e5f81b968f5d84bc975d0e81c6fb9765c26e9814 Mon Sep 17 00:00:00 2001 From: Charles Edward Gagnon Date: Tue, 23 Sep 2025 10:20:07 -0400 Subject: [PATCH 5/5] update CHANGELOG --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f3abfa..f6490a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,9 @@ and this library adheres to Rust's notion of ## [Unreleased] ### Changed -- Some of the methods and constants behind the `PrimeField` trait were moved to - the `Field` trait, because they did not require the field to be prime. +- The methods and constants behind the `PrimeField` trait are moved to + the `Field` trait, because they do not require the field to be prime. + `PrimeField` is now a marker trait. ## [0.13.1] - 2025-03-09 ### Changed