From a36784b202be52dad9c53d1d8965c4409dc89116 Mon Sep 17 00:00:00 2001 From: Solomon Date: Mon, 7 Feb 2022 14:13:14 -0800 Subject: [PATCH 1/7] Removed SquareRootField --- ec/src/lib.rs | 12 ++-- ec/src/models/bls12/mod.rs | 4 +- ec/src/models/bn/mod.rs | 4 +- ec/src/models/bw6/mod.rs | 4 +- ec/src/models/mnt4/mod.rs | 6 +- ec/src/models/mnt6/mod.rs | 6 +- ec/src/models/mod.rs | 6 +- ec/src/models/short_weierstrass_jacobian.rs | 2 +- ec/src/models/twisted_edwards_extended.rs | 2 +- ff/src/fields/macros.rs | 56 +++++++++---------- ff/src/fields/mod.rs | 37 ++++++------ ff/src/fields/models/fp3.rs | 4 +- ff/src/fields/models/mod.rs | 2 +- ff/src/fields/models/quadratic_extension.rs | 6 +- ff/src/lib.rs | 2 +- test-curves/src/bls12_381/tests.rs | 2 +- .../src/bn384_small_two_adicity/tests.rs | 2 +- test-templates/src/fields.rs | 6 +- 18 files changed, 79 insertions(+), 84 deletions(-) diff --git a/ec/src/lib.rs b/ec/src/lib.rs index b759009f9..a631c1b5d 100644 --- a/ec/src/lib.rs +++ b/ec/src/lib.rs @@ -21,7 +21,7 @@ extern crate ark_std; use ark_ff::{ bytes::{FromBytes, ToBytes}, - fields::{BitIteratorBE, Field, PrimeField, SquareRootField}, + fields::{BitIteratorBE, Field, PrimeField}, UniformRand, }; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; @@ -47,7 +47,7 @@ pub mod wnaf; pub trait PairingEngine: Sized + 'static + Copy + Debug + Sync + Send + Eq + PartialEq { /// This is the scalar field of the G1/G2 groups. - type Fr: PrimeField + SquareRootField; + type Fr: PrimeField; /// The projective representation of an element in G1. type G1Projective: ProjectiveCurve @@ -80,10 +80,10 @@ pub trait PairingEngine: Sized + 'static + Copy + Debug + Sync + Send + Eq + Par type G2Prepared: ToBytes + Default + Clone + Send + Sync + Debug + From; /// The base field that hosts G1. - type Fq: PrimeField + SquareRootField; + type Fq: PrimeField; /// The extension field that hosts G2. - type Fqe: SquareRootField; + type Fqe: Field; /// The extension field that hosts the target group of the pairing. type Fqk: Field; @@ -156,7 +156,7 @@ pub trait ProjectiveCurve: + From<::Affine> { type Parameters: ModelParameters; - type ScalarField: PrimeField + SquareRootField; + type ScalarField: PrimeField; type BaseField: Field; type Affine: AffineCurve< Parameters = Self::Parameters, @@ -256,7 +256,7 @@ pub trait AffineCurve: + From<::Projective> { type Parameters: ModelParameters; - type ScalarField: PrimeField + SquareRootField + Into<::BigInt>; + type ScalarField: PrimeField + Into<::BigInt>; type BaseField: Field; type Projective: ProjectiveCurve< Parameters = Self::Parameters, diff --git a/ec/src/models/bls12/mod.rs b/ec/src/models/bls12/mod.rs index e5b1c50e9..fb6f23629 100644 --- a/ec/src/models/bls12/mod.rs +++ b/ec/src/models/bls12/mod.rs @@ -6,7 +6,7 @@ use ark_ff::fields::{ fp12_2over3over2::{Fp12, Fp12Parameters}, fp2::Fp2Parameters, fp6_3over2::Fp6Parameters, - BitIteratorBE, Field, Fp2, PrimeField, SquareRootField, + BitIteratorBE, Field, Fp2, PrimeField, }; use core::marker::PhantomData; use num_traits::{One, Zero}; @@ -33,7 +33,7 @@ pub trait Bls12Parameters: 'static { /// What kind of twist is this? const TWIST_TYPE: TwistType; - type Fp: PrimeField + SquareRootField + Into<::BigInt>; + type Fp: PrimeField + Into<::BigInt>; type Fp2Params: Fp2Parameters; type Fp6Params: Fp6Parameters; type Fp12Params: Fp12Parameters; diff --git a/ec/src/models/bn/mod.rs b/ec/src/models/bn/mod.rs index 7e1751797..e29883828 100644 --- a/ec/src/models/bn/mod.rs +++ b/ec/src/models/bn/mod.rs @@ -6,7 +6,7 @@ use ark_ff::fields::{ fp12_2over3over2::{Fp12, Fp12Parameters}, fp2::Fp2Parameters, fp6_3over2::Fp6Parameters, - Field, Fp2, PrimeField, SquareRootField, + Field, Fp2, PrimeField, }; use num_traits::One; @@ -31,7 +31,7 @@ pub trait BnParameters: 'static { const TWIST_TYPE: TwistType; const TWIST_MUL_BY_Q_X: Fp2; const TWIST_MUL_BY_Q_Y: Fp2; - type Fp: PrimeField + SquareRootField + Into<::BigInt>; + type Fp: PrimeField + Into<::BigInt>; type Fp2Params: Fp2Parameters; type Fp6Params: Fp6Parameters; type Fp12Params: Fp12Parameters; diff --git a/ec/src/models/bw6/mod.rs b/ec/src/models/bw6/mod.rs index ff2726e10..c763be683 100644 --- a/ec/src/models/bw6/mod.rs +++ b/ec/src/models/bw6/mod.rs @@ -5,7 +5,7 @@ use crate::{ use ark_ff::fields::{ fp3::Fp3Parameters, fp6_2over3::{Fp6, Fp6Parameters}, - BitIteratorBE, Field, PrimeField, SquareRootField, + BitIteratorBE, Field, PrimeField, }; use num_traits::One; @@ -24,7 +24,7 @@ pub trait BW6Parameters: 'static + Eq + PartialEq { const ATE_LOOP_COUNT_2: &'static [i8]; const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool; const TWIST_TYPE: TwistType; - type Fp: PrimeField + SquareRootField + Into<::BigInt>; + type Fp: PrimeField + Into<::BigInt>; type Fp3Params: Fp3Parameters; type Fp6Params: Fp6Parameters; type G1Parameters: SWModelParameters; diff --git a/ec/src/models/mnt4/mod.rs b/ec/src/models/mnt4/mod.rs index ea73fdcb2..04544dbad 100644 --- a/ec/src/models/mnt4/mod.rs +++ b/ec/src/models/mnt4/mod.rs @@ -5,7 +5,7 @@ use crate::{ use ark_ff::{ fp2::{Fp2, Fp2Parameters}, fp4::{Fp4, Fp4Parameters}, - BitIteratorBE, Field, PrimeField, SquareRootField, + BitIteratorBE, Field, PrimeField, }; use num_traits::{One, Zero}; @@ -30,8 +30,8 @@ pub trait MNT4Parameters: 'static { const FINAL_EXPONENT_LAST_CHUNK_1: ::BigInt; const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool; const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: ::BigInt; - type Fp: PrimeField + SquareRootField + Into<::BigInt>; - type Fr: PrimeField + SquareRootField + Into<::BigInt>; + type Fp: PrimeField + Into<::BigInt>; + type Fr: PrimeField + Into<::BigInt>; type Fp2Params: Fp2Parameters; type Fp4Params: Fp4Parameters; type G1Parameters: SWModelParameters; diff --git a/ec/src/models/mnt6/mod.rs b/ec/src/models/mnt6/mod.rs index fe1efa8cb..9ad0fb124 100644 --- a/ec/src/models/mnt6/mod.rs +++ b/ec/src/models/mnt6/mod.rs @@ -5,7 +5,7 @@ use crate::{ use ark_ff::{ fp3::{Fp3, Fp3Parameters}, fp6_2over3::{Fp6, Fp6Parameters}, - BitIteratorBE, Field, PrimeField, SquareRootField, + BitIteratorBE, Field, PrimeField, }; use num_traits::{One, Zero}; @@ -30,8 +30,8 @@ pub trait MNT6Parameters: 'static { const FINAL_EXPONENT_LAST_CHUNK_1: ::BigInt; const FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG: bool; const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: ::BigInt; - type Fp: PrimeField + SquareRootField + Into<::BigInt>; - type Fr: PrimeField + SquareRootField + Into<::BigInt>; + type Fp: PrimeField + Into<::BigInt>; + type Fr: PrimeField + Into<::BigInt>; type Fp3Params: Fp3Parameters; type Fp6Params: Fp6Parameters; type G1Parameters: SWModelParameters; diff --git a/ec/src/models/mod.rs b/ec/src/models/mod.rs index 246405b36..d8a399ec0 100644 --- a/ec/src/models/mod.rs +++ b/ec/src/models/mod.rs @@ -1,5 +1,5 @@ use crate::AffineCurve; -use ark_ff::{fields::BitIteratorBE, Field, PrimeField, SquareRootField, Zero}; +use ark_ff::{fields::BitIteratorBE, Field, PrimeField, Zero}; pub mod bls12; pub mod bn; @@ -11,8 +11,8 @@ pub mod twisted_edwards_extended; /// Model parameters for an elliptic curve. pub trait ModelParameters: Send + Sync + Sized + 'static { - type BaseField: Field + SquareRootField; - type ScalarField: PrimeField + SquareRootField + Into<::BigInt>; + type BaseField: Field; + type ScalarField: PrimeField + Into<::BigInt>; const COFACTOR: &'static [u64]; const COFACTOR_INV: Self::ScalarField; diff --git a/ec/src/models/short_weierstrass_jacobian.rs b/ec/src/models/short_weierstrass_jacobian.rs index 0c1918bd6..b00e613d0 100644 --- a/ec/src/models/short_weierstrass_jacobian.rs +++ b/ec/src/models/short_weierstrass_jacobian.rs @@ -12,7 +12,7 @@ use ark_std::{ use ark_ff::{ bytes::{FromBytes, ToBytes}, - fields::{Field, PrimeField, SquareRootField}, + fields::{Field, PrimeField}, ToConstraintField, UniformRand, }; diff --git a/ec/src/models/twisted_edwards_extended.rs b/ec/src/models/twisted_edwards_extended.rs index 8f42fe222..4d23618b9 100644 --- a/ec/src/models/twisted_edwards_extended.rs +++ b/ec/src/models/twisted_edwards_extended.rs @@ -22,7 +22,7 @@ use zeroize::Zeroize; use ark_ff::{ bytes::{FromBytes, ToBytes}, - fields::{Field, PrimeField, SquareRootField}, + fields::{Field, PrimeField}, ToConstraintField, UniformRand, }; diff --git a/ff/src/fields/macros.rs b/ff/src/fields/macros.rs index 4245768f7..3d5293cf5 100644 --- a/ff/src/fields/macros.rs +++ b/ff/src/fields/macros.rs @@ -367,6 +367,33 @@ macro_rules! impl_Fp { } } + #[inline] + fn legendre(&self) -> LegendreSymbol { + use crate::fields::LegendreSymbol::*; + + // s = self^((MODULUS - 1) // 2) + let s = self.pow(P::MODULUS_MINUS_ONE_DIV_TWO); + if s.is_zero() { + Zero + } else if s.is_one() { + QuadraticResidue + } else { + QuadraticNonResidue + } + } + + #[inline] + fn sqrt(&self) -> Option { + sqrt_impl!(Self, P, self) + } + + fn sqrt_in_place(&mut self) -> Option<&mut Self> { + (*self).sqrt().map(|sqrt| { + *self = sqrt; + self + }) + } + #[inline] fn square(&self) -> Self { let mut temp = self.clone(); @@ -486,35 +513,6 @@ macro_rules! impl_Fp { } } - impl SquareRootField for $Fp

