From 93537e263e74cabd78301b0cdb3a246d361d1a27 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 24 Nov 2022 03:37:31 +0000 Subject: [PATCH] Add `PrimeField::{ROOT_OF_UNITY_INV, DELTA}` --- CHANGELOG.md | 5 ++++- ff_derive/src/lib.rs | 18 +++++++++++++++++- src/lib.rs | 11 ++++++++++- tests/derive.rs | 22 ++++++++++++++++++++++ 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44a76bf..30474bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,10 @@ and this library adheres to Rust's notion of - `ff::Field::{sqrt_ratio, sqrt_alt}` - `core::iter::{Sum, Product}` bounds on `ff::Field` - `ff::PrimeField::TWO_INV` -- `ff::PrimeField::{MULTIPLICATIVE_GENERATOR, ROOT_OF_UNITY}` +- Constants related to multiplicative generators: + - `ff::PrimeField::MULTIPLICATIVE_GENERATOR` + - `ff::PrimeField::{ROOT_OF_UNITY, ROOT_OF_UNITY_INV}` + - `ff::PrimeField::DELTA` - `ff::helpers`: - `sqrt_tonelli_shanks` - `sqrt_ratio_generic` diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index bee41ee..e3e6776 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -497,7 +497,13 @@ fn prime_field_constants_and_sqrt( } // Compute 2^s root of unity given the generator - let root_of_unity = biguint_to_u64_vec(to_mont(exp(generator.clone(), &t, &modulus)), limbs); + let root_of_unity = exp(generator.clone(), &t, &modulus); + let root_of_unity_inv = biguint_to_u64_vec(to_mont(invert(root_of_unity.clone())), limbs); + let root_of_unity = biguint_to_u64_vec(to_mont(root_of_unity), limbs); + let delta = biguint_to_u64_vec( + to_mont(exp(generator.clone(), &(BigUint::one() << s), &modulus)), + limbs, + ); let generator = biguint_to_u64_vec(to_mont(generator), limbs); let sqrt_impl = @@ -637,6 +643,12 @@ fn prime_field_constants_and_sqrt( /// 2^s root of unity computed by GENERATOR^t const ROOT_OF_UNITY: #name = #name(#root_of_unity); + + /// (2^s)^{-1} mod m + const ROOT_OF_UNITY_INV: #name = #name(#root_of_unity_inv); + + /// GENERATOR^{2^s} + const DELTA: #name = #name(#delta); }, sqrt_impl, ) @@ -1236,6 +1248,10 @@ fn prime_field_impl( const S: u32 = S; const ROOT_OF_UNITY: Self = ROOT_OF_UNITY; + + const ROOT_OF_UNITY_INV: Self = ROOT_OF_UNITY_INV; + + const DELTA: Self = DELTA; } #prime_field_bits_impl diff --git a/src/lib.rs b/src/lib.rs index 378de75..e40e163 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -297,7 +297,7 @@ pub trait PrimeField: Field + From { /// 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`. + /// derive `Self::ROOT_OF_UNITY`. /// /// [SageMath]: https://www.sagemath.org/ const MULTIPLICATIVE_GENERATOR: Self; @@ -313,6 +313,15 @@ pub trait PrimeField: Field + From { /// 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; } /// This represents the bits of an element of a prime field. diff --git a/tests/derive.rs b/tests/derive.rs index 2d33f4a..4137b53 100644 --- a/tests/derive.rs +++ b/tests/derive.rs @@ -45,6 +45,28 @@ fn constants() { Bls381K12Scalar::from(2) * Bls381K12Scalar::TWO_INV, Bls381K12Scalar::ONE, ); + + assert_eq!( + Bls381K12Scalar::ROOT_OF_UNITY * Bls381K12Scalar::ROOT_OF_UNITY_INV, + Bls381K12Scalar::ONE, + ); + + // ROOT_OF_UNITY^{2^s} mod m == 1 + assert_eq!( + Bls381K12Scalar::ROOT_OF_UNITY.pow(&[1u64 << Bls381K12Scalar::S, 0, 0, 0]), + Bls381K12Scalar::ONE, + ); + + // DELTA^{t} mod m == 1 + assert_eq!( + Bls381K12Scalar::DELTA.pow(&[ + 0xfffe5bfeffffffff, + 0x09a1d80553bda402, + 0x299d7d483339d808, + 0x73eda753, + ]), + Bls381K12Scalar::ONE, + ); } #[test]