{ - #[inline] - fn legendre(&self) -> LegendreSymbol { - use crate::fields::LegendreSymbol::*; - - // s = self^((MODULUS - 1) // 2) - let s = self.pow(P::MODULUS_MINUS_ONE_DIV_TWO); - if s.is_zero() { - Zero - } else if s.is_one() { - QuadraticResidue - } else { - QuadraticNonResidue - } - } - - #[inline] - fn sqrt(&self) -> Option { - sqrt_impl!(Self, P, self) - } - - fn sqrt_in_place(&mut self) -> Option<&mut Self> { - (*self).sqrt().map(|sqrt| { - *self = sqrt; - self - }) - } - } - /// Note that this implementation of `Ord` compares field elements viewing /// them as integers in the range 0, 1, ..., P::MODULUS - 1. However, other /// implementations of `PrimeField` might choose a different ordering, and diff --git a/ff/src/fields/mod.rs b/ff/src/fields/mod.rs index bc6df82de..0d3356a49 100644 --- a/ff/src/fields/mod.rs +++ b/ff/src/fields/mod.rs @@ -150,6 +150,19 @@ pub trait Field: /// random field elements from a hash-function or RNG output. fn from_random_bytes_with_flags(bytes: &[u8]) -> Option<(Self, F)>; + /// Returns a `LegendreSymbol`, which indicates whether this field element + /// is 1 : a quadratic residue + /// 0 : equal to 0 + /// -1 : a quadratic non-residue + fn legendre(&self) -> LegendreSymbol; + + /// Returns the square root of self, if it exists. + #[must_use] + fn sqrt(&self) -> Option; + + /// Sets `self` to be the square root of `self`, if it exists. + fn sqrt_in_place(&mut self) -> Option<&mut Self>; + /// Returns `self * self`. #[must_use] fn square(&self) -> Self; @@ -432,22 +445,6 @@ pub trait PrimeField: } } -/// The interface for a field that supports an efficient square-root operation. -pub trait SquareRootField: Field { - /// Returns a `LegendreSymbol`, which indicates whether this field element - /// is 1 : a quadratic residue - /// 0 : equal to 0 - /// -1 : a quadratic non-residue - fn legendre(&self) -> LegendreSymbol; - - /// Returns the square root of self, if it exists. - #[must_use] - fn sqrt(&self) -> Option; - - /// Sets `self` to be the square root of `self`, if it exists. - fn sqrt_in_place(&mut self) -> Option<&mut Self>; -} - /// Indication of the field element's quadratic residuosity /// /// # Examples @@ -455,7 +452,7 @@ pub trait SquareRootField: Field { /// # use ark_std::test_rng; /// # use ark_test_curves::bls12_381::Fq as Fp; /// # use ark_std::UniformRand; -/// # use ark_ff::{LegendreSymbol, Field, SquareRootField}; +/// # use ark_ff::{LegendreSymbol, Field}; /// let a: Fp = Fp::rand(&mut test_rng()); /// let b = a.square(); /// assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue); @@ -475,7 +472,7 @@ impl LegendreSymbol { /// # use ark_std::test_rng; /// # use ark_test_curves::bls12_381::Fq as Fp; /// # use ark_std::UniformRand; - /// # use ark_ff::{LegendreSymbol, Field, SquareRootField}; + /// # use ark_ff::{LegendreSymbol, Field}; /// let a: Fp = Fp::rand(&mut test_rng()); /// let b: Fp = a.square(); /// assert!(!b.legendre().is_zero()); @@ -489,7 +486,7 @@ impl LegendreSymbol { /// # Examples /// ``` /// # use ark_test_curves::bls12_381::{Fq, Fq2Parameters}; - /// # use ark_ff::{LegendreSymbol, SquareRootField}; + /// # use ark_ff::LegendreSymbol; /// # use ark_ff::Fp2Parameters; /// let a: Fq = Fq2Parameters::NONRESIDUE; /// assert!(a.legendre().is_qnr()); @@ -504,7 +501,7 @@ impl LegendreSymbol { /// # use ark_std::test_rng; /// # use ark_test_curves::bls12_381::Fq as Fp; /// # use ark_std::UniformRand; - /// # use ark_ff::{LegendreSymbol, Field, SquareRootField}; + /// # use ark_ff::{LegendreSymbol, Field}; /// let a: Fp = Fp::rand(&mut test_rng()); /// let b: Fp = a.square(); /// assert!(b.legendre().is_qr()); diff --git a/ff/src/fields/models/fp3.rs b/ff/src/fields/models/fp3.rs index 809bfa111..0a1bd5339 100644 --- a/ff/src/fields/models/fp3.rs +++ b/ff/src/fields/models/fp3.rs @@ -3,7 +3,7 @@ use crate::fields::*; use core::marker::PhantomData; pub trait Fp3Parameters: 'static + Send + Sync { - type Fp: PrimeField + SquareRootField; + type Fp: PrimeField; const NONRESIDUE: Self::Fp; @@ -71,7 +71,7 @@ impl Fp3

{ } } -impl SquareRootField for Fp3

{ +impl Field for Fp3

{ /// Returns the Legendre symbol. fn legendre(&self) -> LegendreSymbol { self.norm().legendre() diff --git a/ff/src/fields/models/mod.rs b/ff/src/fields/models/mod.rs index 4f70b4fe4..a11cab1de 100644 --- a/ff/src/fields/models/mod.rs +++ b/ff/src/fields/models/mod.rs @@ -14,7 +14,7 @@ use crate::{ BigInteger384, BigInteger448, BigInteger64, BigInteger768, BigInteger832, }, bytes::{FromBytes, ToBytes}, - fields::{FftField, Field, FpParameters, LegendreSymbol, PrimeField, SquareRootField}, + fields::{FftField, Field, FpParameters, LegendreSymbol, PrimeField}, }; use ark_serialize::*; diff --git a/ff/src/fields/models/quadratic_extension.rs b/ff/src/fields/models/quadratic_extension.rs index 1888297a7..30f25d638 100644 --- a/ff/src/fields/models/quadratic_extension.rs +++ b/ff/src/fields/models/quadratic_extension.rs @@ -21,7 +21,7 @@ use ark_std::rand::{ use crate::{ biginteger::BigInteger, bytes::{FromBytes, ToBytes}, - fields::{Field, LegendreSymbol, PrimeField, SquareRootField}, + fields::{Field, LegendreSymbol, PrimeField}, ToConstraintField, UniformRand, }; @@ -369,9 +369,9 @@ impl Field for QuadExtField

{ } } -impl<'a, P: QuadExtParameters> SquareRootField for QuadExtField

+impl<'a, P: QuadExtParameters> Field for QuadExtField

where - P::BaseField: SquareRootField + From, + P::BaseField: Field + From, { fn legendre(&self) -> LegendreSymbol { // The LegendreSymbol in a field of order q for an element x can be diff --git a/ff/src/lib.rs b/ff/src/lib.rs index 3c088a184..b4b375b29 100644 --- a/ff/src/lib.rs +++ b/ff/src/lib.rs @@ -41,7 +41,7 @@ pub use ark_std::vec; pub mod prelude { pub use crate::biginteger::BigInteger; - pub use crate::fields::{Field, FpParameters, PrimeField, SquareRootField}; + pub use crate::fields::{Field, FpParameters, PrimeField}; pub use ark_std::UniformRand; diff --git a/test-curves/src/bls12_381/tests.rs b/test-curves/src/bls12_381/tests.rs index 338770c27..504af3b49 100644 --- a/test-curves/src/bls12_381/tests.rs +++ b/test-curves/src/bls12_381/tests.rs @@ -1,6 +1,6 @@ #![allow(unused_imports)] use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve}; -use ark_ff::{Field, One, SquareRootField, UniformRand, Zero}; +use ark_ff::{Field, One, UniformRand, Zero}; use crate::bls12_381::{g1, Fq, Fq2, Fq6, FqParameters, Fr, G1Affine, G1Projective}; use ark_algebra_test_templates::{ diff --git a/test-curves/src/bn384_small_two_adicity/tests.rs b/test-curves/src/bn384_small_two_adicity/tests.rs index 32c6438bd..9b4cc36af 100644 --- a/test-curves/src/bn384_small_two_adicity/tests.rs +++ b/test-curves/src/bn384_small_two_adicity/tests.rs @@ -1,6 +1,6 @@ #![allow(unused_imports)] use ark_ec::{models::SWModelParameters, AffineCurve, PairingEngine, ProjectiveCurve}; -use ark_ff::{Field, One, SquareRootField, UniformRand, Zero}; +use ark_ff::{Field, One, UniformRand, Zero}; use ark_std::{rand::Rng, test_rng}; use crate::bn384_small_two_adicity::{g1, Fq, FqParameters, Fr, G1Affine, G1Projective}; diff --git a/test-templates/src/fields.rs b/test-templates/src/fields.rs index be0003c28..85d5538dc 100644 --- a/test-templates/src/fields.rs +++ b/test-templates/src/fields.rs @@ -1,6 +1,6 @@ #![allow(unused)] #![allow(clippy::eq_op)] -use ark_ff::fields::{FftField, FftParameters, Field, LegendreSymbol, PrimeField, SquareRootField}; +use ark_ff::fields::{FftField, FftParameters, Field, LegendreSymbol, PrimeField}; use ark_serialize::{buffer_bit_byte_size, Flags, SWFlags}; use ark_std::{io::Cursor, rand::Rng}; @@ -187,7 +187,7 @@ fn random_field_tests() { } } -fn random_sqrt_tests() { +fn random_sqrt_tests() { let mut rng = ark_std::test_rng(); for _ in 0..ITERATIONS { @@ -343,7 +343,7 @@ pub fn primefield_test() { fft_field_test::(); } -pub fn sqrt_field_test(elem: F) { +pub fn sqrt_field_test(elem: F) { let square = elem.square(); let sqrt = square.sqrt().unwrap(); assert!(sqrt == elem || sqrt == -elem); From bf84185356609b532910933900615e5e047d0480 Mon Sep 17 00:00:00 2001 From: Solomon Date: Mon, 7 Feb 2022 15:01:34 -0800 Subject: [PATCH 2/7] Merge cleanup --- ec/src/models/bn/mod.rs | 12 - ec/src/models/bw6/mod.rs | 12 - ff/src/fields/macros.rs | 744 ----------------------------------- test-templates/src/fields.rs | 6 +- 4 files changed, 1 insertion(+), 773 deletions(-) delete mode 100644 ff/src/fields/macros.rs diff --git a/ec/src/models/bn/mod.rs b/ec/src/models/bn/mod.rs index 6b7bc6d1a..c61a5a05c 100644 --- a/ec/src/models/bn/mod.rs +++ b/ec/src/models/bn/mod.rs @@ -4,15 +4,9 @@ use crate::{ }; use ark_ff::fields::{ fp12_2over3over2::{Fp12, Fp12Parameters}, -<<<<<<< HEAD fp2::Fp2Parameters, fp6_3over2::Fp6Parameters, Field, Fp2, PrimeField, -======= - fp2::Fp2Config, - fp6_3over2::Fp6Config, - Field, Fp2, PrimeField, SquareRootField, ->>>>>>> master }; use num_traits::One; @@ -37,15 +31,9 @@ pub trait BnParameters: 'static { const TWIST_TYPE: TwistType; const TWIST_MUL_BY_Q_X: Fp2; const TWIST_MUL_BY_Q_Y: Fp2; -<<<<<<< HEAD type Fp: PrimeField + Into<::BigInt>; type Fp2Params: Fp2Parameters; type Fp6Params: Fp6Parameters; -======= - type Fp: PrimeField + SquareRootField + Into<::BigInt>; - type Fp2Params: Fp2Config; - type Fp6Params: Fp6Config; ->>>>>>> master type Fp12Params: Fp12Parameters; type G1Parameters: SWModelParameters; type G2Parameters: SWModelParameters< diff --git a/ec/src/models/bw6/mod.rs b/ec/src/models/bw6/mod.rs index 17afe4092..3dc001d7f 100644 --- a/ec/src/models/bw6/mod.rs +++ b/ec/src/models/bw6/mod.rs @@ -3,15 +3,9 @@ use crate::{ PairingEngine, }; use ark_ff::fields::{ -<<<<<<< HEAD fp3::Fp3Parameters, fp6_2over3::{Fp6, Fp6Parameters}, BitIteratorBE, Field, PrimeField, -======= - fp3::Fp3Config, - fp6_2over3::{Fp6, Fp6Config}, - BitIteratorBE, Field, PrimeField, SquareRootField, ->>>>>>> master }; use num_traits::One; @@ -30,15 +24,9 @@ pub trait BW6Parameters: 'static + Eq + PartialEq { const ATE_LOOP_COUNT_2: &'static [i8]; const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool; const TWIST_TYPE: TwistType; -<<<<<<< HEAD type Fp: PrimeField + Into<::BigInt>; type Fp3Params: Fp3Parameters; type Fp6Params: Fp6Parameters; -======= - type Fp: PrimeField + SquareRootField + Into<::BigInt>; - type Fp3Params: Fp3Config; - type Fp6Params: Fp6Config; ->>>>>>> master type G1Parameters: SWModelParameters; type G2Parameters: SWModelParameters< BaseField = Self::Fp, diff --git a/ff/src/fields/macros.rs b/ff/src/fields/macros.rs deleted file mode 100644 index 3d5293cf5..000000000 --- a/ff/src/fields/macros.rs +++ /dev/null @@ -1,744 +0,0 @@ -macro_rules! impl_prime_field_serializer { - ($field: ident, $params: ident, $byte_size: expr) => { - impl CanonicalSerializeWithFlags for $field

{ - fn serialize_with_flags( - &self, - mut writer: W, - flags: F, - ) -> Result<(), SerializationError> { - // All reasonable `Flags` should be less than 8 bits in size - // (256 values are enough for anyone!) - if F::BIT_SIZE > 8 { - return Err(SerializationError::NotEnoughSpace); - } - - // Calculate the number of bytes required to represent a field element - // serialized with `flags`. If `F::BIT_SIZE < 8`, - // this is at most `$byte_size + 1` - let output_byte_size = buffer_byte_size(P::MODULUS_BITS as usize + F::BIT_SIZE); - - // Write out `self` to a temporary buffer. - // The size of the buffer is $byte_size + 1 because `F::BIT_SIZE` - // is at most 8 bits. - let mut bytes = [0u8; $byte_size + 1]; - self.write(&mut bytes[..$byte_size])?; - - // Mask out the bits of the last byte that correspond to the flag. - bytes[output_byte_size - 1] |= flags.u8_bitmask(); - - writer.write_all(&bytes[..output_byte_size])?; - Ok(()) - } - - // Let `m = 8 * n` for some `n` be the smallest multiple of 8 greater - // than `P::MODULUS_BITS`. - // If `(m - P::MODULUS_BITS) >= F::BIT_SIZE` , then this method returns `n`; - // otherwise, it returns `n + 1`. - fn serialized_size_with_flags(&self) -> usize { - buffer_byte_size(P::MODULUS_BITS as usize + F::BIT_SIZE) - } - } - - impl CanonicalSerialize for $field

{ - #[inline] - fn serialize( - &self, - writer: W, - ) -> Result<(), SerializationError> { - self.serialize_with_flags(writer, EmptyFlags) - } - - #[inline] - fn serialized_size(&self) -> usize { - self.serialized_size_with_flags::() - } - } - - impl CanonicalDeserializeWithFlags for $field

{ - fn deserialize_with_flags( - mut reader: R, - ) -> Result<(Self, F), SerializationError> { - // All reasonable `Flags` should be less than 8 bits in size - // (256 values are enough for anyone!) - if F::BIT_SIZE > 8 { - return Err(SerializationError::NotEnoughSpace); - } - // Calculate the number of bytes required to represent a field element - // serialized with `flags`. If `F::BIT_SIZE < 8`, - // this is at most `$byte_size + 1` - let output_byte_size = buffer_byte_size(P::MODULUS_BITS as usize + F::BIT_SIZE); - - let mut masked_bytes = [0; $byte_size + 1]; - reader.read_exact(&mut masked_bytes[..output_byte_size])?; - - let flags = F::from_u8_remove_flags(&mut masked_bytes[output_byte_size - 1]) - .ok_or(SerializationError::UnexpectedFlags)?; - - Ok((Self::read(&masked_bytes[..])?, flags)) - } - } - - impl CanonicalDeserialize for $field

{ - fn deserialize(reader: R) -> Result { - Self::deserialize_with_flags::(reader).map(|(r, _)| r) - } - } - }; -} - -macro_rules! impl_Fp { - ($Fp:ident, $FpParameters:ident, $BigInteger:ident, $BigIntegerType:ty, $limbs:expr, $field_size:expr) => { - /// Trait for prime field parameters of size at most - #[doc = $field_size] - /// bits. - pub trait $FpParameters: FpParameters> {} - - /// Represents an element of the prime field F_p, where `p == P::MODULUS`. - /// This type can represent elements in any field of size at most - #[doc = $field_size] - /// bits. - #[derive(Derivative)] - #[derivative( - Default(bound = ""), - Hash(bound = ""), - Clone(bound = ""), - Copy(bound = ""), - PartialEq(bound = ""), - Eq(bound = "") - )] - pub struct $Fp

( - pub $BigIntegerType, - #[derivative(Debug = "ignore")] - #[doc(hidden)] - pub PhantomData

, - ); - - impl

$Fp

{ - /// Construct a new prime element directly from its underlying - /// `BigInteger` data type. The `BigInteger` should be in - /// Montgomery representation. If it is not, use `Self::from_repr`. - #[inline] - pub const fn new(element: $BigIntegerType) -> Self { - Self(element, PhantomData) - } - - #[ark_ff_asm::unroll_for_loops] - const fn const_is_zero(&self) -> bool { - let mut is_zero = true; - for i in 0..$limbs { - is_zero &= (self.0).0[i] == 0; - } - is_zero - } - - const fn const_neg(self, modulus: $BigIntegerType) -> Self { - if !self.const_is_zero() { - Self::new(Self::sub_noborrow(&modulus, &self.0)) - } else { - self - } - } - - /// Interpret a string of decimal numbers as a prime field element. - /// Does not accept unnecessary leading zeroes or a blank string. - /// For *internal* use only; please use the `field_new` macro instead - /// of this method - #[doc(hidden)] - pub const fn const_from_str(limbs: &[u64], is_positive: bool, r2: $BigIntegerType, modulus: $BigIntegerType, inv: u64) -> Self { - let mut repr = BigInt::<$limbs>([0; $limbs]); - let mut i = 0; - while i < limbs.len() { - repr.0[i] = limbs[i]; - i += 1; - } - let res = Self::const_from_repr(repr, r2, modulus, inv); - if is_positive { - res - } else { - res.const_neg(modulus) - } - } - - #[inline] - pub(crate) const fn const_from_repr(repr: $BigIntegerType, r2: $BigIntegerType, modulus: $BigIntegerType, inv: u64) -> Self { - let mut r = Self::new(repr); - if r.const_is_zero() { - r - } else { - r = r.const_mul(&$Fp(r2, PhantomData), modulus, inv); - r - } - } - - #[ark_ff_asm::unroll_for_loops] - const fn mul_without_reduce(mut self, other: &Self, modulus: $BigIntegerType, inv: u64) -> Self { - let mut r = [0u64; $limbs * 2]; - - for i in 0..$limbs { - let mut carry = 0; - for j in 0..$limbs { - r[j + i] = mac_with_carry!(r[j + i], (self.0).0[i], (other.0).0[j], &mut carry); - } - r[$limbs + i] = carry; - } - // Montgomery reduction - let mut _carry2 = 0; - for i in 0..$limbs { - let k = r[i].wrapping_mul(inv); - let mut carry = 0; - mac_with_carry!(r[i], k, modulus.0[0], &mut carry); - for j in 1..$limbs { - r[j + i] = mac_with_carry!(r[j + i], k, modulus.0[j], &mut carry); - } - r[$limbs + i] = adc!(r[$limbs + i], _carry2, &mut carry); - _carry2 = carry; - } - - for i in 0..$limbs { - (self.0).0[i] = r[$limbs + i]; - } - self - } - - #[ark_ff_asm::unroll_for_loops] - const fn const_mul(mut self, other: &Self, modulus: $BigIntegerType, inv: u64) -> Self { - self = self.mul_without_reduce(other, modulus, inv); - self.const_reduce(modulus) - } - - - #[ark_ff_asm::unroll_for_loops] - const fn const_is_valid(&self, modulus: $BigIntegerType) -> bool { - for i in 0..$limbs { - if (self.0).0[($limbs - i - 1)] < modulus.0[($limbs - i - 1)] { - return true - } else if (self.0).0[($limbs - i - 1)] > modulus.0[($limbs - i - 1)] { - return false - } - } - false - } - - #[inline] - const fn const_reduce(mut self, modulus: $BigIntegerType) -> Self { - if !self.const_is_valid(modulus) { - self.0 = Self::sub_noborrow(&self.0, &modulus); - } - self - } - - #[ark_ff_asm::unroll_for_loops] - // need unused assignment because the last iteration of the loop produces an assignment - // to `borrow` that is unused. - #[allow(unused_assignments)] - const fn sub_noborrow(a: &$BigIntegerType, b: &$BigIntegerType) -> $BigInteger { - let mut a = *a; - let mut borrow = 0; - for i in 0..$limbs { - a.0[i] = sbb!(a.0[i], b.0[i], &mut borrow); - } - a - } - } - - impl $Fp

{ - #[inline(always)] - pub(crate) fn is_valid(&self) -> bool { - self.0 < P::MODULUS - } - - #[inline] - fn reduce(&mut self) { - if !self.is_valid() { - self.0.sub_noborrow(&P::MODULUS); - } - } - } - - impl

ark_std::fmt::Debug for $Fp

{ - fn fmt(&self, f: &mut ark_std::fmt::Formatter<'_>) -> ark_std::fmt::Result { - ark_std::fmt::Debug::fmt(&self.0, f) - } - } - - impl Zero for $Fp

{ - #[inline] - fn zero() -> Self { - $Fp::

($BigInteger::from(0), PhantomData) - } - - #[inline] - fn is_zero(&self) -> bool { - self.0.is_zero() - } - } - - impl One for $Fp

{ - #[inline] - fn one() -> Self { - $Fp::

(P::R, PhantomData) - } - - #[inline] - fn is_one(&self) -> bool { - self.0 == P::R - } - } - - impl Field for $Fp

{ - type BasePrimeField = Self; - - fn extension_degree() -> u64 { - 1 - } - - fn from_base_prime_field_elems(elems: &[Self::BasePrimeField]) -> Option { - if elems.len() != (Self::extension_degree() as usize) { - return None; - } - Some(elems[0]) - } - - #[inline] - fn double(&self) -> Self { - let mut temp = *self; - temp.double_in_place(); - temp - } - - #[inline] - fn double_in_place(&mut self) -> &mut Self { - // This cannot exceed the backing capacity. - self.0.mul2(); - // However, it may need to be reduced. - self.reduce(); - self - } - - #[inline] - fn characteristic() -> &'static [u64] { - P::MODULUS.as_ref() - } - - #[inline] - fn from_random_bytes_with_flags(bytes: &[u8]) -> Option<(Self, F)> { - if F::BIT_SIZE > 8 { - return None - } else { - let mut result_bytes = [0u8; $limbs * 8 + 1]; - // Copy the input into a temporary buffer. - result_bytes.iter_mut().zip(bytes).for_each(|(result, input)| { - *result = *input; - }); - // This mask retains everything in the last limb - // that is below `P::MODULUS_BITS`. - let last_limb_mask = (u64::MAX >> P::REPR_SHAVE_BITS).to_le_bytes(); - let mut last_bytes_mask = [0u8; 9]; - last_bytes_mask[..8].copy_from_slice(&last_limb_mask); - - - // Length of the buffer containing the field element and the flag. - let output_byte_size = buffer_byte_size(P::MODULUS_BITS as usize + F::BIT_SIZE); - // Location of the flag is the last byte of the serialized - // form of the field element. - let flag_location = output_byte_size - 1; - - // At which byte is the flag located in the last limb? - let flag_location_in_last_limb = flag_location - (8 * ($limbs - 1)); - - // Take all but the last 9 bytes. - let last_bytes = &mut result_bytes[8 * ($limbs - 1)..]; - - // The mask only has the last `F::BIT_SIZE` bits set - let flags_mask = u8::MAX.checked_shl(8 - (F::BIT_SIZE as u32)).unwrap_or(0); - - // Mask away the remaining bytes, and try to reconstruct the - // flag - let mut flags: u8 = 0; - for (i, (b, m)) in last_bytes.iter_mut().zip(&last_bytes_mask).enumerate() { - if i == flag_location_in_last_limb { - flags = *b & flags_mask - } - *b &= m; - } - Self::deserialize(&result_bytes[..($limbs * 8)]) - .ok() - .and_then(|f| F::from_u8(flags).map(|flag| (f, flag))) - } - } - - #[inline] - fn legendre(&self) -> LegendreSymbol { - use crate::fields::LegendreSymbol::*; - - // s = self^((MODULUS - 1) // 2) - let s = self.pow(P::MODULUS_MINUS_ONE_DIV_TWO); - if s.is_zero() { - Zero - } else if s.is_one() { - QuadraticResidue - } else { - QuadraticNonResidue - } - } - - #[inline] - fn sqrt(&self) -> Option { - sqrt_impl!(Self, P, self) - } - - fn sqrt_in_place(&mut self) -> Option<&mut Self> { - (*self).sqrt().map(|sqrt| { - *self = sqrt; - self - }) - } - - #[inline] - fn square(&self) -> Self { - let mut temp = self.clone(); - temp.square_in_place(); - temp - } - - impl_field_square_in_place!($limbs); - - #[inline] - fn inverse(&self) -> Option { - if self.is_zero() { - None - } else { - // Guajardo Kumar Paar Pelzl - // Efficient Software-Implementation of Finite Fields with Applications to - // Cryptography - // Algorithm 16 (BEA for Inversion in Fp) - - let one = $BigInteger::from(1); - - let mut u = self.0; - let mut v = P::MODULUS; - let mut b = $Fp::

(P::R2, PhantomData); // Avoids unnecessary reduction step. - let mut c = Self::zero(); - - while u != one && v != one { - while u.is_even() { - u.div2(); - - if b.0.is_even() { - b.0.div2(); - } else { - b.0.add_nocarry(&P::MODULUS); - b.0.div2(); - } - } - - while v.is_even() { - v.div2(); - - if c.0.is_even() { - c.0.div2(); - } else { - c.0.add_nocarry(&P::MODULUS); - c.0.div2(); - } - } - - if v < u { - u.sub_noborrow(&v); - b.sub_assign(&c); - } else { - v.sub_noborrow(&u); - c.sub_assign(&b); - } - } - - if u == one { - Some(b) - } else { - Some(c) - } - } - } - - fn inverse_in_place(&mut self) -> Option<&mut Self> { - if let Some(inverse) = self.inverse() { - *self = inverse; - Some(self) - } else { - None - } - } - - /// The Frobenius map has no effect in a prime field. - #[inline] - fn frobenius_map(&mut self, _: usize) {} - } - - impl PrimeField for $Fp

{ - type Params = P; - type BigInt = $BigIntegerType; - - #[inline] - fn from_repr(r: $BigIntegerType) -> Option { - let mut r = $Fp(r, PhantomData); - if r.is_zero() { - Some(r) - } else if r.is_valid() { - r *= &$Fp(P::R2, PhantomData); - Some(r) - } else { - None - } - } - - impl_field_into_repr!($limbs, $BigIntegerType); - } - - impl FftField for $Fp

{ - type FftParams = P; - - #[inline] - fn two_adic_root_of_unity() -> Self { - $Fp::

(P::TWO_ADIC_ROOT_OF_UNITY, PhantomData) - } - - #[inline] - fn large_subgroup_root_of_unity() -> Option { - Some($Fp::

(P::LARGE_SUBGROUP_ROOT_OF_UNITY?, PhantomData)) - } - - #[inline] - fn multiplicative_generator() -> Self { - $Fp::

(P::GENERATOR, PhantomData) - } - } - - /// Note that this implementation of `Ord` compares field elements viewing - /// them as integers in the range 0, 1, ..., P::MODULUS - 1. However, other - /// implementations of `PrimeField` might choose a different ordering, and - /// as such, users should use this `Ord` for applications where - /// any ordering suffices (like in a BTreeMap), and not in applications - /// where a particular ordering is required. - impl Ord for $Fp

{ - #[inline(always)] - fn cmp(&self, other: &Self) -> Ordering { - self.into_repr().cmp(&other.into_repr()) - } - } - - /// Note that this implementation of `PartialOrd` compares field elements viewing - /// them as integers in the range 0, 1, ..., `P::MODULUS` - 1. However, other - /// implementations of `PrimeField` might choose a different ordering, and - /// as such, users should use this `PartialOrd` for applications where - /// any ordering suffices (like in a BTreeMap), and not in applications - /// where a particular ordering is required. - impl PartialOrd for $Fp

{ - #[inline(always)] - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } - } - - impl_prime_field_from_int!($Fp, 128, $FpParameters, $limbs); - impl_prime_field_from_int!($Fp, 64, $FpParameters, $limbs); - impl_prime_field_from_int!($Fp, 32, $FpParameters, $limbs); - impl_prime_field_from_int!($Fp, 16, $FpParameters, $limbs); - impl_prime_field_from_int!($Fp, 8, $FpParameters, $limbs); - impl_prime_field_from_int!($Fp, bool, $FpParameters, $limbs); - - impl_prime_field_standard_sample!($Fp, $FpParameters); - - impl_prime_field_serializer!($Fp, $FpParameters, $limbs * 8); - - impl ToBytes for $Fp

{ - #[inline] - fn write(&self, writer: W) -> IoResult<()> { - self.into_repr().write(writer) - } - } - - impl FromBytes for $Fp

{ - #[inline] - fn read(reader: R) -> IoResult { - $BigInteger::read(reader).and_then(|b| - match $Fp::from_repr(b) { - Some(f) => Ok(f), - None => Err(crate::error("FromBytes::read failed")), - }) - } - } - - impl FromStr for $Fp

{ - type Err = (); - - /// Interpret a string of numbers as a (congruent) prime field element. - /// Does not accept unnecessary leading zeroes or a blank string. - fn from_str(s: &str) -> Result { - if s.is_empty() { - return Err(()); - } - - if s == "0" { - return Ok(Self::zero()); - } - - let mut res = Self::zero(); - - let ten = Self::from(::BigInt::from(10)); - - let mut first_digit = true; - - for c in s.chars() { - match c.to_digit(10) { - Some(c) => { - if first_digit { - if c == 0 { - return Err(()); - } - - first_digit = false; - } - - res.mul_assign(&ten); - let digit = Self::from(u64::from(c)); - res.add_assign(&digit); - }, - None => { - return Err(()); - }, - } - } - if !res.is_valid() { - Err(()) - } else { - Ok(res) - } - } - } - - /// Outputs a string containing the value of `self`, chunked up into - /// 64-bit limbs. - impl Display for $Fp

{ - #[inline] - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, stringify!($Fp "({})"), self.into_repr()) - } - } - - impl Neg for $Fp

{ - type Output = Self; - #[inline] - #[must_use] - fn neg(self) -> Self { - if !self.is_zero() { - let mut tmp = P::MODULUS; - tmp.sub_noborrow(&self.0); - $Fp::

(tmp, PhantomData) - } else { - self - } - } - } - - impl<'a, P: $FpParameters> Add<&'a $Fp

> for $Fp

{ - type Output = Self; - - #[inline] - fn add(mut self, other: &Self) -> Self { - self.add_assign(other); - self - } - } - - impl<'a, P: $FpParameters> Sub<&'a $Fp

> for $Fp

{ - type Output = Self; - - #[inline] - fn sub(mut self, other: &Self) -> Self { - self.sub_assign(other); - self - } - } - - impl<'a, P: $FpParameters> Mul<&'a $Fp

> for $Fp

{ - type Output = Self; - - #[inline] - fn mul(mut self, other: &Self) -> Self { - self.mul_assign(other); - self - } - } - - impl<'a, P: $FpParameters> Div<&'a $Fp

> for $Fp

{ - type Output = Self; - - /// Returns `self * other.inverse()` if `other.inverse()` is `Some`, and - /// panics otherwise. - #[inline] - fn div(mut self, other: &Self) -> Self { - self.mul_assign(&other.inverse().unwrap()); - self - } - } - - impl_additive_ops_from_ref!($Fp, $FpParameters); - impl_multiplicative_ops_from_ref!($Fp, $FpParameters); - - impl<'a, P: $FpParameters> AddAssign<&'a Self> for $Fp

{ - #[inline] - fn add_assign(&mut self, other: &Self) { - // This cannot exceed the backing capacity. - self.0.add_nocarry(&other.0); - // However, it may need to be reduced - self.reduce(); - } - } - - impl<'a, P: $FpParameters> SubAssign<&'a Self> for $Fp

{ - #[inline] - fn sub_assign(&mut self, other: &Self) { - // If `other` is larger than `self`, add the modulus to self first. - if other.0 > self.0 { - self.0.add_nocarry(&P::MODULUS); - } - self.0.sub_noborrow(&other.0); - } - } - - impl<'a, P: $FpParameters> MulAssign<&'a Self> for $Fp

{ - impl_field_mul_assign!($limbs); - } - - /// Computes `self *= other.inverse()` if `other.inverse()` is `Some`, and - /// panics otherwise. - impl<'a, P: $FpParameters> DivAssign<&'a Self> for $Fp

{ - #[inline] - fn div_assign(&mut self, other: &Self) { - self.mul_assign(&other.inverse().unwrap()); - } - } - - impl zeroize::Zeroize for $Fp

{ - // The phantom data does not contain element-specific data - // and thus does not need to be zeroized. - fn zeroize(&mut self) { - self.0.zeroize(); - } - } - - impl From for $Fp

{ - #[inline] - fn from(val: num_bigint::BigUint) -> $Fp

{ - $Fp::

::from_le_bytes_mod_order(&val.to_bytes_le()) - } - } - - impl From<$Fp

> for num_bigint::BigUint { - #[inline] - fn from(other: $Fp

) -> Self { - other.into_repr().into() - } - } - } -} diff --git a/test-templates/src/fields.rs b/test-templates/src/fields.rs index 547a210dc..9b7c89621 100644 --- a/test-templates/src/fields.rs +++ b/test-templates/src/fields.rs @@ -1,13 +1,9 @@ #![allow(unused)] #![allow(clippy::eq_op)] -<<<<<<< HEAD -use ark_ff::fields::{FftField, FftParameters, Field, LegendreSymbol, PrimeField}; -======= use ark_ff::{ - fields::{FftField, Field, LegendreSymbol, PrimeField, SquareRootField}, + fields::{FftField, Field, LegendreSymbol, PrimeField}, Fp, MontBackend, MontConfig, }; ->>>>>>> master use ark_serialize::{buffer_bit_byte_size, Flags, SWFlags}; use ark_std::{io::Cursor, rand::Rng}; From 08dc4d649beed6f44fa65ee188b871c95d961460 Mon Sep 17 00:00:00 2001 From: Solomon Date: Mon, 7 Feb 2022 18:46:25 -0800 Subject: [PATCH 3/7] Reverted changes to track master --- ec/src/models/bls12/mod.rs | 8 ++++---- ec/src/models/bn/mod.rs | 8 ++++---- ec/src/models/bw6/mod.rs | 8 ++++---- ec/src/models/mnt4/mod.rs | 8 ++++---- ec/src/models/mnt6/mod.rs | 8 ++++---- ff/src/fields/models/fp3.rs | 7 ++++--- ff/src/fields/models/quadratic_extension.rs | 2 +- ff/src/lib.rs | 2 +- 8 files changed, 26 insertions(+), 25 deletions(-) diff --git a/ec/src/models/bls12/mod.rs b/ec/src/models/bls12/mod.rs index f51d559db..25b046c81 100644 --- a/ec/src/models/bls12/mod.rs +++ b/ec/src/models/bls12/mod.rs @@ -4,8 +4,8 @@ use crate::{ }; use ark_ff::fields::{ fp12_2over3over2::{Fp12, Fp12Parameters}, - fp2::Fp2Parameters, - fp6_3over2::Fp6Parameters, + fp2::Fp2Config, + fp6_3over2::Fp6Config, BitIteratorBE, Field, Fp2, PrimeField, }; use core::marker::PhantomData; @@ -34,8 +34,8 @@ pub trait Bls12Parameters: 'static { const TWIST_TYPE: TwistType; type Fp: PrimeField + Into<::BigInt>; - type Fp2Params: Fp2Parameters; - type Fp6Params: Fp6Parameters; + type Fp2Params: Fp2Config; + type Fp6Params: Fp6Config; type Fp12Params: Fp12Parameters; type G1Parameters: SWModelParameters; type G2Parameters: SWModelParameters< diff --git a/ec/src/models/bn/mod.rs b/ec/src/models/bn/mod.rs index c61a5a05c..c303641f6 100644 --- a/ec/src/models/bn/mod.rs +++ b/ec/src/models/bn/mod.rs @@ -4,8 +4,8 @@ use crate::{ }; use ark_ff::fields::{ fp12_2over3over2::{Fp12, Fp12Parameters}, - fp2::Fp2Parameters, - fp6_3over2::Fp6Parameters, + fp2::Fp2Config, + fp6_3over2::Fp6Config, Field, Fp2, PrimeField, }; use num_traits::One; @@ -32,8 +32,8 @@ pub trait BnParameters: 'static { const TWIST_MUL_BY_Q_X: Fp2; const TWIST_MUL_BY_Q_Y: Fp2; type Fp: PrimeField + Into<::BigInt>; - type Fp2Params: Fp2Parameters; - type Fp6Params: Fp6Parameters; + type Fp2Params: Fp2Config; + type Fp6Params: Fp6Config; type Fp12Params: Fp12Parameters; type G1Parameters: SWModelParameters; type G2Parameters: SWModelParameters< diff --git a/ec/src/models/bw6/mod.rs b/ec/src/models/bw6/mod.rs index 3dc001d7f..45189d7f3 100644 --- a/ec/src/models/bw6/mod.rs +++ b/ec/src/models/bw6/mod.rs @@ -3,8 +3,8 @@ use crate::{ PairingEngine, }; use ark_ff::fields::{ - fp3::Fp3Parameters, - fp6_2over3::{Fp6, Fp6Parameters}, + fp3::Fp3Config, + fp6_2over3::{Fp6, Fp6Config}, BitIteratorBE, Field, PrimeField, }; use num_traits::One; @@ -25,8 +25,8 @@ pub trait BW6Parameters: 'static + Eq + PartialEq { const ATE_LOOP_COUNT_2_IS_NEGATIVE: bool; const TWIST_TYPE: TwistType; type Fp: PrimeField + Into<::BigInt>; - type Fp3Params: Fp3Parameters; - type Fp6Params: Fp6Parameters; + type Fp3Params: Fp3Config; + type Fp6Params: Fp6Config; type G1Parameters: SWModelParameters; type G2Parameters: SWModelParameters< BaseField = Self::Fp, diff --git a/ec/src/models/mnt4/mod.rs b/ec/src/models/mnt4/mod.rs index 04544dbad..c5a5d2cdc 100644 --- a/ec/src/models/mnt4/mod.rs +++ b/ec/src/models/mnt4/mod.rs @@ -3,8 +3,8 @@ use crate::{ PairingEngine, }; use ark_ff::{ - fp2::{Fp2, Fp2Parameters}, - fp4::{Fp4, Fp4Parameters}, + fp2::{Fp2, Fp2Config}, + fp4::{Fp4, Fp4Config}, BitIteratorBE, Field, PrimeField, }; use num_traits::{One, Zero}; @@ -32,8 +32,8 @@ pub trait MNT4Parameters: 'static { const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: ::BigInt; type Fp: PrimeField + Into<::BigInt>; type Fr: PrimeField + Into<::BigInt>; - type Fp2Params: Fp2Parameters; - type Fp4Params: Fp4Parameters; + type Fp2Params: Fp2Config; + type Fp4Params: Fp4Config; type G1Parameters: SWModelParameters; type G2Parameters: SWModelParameters< BaseField = Fp2, diff --git a/ec/src/models/mnt6/mod.rs b/ec/src/models/mnt6/mod.rs index 9ad0fb124..8bb200b40 100644 --- a/ec/src/models/mnt6/mod.rs +++ b/ec/src/models/mnt6/mod.rs @@ -3,8 +3,8 @@ use crate::{ PairingEngine, }; use ark_ff::{ - fp3::{Fp3, Fp3Parameters}, - fp6_2over3::{Fp6, Fp6Parameters}, + fp3::{Fp3, Fp3Config}, + fp6_2over3::{Fp6, Fp6Config}, BitIteratorBE, Field, PrimeField, }; use num_traits::{One, Zero}; @@ -32,8 +32,8 @@ pub trait MNT6Parameters: 'static { const FINAL_EXPONENT_LAST_CHUNK_ABS_OF_W0: ::BigInt; type Fp: PrimeField + Into<::BigInt>; type Fr: PrimeField + Into<::BigInt>; - type Fp3Params: Fp3Parameters; - type Fp6Params: Fp6Parameters; + type Fp3Params: Fp3Config; + type Fp6Params: Fp6Config; type G1Parameters: SWModelParameters; type G2Parameters: SWModelParameters< BaseField = Fp3, diff --git a/ff/src/fields/models/fp3.rs b/ff/src/fields/models/fp3.rs index 683ffeba6..eb1cf959c 100644 --- a/ff/src/fields/models/fp3.rs +++ b/ff/src/fields/models/fp3.rs @@ -2,9 +2,10 @@ use super::cubic_extension::*; use crate::fields::*; use core::marker::PhantomData; -pub trait Fp3Parameters: 'static + Send + Sync { +/// Trait that specifies constants and methods for defining degree-three extension fields. +pub trait Fp3Config: 'static + Send + Sync + Sized { + /// Base prime field underlying this extension. type Fp: PrimeField; - /// Cubic non-residue in `Self::Fp` used to construct the extension /// field. That is, `NONRESIDUE` is such that the cubic polynomial /// `f(X) = X^3 - Self::NONRESIDUE` in Fp\[X\] is irreducible in `Self::Fp`. @@ -98,7 +99,7 @@ impl Fp3

{ } } -impl Field for Fp3

{ +impl Field for Fp3

{ /// Returns the Legendre symbol. fn legendre(&self) -> LegendreSymbol { self.norm().legendre() diff --git a/ff/src/fields/models/quadratic_extension.rs b/ff/src/fields/models/quadratic_extension.rs index 9d1a5c548..2f974f2bd 100644 --- a/ff/src/fields/models/quadratic_extension.rs +++ b/ff/src/fields/models/quadratic_extension.rs @@ -387,7 +387,7 @@ impl Field for QuadExtField

{ } } -impl<'a, P: QuadExtParameters> Field for QuadExtField

+impl<'a, P: QuadExtConfig> Field for QuadExtField

where P::BaseField: Field + From, { diff --git a/ff/src/lib.rs b/ff/src/lib.rs index 293140857..002d74a11 100644 --- a/ff/src/lib.rs +++ b/ff/src/lib.rs @@ -42,7 +42,7 @@ pub use ark_std::vec; pub mod prelude { pub use crate::biginteger::BigInteger; - pub use crate::fields::{Field, FpParameters, PrimeField}; + pub use crate::fields::{Field, PrimeField}; pub use ark_std::UniformRand; From a518c6784d5c03950cc1455ce85eabd4bd25fb08 Mon Sep 17 00:00:00 2001 From: Solomon Date: Mon, 7 Feb 2022 18:47:37 -0800 Subject: [PATCH 4/7] Added Tonelli-Shanks and Shanks sqrt algorithms for cubic extension fields --- ff/src/fields/models/cubic_extension.rs | 91 ++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/ff/src/fields/models/cubic_extension.rs b/ff/src/fields/models/cubic_extension.rs index 247ae0b13..271c89d20 100644 --- a/ff/src/fields/models/cubic_extension.rs +++ b/ff/src/fields/models/cubic_extension.rs @@ -263,6 +263,10 @@ impl Field for CubicExtField

{ self } + fn sqrt(&self) -> Option { + tonelli_shanks(self) + } + fn inverse(&self) -> Option { if self.is_zero() { None @@ -314,8 +318,93 @@ impl Field for CubicExtField

{ } } +fn tonelli_shanks(f: &CubicExtField

) -> Option> { + // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) + // Actually this is just normal Tonelli-Shanks; since `P::Generator` + // is a quadratic non-residue, `P::ROOT_OF_UNITY = P::GENERATOR ^ t` + // is also a quadratic non-residue (since `t` is odd). + if f.is_zero() { + return Some(CubicExtField::zero()); + } + // Try computing the square root (x at the end of the algorithm) + // Check at the end of the algorithm if x was a square root + // Begin Tonelli-Shanks + let mut z = CubicExtField::qnr_to_t(); + let mut w = f.pow(P::TRACE_MINUS_ONE_DIV_TWO); + let mut x = w * f; + let mut b = x * &w; + + let mut v = P::TWO_ADICITY as usize; + + while !b.is_one() { + let mut k = 0usize; + + let mut b2k = b; + while !b2k.is_one() { + // invariant: b2k = b^(2^k) after entering this loop + b2k.square_in_place(); + k += 1; + } + + if k == (P::TWO_ADICITY as usize) { + // We are in the case where self^(T * 2^k) = x^(P::MODULUS - 1) = 1, + // which means that no square root exists. + return None; + } + let j = v - k; + w = z; + for _ in 1..j { + w.square_in_place(); + } + + z = w.square(); + b *= &z; + x *= &w; + v = k; + } + // Is x the square root? If so, return it. + if (x.square() == *f) { + return Some(x); + } else { + // Consistency check that if no square root is found, + // it is because none exists. + #[cfg(debug_assertions)] + { + use crate::fields::LegendreSymbol::*; + if (f.legendre() != QuadraticNonResidue) { + panic!("Input has a square root per its legendre symbol, but it was not found") + } + } + None + } +} + +fn shanks(f: &CubicExtField

) -> Option> { + // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2) + // Using decomposition of (q-3)/ 4 = alpha + p[p(alpha) + (3a + 2)]*sum_i^((m-3)/2) p^{2i} + + // t1 = f^alpha + let t1 = f.pow(\alpha); + // t2 = f^p + let t2 = f.frobenius(1); + // t3 = f^((p^2)alpha) * f^(3p(alpha) + 2p) + let t3 = t2.frobenius(1).pow(alpha) * (t2.pow(3).pow(alpha) + t2.square()); + let mut r = CubicExtField::one(); + let n = (CubicExtField::extension_degree() - 3)/2; + for i in 1..(n+1) { + r *= t3.frobenius(2 * i); + + let mut a_1 = t1 * r; + let mut x = a_1 * f; + let mut a_0 = a_1 * x; + if (a_0 == -CubicExtField::one()) { + return None; + } + x +} + /// `CubicExtField` elements are ordered lexicographically. -impl Ord for CubicExtField

{ +impl Ord for CubicExtField

-> { #[inline(always)] fn cmp(&self, other: &Self) -> Ordering { let c2_cmp = self.c2.cmp(&other.c2); From df8d67cef4f83e3528bda13ca227f2471e9e20c8 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 7 Feb 2022 18:54:45 -0800 Subject: [PATCH 5/7] Apply suggestions from code review --- ff/src/fields/models/cubic_extension.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ff/src/fields/models/cubic_extension.rs b/ff/src/fields/models/cubic_extension.rs index 271c89d20..f68c2b73f 100644 --- a/ff/src/fields/models/cubic_extension.rs +++ b/ff/src/fields/models/cubic_extension.rs @@ -371,7 +371,7 @@ fn tonelli_shanks(f: &CubicExtField

) -> Option(f: &CubicExtField

) -> Option> { // Using decomposition of (q-3)/ 4 = alpha + p[p(alpha) + (3a + 2)]*sum_i^((m-3)/2) p^{2i} // t1 = f^alpha - let t1 = f.pow(\alpha); + let t1 = f.pow(alpha); // t2 = f^p let t2 = f.frobenius(1); // t3 = f^((p^2)alpha) * f^(3p(alpha) + 2p) @@ -404,7 +404,7 @@ fn shanks(f: &CubicExtField

) -> Option> { } /// `CubicExtField` elements are ordered lexicographically. -impl Ord for CubicExtField

-> { +impl Ord for CubicExtField

{ #[inline(always)] fn cmp(&self, other: &Self) -> Ordering { let c2_cmp = self.c2.cmp(&other.c2); From d9136e5282a4e6ef58d1521b1f6ee0b5c1f1d5c9 Mon Sep 17 00:00:00 2001 From: Solomon Date: Tue, 29 Mar 2022 13:40:34 -0700 Subject: [PATCH 6/7] WIP: Drafted square root algorithms for cubic extensions --- ff/src/fields/mod.rs | 2 +- ff/src/fields/models/cubic_extension.rs | 111 ++++++++++++++++++++++-- 2 files changed, 104 insertions(+), 9 deletions(-) diff --git a/ff/src/fields/mod.rs b/ff/src/fields/mod.rs index ac3931e1b..efaf9ddd9 100644 --- a/ff/src/fields/mod.rs +++ b/ff/src/fields/mod.rs @@ -84,7 +84,7 @@ pub trait Field: + From { type BasePrimeField: PrimeField; - + const SqrtPrecomp: SqrtPrecomputation; /// Returns the characteristic of the field, /// in little-endian representation. fn characteristic() -> &'static [u64] { diff --git a/ff/src/fields/models/cubic_extension.rs b/ff/src/fields/models/cubic_extension.rs index 271c89d20..ec666791d 100644 --- a/ff/src/fields/models/cubic_extension.rs +++ b/ff/src/fields/models/cubic_extension.rs @@ -38,6 +38,7 @@ pub trait CubicExtConfig: 'static + Send + Sync { /// Frobenius endomorphism. type FrobCoeff: Field; + const PRECOMP : SqrtPrecomputation; /// The degree of the extension over the base prime field. const DEGREE_OVER_BASE_PRIME_FIELD: usize; @@ -183,6 +184,7 @@ impl One for CubicExtField

{ } impl Field for CubicExtField

{ + const SqrtPrecomp: SqrtPrecomputation = P::PRECOMP; type BasePrimeField = P::BasePrimeField; fn extension_degree() -> u64 { @@ -318,7 +320,33 @@ impl Field for CubicExtField

{ } } -fn tonelli_shanks(f: &CubicExtField

) -> Option> { +public enum SqrtPrecomputation { + ThreeModFour, + FiveModEight{TRACE: F::BigInt}, + NineModSixteen{TRACE: F::BigInt, d: F::BigInt, e: F::BigInt, c: F::BigInt}, + OneModSixteen{TRACE: F::BigInt, TRACE_MINUS_ONE_DIV_TWO: F::BigInt}, +} + +impl SqrtPrecomputation { + fn sqrt(&self) -> Option { + match self { + SqrtPrecomputation::ThreeModFour => { + shanks(self) + }, + SqrtPrecomputation::FiveModEight{TRACE: F::BigInt} => { + atkin(self, TRACE) + }, + SqrtPrecomputation::NineModSixteen{TRACE: F::BigInt, d: F::BigInt, e: F::BigInt, c: F::BigInt} => { + kong(self, TRACE, d, e, c) + }, + SqrtPrecomputation::OneModSixteen{TRACE: F::BigInt, TRACE_MINUS_ONE_DIV_TWO: F::BigInt} => { + tonelli_shanks(self, TRACE, TRACE_MINUS_ONE_DIV_TWO) + } + } + } +} + +fn tonelli_shanks(f: &CubicExtField

, TRACE: F::BigInt, TRACE_MINUS_ONE_DIV_TWO: F::BigInt) -> Option> { // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) // Actually this is just normal Tonelli-Shanks; since `P::Generator` // is a quadratic non-residue, `P::ROOT_OF_UNITY = P::GENERATOR ^ t` @@ -330,7 +358,7 @@ fn tonelli_shanks(f: &CubicExtField

) -> Option(f: &CubicExtField

) -> Option> { // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2) // Using decomposition of (q-3)/ 4 = alpha + p[p(alpha) + (3a + 2)]*sum_i^((m-3)/2) p^{2i} + // alpha = (p - 3) / 4; + let alpha = (f.characteristic() - 3) / 4; // t1 = f^alpha - let t1 = f.pow(\alpha); + let t1 = f.pow(alpha); // t2 = f^p - let t2 = f.frobenius(1); + let t2 = f.frobenius_map(1); // t3 = f^((p^2)alpha) * f^(3p(alpha) + 2p) - let t3 = t2.frobenius(1).pow(alpha) * (t2.pow(3).pow(alpha) + t2.square()); + let t3 = t2.frobenius_map(1).pow(alpha) * (t2.pow(3).pow(alpha) + t2.square()); let mut r = CubicExtField::one(); let n = (CubicExtField::extension_degree() - 3)/2; for i in 1..(n+1) { - r *= t3.frobenius(2 * i); + r *= t3.frobenius_map(2 * i); let mut a_1 = t1 * r; - let mut x = a_1 * f; - let mut a_0 = a_1 * x; + let mut a_0 = a_1 * a_1 * f; + if (a_0 == -CubicExtField::one()) { + return None; + } + x +} + +fn atkin(f: &CubicExtField

, TRACE: F::BigInt) -> Option> { + // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 3) + // Using decomposition of (q-5)/ 8 = alpha + p[p(alpha) + (5a + 3)]*sum_i^((m-3)/2) p^{2i} + // Precomputation + let t = TRACE; + // alpha = (p - 5) / 8 + let alpha = (f.characteristic() - 5) / 8; + // t1 = f^alpha + let t1 = f.pow(alpha); + // t2 = f^p + let t2 = f.frobenius_map(1); + // t3 = f^((p^2)alpha) * f^(5p(alpha) + 3p) + let t3 = t2.frobenius_map(1).pow(alpha) * (t2.pow(5).pow(alpha) + t2.pow(3)); + let mut r = CubicExtField::one(); + let n = (CubicExtField::extension_degree() - 3)/2; + for i in 1..(n+1) { + r *= t3.frobenius_map(2 * i); + let mut a_1 = t1 * r; + let mut a_0 = a_1 * a_1 * f; + a_0 *= a_0; if (a_0 == -CubicExtField::one()) { return None; } + let b = t * a_1; + let i = 2 * b * f * b; + let x = a * b * (i - 1); x } +fn kong(f: &CubicExtField

, TRACE: F::BigInt, d: F::BigInt, e: F::BigInt, c: F::BigInt) -> Option> { + // https://eprint.iacr.org/2012/685.pdf (page 11, algorithm 4) + // Using decomposition of (q-9)/16 = alpha + p[p(alpha) + (9a + 5)]*sum_i^((m-3)/2) p^{2i} + // Precomputation + let t = TRACE; + // alpha = (p - 9) / 16 + let alpha = (f.characteristic() - 9) / 16; + // t1 = f^alpha + let t1 = f.pow(alpha); + // t2 = f^p + let t2 = f.frobenius_map(1); + // t3 = f^((p^2)alpha) * f^(9p(alpha) + 5p) + let t3 = t2.frobenius_map(1).pow(alpha) * (t2.pow(9).pow(alpha) + t2.pow(5)); + let mut r = CubicExtField::one(); + let n = (CubicExtField::extension_degree() - 3)/2; + for i in 1..(n+1) { + r *= t3.frobenius_map(2 * i); + let mut a_1 = t1 * r; + let mut a_0 = a_1 * a_1 * f; + a_0 = a_0.pow(4); + if (a_0 == -CubicExtField::one()) { + return None; + } + let b = t * a_1; + let i = 2 * b * f * b; + let r = i * i; + if (r == -CubicExtField::one()) { + let x = a * b * (i - 1); + return x; + } else { + let u = b * d; + let i = 2 * u * u * e * f; + let x = u * c * f * (i - 1); + return x; + } +} + /// `CubicExtField` elements are ordered lexicographically. impl Ord for CubicExtField

-> { #[inline(always)] From 547542608536a7bfdbd68a66b022069d5ae5becb Mon Sep 17 00:00:00 2001 From: Solomon Date: Tue, 29 Mar 2022 15:24:03 -0700 Subject: [PATCH 7/7] Small fix --- ff/src/fields/models/cubic_extension.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ff/src/fields/models/cubic_extension.rs b/ff/src/fields/models/cubic_extension.rs index cb69fbc69..b9ccbb4d9 100644 --- a/ff/src/fields/models/cubic_extension.rs +++ b/ff/src/fields/models/cubic_extension.rs @@ -266,7 +266,7 @@ impl Field for CubicExtField

{ } fn sqrt(&self) -> Option { - tonelli_shanks(self) + self.SqrtPrecomp.sqrt() } fn inverse(&self) -> Option {