diff --git a/bench-templates/src/macros/ec.rs b/bench-templates/src/macros/ec.rs index d561fcfc9..b69a664ae 100644 --- a/bench-templates/src/macros/ec.rs +++ b/bench-templates/src/macros/ec.rs @@ -3,10 +3,10 @@ macro_rules! ec_bench { ($curve_name:expr, $Group:ident) => { $crate::paste! { mod [<$Group:lower>] { - use ark_ec::Group; + use ark_ec::PrimeGroup; use super::*; - type Scalar = <$Group as Group>::ScalarField; + type Scalar = <$Group::ScalarField; fn rand(c: &mut $crate::criterion::Criterion) { let name = format!("{}::{}", $curve_name, stringify!($Group)); use ark_std::UniformRand; @@ -18,11 +18,11 @@ macro_rules! ec_bench { } fn arithmetic(c: &mut $crate::criterion::Criterion) { - use ark_ec::{CurveGroup, Group}; + use ark_ec::{CurveGroup, PrimeGroup}; use ark_std::UniformRand; let name = format!("{}::{}", $curve_name, stringify!($Group)); - type Scalar = <$Group as Group>::ScalarField; + type Scalar = $Group::ScalarField; const SAMPLES: usize = 1000; let mut rng = ark_std::test_rng(); let mut arithmetic = diff --git a/ec/README.md b/ec/README.md index eec8bcfd1..9ee29eec1 100644 --- a/ec/README.md +++ b/ec/README.md @@ -13,10 +13,10 @@ Implementations of particular curves using these curve models can be found in [` ### The `Group` trait -Many cryptographic protocols use as core building-blocks prime-order groups. The [`Group`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs) trait is an abstraction that represents elements of such abelian prime-order groups. It provides methods for performing common operations on group elements: +Many cryptographic protocols use as core building-blocks prime-order groups. The [`PrimeGroup`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs) trait is an abstraction that represents elements of such abelian prime-order groups. It provides methods for performing common operations on group elements: ```rust -use ark_ec::Group; +use ark_ec::PrimeGroup; use ark_ff::{PrimeField, Field}; // We'll use the BLS12-381 G1 curve for this example. // This group has a prime order `r`, and is associated with a prime field `Fr`. @@ -49,12 +49,12 @@ assert_eq!(f, c); ## Scalar multiplication -While the `Group` trait already produces scalar multiplication routines, in many cases one can take advantage of +While the `PrimeGroup` trait already produces scalar multiplication routines, in many cases one can take advantage of the group structure to perform scalar multiplication more efficiently. To allow such specialization, `ark-ec` provides the `ScalarMul` and `VariableBaseMSM` traits. The latter trait computes an "inner product" between a vector of scalars `s` and a vector of group elements `g`. That is, it computes `s.iter().zip(g).map(|(s, g)| g * s).sum()`. ```rust -use ark_ec::{Group, VariableBaseMSM}; +use ark_ec::{PrimeGroup, VariableBaseMSM}; use ark_ff::{PrimeField, Field}; // We'll use the BLS12-381 G1 curve for this example. // This group has a prime order `r`, and is associated with a prime field `Fr`. @@ -72,7 +72,7 @@ let s2 = ScalarField::rand(&mut rng); // Note that we're using the `GAffine` type here, as opposed to `G`. // This is because MSMs are more efficient when the group elements are in affine form. (See below for why.) // -// The `VariableBaseMSM` trait allows specializing the input group element representation to allow +// The `VariableBaseMSM` trait allows specializing the input group element representation to allow // for more efficient implementations. let r = G::msm(&[a, b], &[s1, s2]).unwrap(); assert_eq!(r, a * s1 + b * s2); @@ -90,7 +90,7 @@ but is slower for most arithmetic operations. Let's explore how and when to use these: ```rust -use ark_ec::{AffineRepr, Group, CurveGroup, VariableBaseMSM}; +use ark_ec::{AffineRepr, PrimeGroup, CurveGroup, VariableBaseMSM}; use ark_ff::{PrimeField, Field}; use ark_test_curves::bls12_381::{G1Projective as G, G1Affine as GAffine, Fr as ScalarField}; use ark_std::{Zero, UniformRand}; @@ -105,9 +105,9 @@ assert_eq!(a_aff, a); // We can also convert back to the `CurveGroup` representation: assert_eq!(a, a_aff.into_group()); -// As a general rule, most group operations are slower when elements -// are represented as `AffineRepr`. However, adding an `AffineRepr` -// point to a `CurveGroup` one is usually slightly more efficient than +// As a general rule, most group operations are slower when elements +// are represented as `AffineRepr`. However, adding an `AffineRepr` +// point to a `CurveGroup` one is usually slightly more efficient than // adding two `CurveGroup` points. let d = a + a_aff; assert_eq!(d, a.double()); diff --git a/ec/src/lib.rs b/ec/src/lib.rs index daf169566..d424bd355 100644 --- a/ec/src/lib.rs +++ b/ec/src/lib.rs @@ -22,16 +22,15 @@ extern crate ark_std; use ark_ff::{ fields::{Field, PrimeField}, - UniformRand, + UniformRand, AdditiveGroup, }; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::{ fmt::{Debug, Display}, hash::Hash, - ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}, + ops::{Add, AddAssign, Mul, MulAssign}, vec::Vec, }; -use num_traits::Zero; pub use scalar_mul::{variable_base::VariableBaseMSM, ScalarMul}; use zeroize::Zeroize; @@ -47,38 +46,7 @@ pub mod hashing; pub mod pairing; /// Represents (elements of) a group of prime order `r`. -pub trait Group: - Eq - + 'static - + Sized - + CanonicalSerialize - + CanonicalDeserialize - + Copy - + Clone - + Default - + Send - + Sync - + Hash - + Debug - + Display - + UniformRand - + Zeroize - + Zero - + Neg - + Add - + Sub - + Mul<::ScalarField, Output = Self> - + AddAssign - + SubAssign - + MulAssign<::ScalarField> - + for<'a> Add<&'a Self, Output = Self> - + for<'a> Sub<&'a Self, Output = Self> - + for<'a> Mul<&'a ::ScalarField, Output = Self> - + for<'a> AddAssign<&'a Self> - + for<'a> SubAssign<&'a Self> - + for<'a> MulAssign<&'a ::ScalarField> - + core::iter::Sum - + for<'a> core::iter::Sum<&'a Self> +pub trait PrimeGroup: AdditiveGroup { /// The scalar field `F_r`, where `r` is the order of this group. type ScalarField: PrimeField; @@ -116,12 +84,13 @@ pub trait Group: } } + /// An opaque representation of an elliptic curve group element that is suitable /// for efficient group arithmetic. /// /// The point is guaranteed to be in the correct prime order subgroup. pub trait CurveGroup: - Group + PrimeGroup::ScalarField> + Add + AddAssign // + for<'a> Add<&'a Self::Affine, Output = Self> @@ -133,14 +102,15 @@ pub trait CurveGroup: + core::iter::Sum + for<'a> core::iter::Sum<&'a Self::Affine> { - type Config: CurveConfig; + type Config: CurveConfig::ScalarField, BaseField = Self::BaseField>; + type ScalarField: PrimeField; /// The field over which this curve is defined. type BaseField: Field; /// The affine representation of this element. type Affine: AffineRepr< Config = Self::Config, Group = Self, - ScalarField = Self::ScalarField, + ScalarField = ::ScalarField, BaseField = Self::BaseField, > + From + Into; @@ -198,7 +168,7 @@ pub trait AffineRepr: type Group: CurveGroup< Config = Self::Config, Affine = Self, - ScalarField = Self::ScalarField, + ScalarField = ::ScalarField, BaseField = Self::BaseField, > + From + Into @@ -278,7 +248,7 @@ where Self::E2: MulAssign<::BaseField>, { type E1: CurveGroup< - BaseField = ::ScalarField, + BaseField = ::ScalarField, ScalarField = ::BaseField, >; type E2: CurveGroup; @@ -289,12 +259,12 @@ pub trait PairingFriendlyCycle: CurveCycle { type Engine1: pairing::Pairing< G1 = Self::E1, G1Affine = ::Affine, - ScalarField = ::ScalarField, + ScalarField = ::ScalarField, >; type Engine2: pairing::Pairing< G1 = Self::E2, G1Affine = ::Affine, - ScalarField = ::ScalarField, + ScalarField = ::ScalarField, >; } diff --git a/ec/src/models/short_weierstrass/group.rs b/ec/src/models/short_weierstrass/group.rs index 99fa901d2..bfb3ed810 100644 --- a/ec/src/models/short_weierstrass/group.rs +++ b/ec/src/models/short_weierstrass/group.rs @@ -15,7 +15,7 @@ use ark_std::{ One, Zero, }; -use ark_ff::{fields::Field, PrimeField, ToConstraintField, UniformRand}; +use ark_ff::{AdditiveGroup, fields::Field, PrimeField, ToConstraintField, UniformRand}; use zeroize::Zeroize; @@ -25,7 +25,7 @@ use rayon::prelude::*; use super::{Affine, SWCurveConfig}; use crate::{ scalar_mul::{variable_base::VariableBaseMSM, ScalarMul}, - AffineRepr, CurveGroup, Group, + AffineRepr, CurveGroup, PrimeGroup, }; /// Jacobian coordinates for a point on an elliptic curve in short Weierstrass @@ -160,7 +160,11 @@ impl Zero for Projective

{ } } -impl Group for Projective

{ +impl AdditiveGroup for Projective

{ + type Scalar = P::ScalarField; +} + +impl PrimeGroup for Projective

{ type ScalarField = P::ScalarField; #[inline] @@ -283,6 +287,7 @@ impl Group for Projective

{ impl CurveGroup for Projective

{ type Config = P; type BaseField = P::BaseField; + type ScalarField = P::ScalarField; type Affine = Affine

; type FullGroup = Affine

; @@ -636,7 +641,7 @@ impl ScalarMul for Projective

{ } impl VariableBaseMSM for Projective

{ - fn msm(bases: &[Self::MulBase], bigints: &[Self::ScalarField]) -> Result { + fn msm(bases: &[Self::MulBase], bigints: &[::ScalarField]) -> Result { P::msm(bases, bigints) } } diff --git a/ec/src/models/short_weierstrass/mod.rs b/ec/src/models/short_weierstrass/mod.rs index 965cbb83f..7e0a3f432 100644 --- a/ec/src/models/short_weierstrass/mod.rs +++ b/ec/src/models/short_weierstrass/mod.rs @@ -6,7 +6,7 @@ use ark_std::io::{Read, Write}; use ark_ff::fields::Field; -use crate::{scalar_mul::variable_base::VariableBaseMSM, AffineRepr, Group}; +use crate::{scalar_mul::variable_base::VariableBaseMSM, AffineRepr, PrimeGroup}; use num_traits::Zero; diff --git a/ec/src/models/twisted_edwards/group.rs b/ec/src/models/twisted_edwards/group.rs index d82d70a2e..6b6bb3364 100644 --- a/ec/src/models/twisted_edwards/group.rs +++ b/ec/src/models/twisted_edwards/group.rs @@ -15,7 +15,7 @@ use ark_std::{ One, Zero, }; -use ark_ff::{fields::Field, PrimeField, ToConstraintField, UniformRand}; +use ark_ff::{AdditiveGroup, fields::Field, PrimeField, ToConstraintField, UniformRand}; use zeroize::Zeroize; @@ -25,7 +25,7 @@ use rayon::prelude::*; use super::{Affine, MontCurveConfig, TECurveConfig}; use crate::{ scalar_mul::{variable_base::VariableBaseMSM, ScalarMul}, - AffineRepr, CurveGroup, Group, + AffineRepr, CurveGroup, PrimeGroup, }; /// `Projective` implements Extended Twisted Edwards Coordinates @@ -150,7 +150,11 @@ impl Zero for Projective

{ } } -impl Group for Projective

{ +impl AdditiveGroup for Projective

{ + type Scalar = P::ScalarField; +} + +impl PrimeGroup for Projective

{ type ScalarField = P::ScalarField; fn generator() -> Self { @@ -201,6 +205,7 @@ impl CurveGroup for Projective

{ type Config = P; type BaseField = P::BaseField; type Affine = Affine

; + type ScalarField = P::ScalarField; type FullGroup = Affine

; fn normalize_batch(v: &[Self]) -> Vec { @@ -226,6 +231,7 @@ impl CurveGroup for Projective

{ }) .collect() } + } impl Neg for Projective

{ diff --git a/ec/src/models/twisted_edwards/mod.rs b/ec/src/models/twisted_edwards/mod.rs index 67402ed69..3934d4d9c 100644 --- a/ec/src/models/twisted_edwards/mod.rs +++ b/ec/src/models/twisted_edwards/mod.rs @@ -4,7 +4,7 @@ use ark_serialize::{ }; use ark_std::io::{Read, Write}; -use crate::{scalar_mul::variable_base::VariableBaseMSM, AffineRepr, Group}; +use crate::{scalar_mul::variable_base::VariableBaseMSM, AffineRepr, PrimeGroup}; use num_traits::Zero; use ark_ff::fields::Field; diff --git a/ec/src/pairing.rs b/ec/src/pairing.rs index 05071a593..74d3e40a4 100644 --- a/ec/src/pairing.rs +++ b/ec/src/pairing.rs @@ -1,4 +1,4 @@ -use ark_ff::{CyclotomicMultSubgroup, Field, One, PrimeField}; +use ark_ff::{CyclotomicMultSubgroup, Field, One, PrimeField, AdditiveGroup}; use ark_serialize::{ CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate, }; @@ -16,7 +16,7 @@ use ark_std::{ }; use zeroize::Zeroize; -use crate::{AffineRepr, CurveGroup, Group, VariableBaseMSM}; +use crate::{AffineRepr, CurveGroup, PrimeGroup, VariableBaseMSM}; /// Collection of types (mainly fields and curves) that together describe /// how to compute a pairing over a pairing-friendly curve. @@ -28,7 +28,7 @@ pub trait Pairing: Sized + 'static + Copy + Debug + Sync + Send + Eq { type ScalarField: PrimeField; /// An element in G1. - type G1: CurveGroup + type G1: CurveGroup::ScalarField, Affine = Self::G1Affine> + From + Into // needed due to https://github.com/rust-lang/rust/issues/69640 @@ -53,7 +53,7 @@ pub trait Pairing: Sized + 'static + Copy + Debug + Sync + Send + Eq { + From; /// An element of G2. - type G2: CurveGroup + type G2: CurveGroup::ScalarField, Affine = Self::G2Affine> + From + Into // needed due to https://github.com/rust-lang/rust/issues/69640 @@ -265,7 +265,11 @@ impl Distribution> for Standard { } } -impl Group for PairingOutput

{ +impl AdditiveGroup for PairingOutput

{ + type Scalar = P::ScalarField; +} + +impl PrimeGroup for PairingOutput

{ type ScalarField = P::ScalarField; fn generator() -> Self { diff --git a/ec/src/scalar_mul/fixed_base.rs b/ec/src/scalar_mul/fixed_base.rs index ce8001ccd..8062f5a8b 100644 --- a/ec/src/scalar_mul/fixed_base.rs +++ b/ec/src/scalar_mul/fixed_base.rs @@ -4,6 +4,8 @@ use ark_std::{cfg_iter, cfg_iter_mut, vec::Vec}; #[cfg(feature = "parallel")] use rayon::prelude::*; +use crate::PrimeGroup; + use super::ScalarMul; pub struct FixedBase; @@ -62,9 +64,9 @@ impl FixedBase { outerc: usize, window: usize, multiples_of_g: &[Vec<::MulBase>], - scalar: &T::ScalarField, + scalar: &::ScalarField, ) -> T { - let modulus_size = T::ScalarField::MODULUS_BIT_SIZE as usize; + let modulus_size = ::ScalarField::MODULUS_BIT_SIZE as usize; let scalar_val = scalar.into_bigint().to_bits_le(); let mut res = T::from(multiples_of_g[0][0]); @@ -86,7 +88,7 @@ impl FixedBase { scalar_size: usize, window: usize, table: &[Vec<::MulBase>], - v: &[T::ScalarField], + v: &[::ScalarField], ) -> Vec { let outerc = (scalar_size + window - 1) / window; assert!(outerc <= table.len()); diff --git a/ec/src/scalar_mul/mod.rs b/ec/src/scalar_mul/mod.rs index 9f81b75c7..c6172ca52 100644 --- a/ec/src/scalar_mul/mod.rs +++ b/ec/src/scalar_mul/mod.rs @@ -4,7 +4,7 @@ pub mod wnaf; pub mod fixed_base; pub mod variable_base; -use crate::Group; +use crate::PrimeGroup; use ark_std::{ ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign}, vec::Vec, @@ -20,7 +20,7 @@ fn ln_without_floats(a: usize) -> usize { } pub trait ScalarMul: - Group + PrimeGroup + Add + AddAssign + for<'a> Add<&'a Self::MulBase, Output = Self> @@ -36,8 +36,8 @@ pub trait ScalarMul: + Copy + Eq + core::hash::Hash - + Mul - + for<'a> Mul<&'a Self::ScalarField, Output = Self> + + Mul<::ScalarField, Output = Self> + + for<'a> Mul<&'a ::ScalarField, Output = Self> + Neg; const NEGATION_IS_CHEAP: bool; diff --git a/ec/src/scalar_mul/variable_base/mod.rs b/ec/src/scalar_mul/variable_base/mod.rs index bc4719c8f..b41a94cba 100644 --- a/ec/src/scalar_mul/variable_base/mod.rs +++ b/ec/src/scalar_mul/variable_base/mod.rs @@ -7,6 +7,8 @@ use rayon::prelude::*; pub mod stream_pippenger; pub use stream_pippenger::*; +use crate::PrimeGroup; + use super::ScalarMul; pub trait VariableBaseMSM: ScalarMul { @@ -17,7 +19,7 @@ pub trait VariableBaseMSM: ScalarMul { /// shortest length between `scalars.len()` and `bases.len()`. /// /// Reference: [`VariableBaseMSM::msm`] - fn msm_unchecked(bases: &[Self::MulBase], scalars: &[Self::ScalarField]) -> Self { + fn msm_unchecked(bases: &[Self::MulBase], scalars: &[::ScalarField]) -> Self { let bigints = cfg_into_iter!(scalars) .map(|s| s.into_bigint()) .collect::>(); @@ -31,7 +33,7 @@ pub trait VariableBaseMSM: ScalarMul { /// This method checks that `bases` and `scalars` have the same length. /// If they are unequal, it returns an error containing /// the shortest length over which the MSM can be performed. - fn msm(bases: &[Self::MulBase], scalars: &[Self::ScalarField]) -> Result { + fn msm(bases: &[Self::MulBase], scalars: &[::ScalarField]) -> Result { (bases.len() == scalars.len()) .then(|| Self::msm_unchecked(bases, scalars)) .ok_or(bases.len().min(scalars.len())) @@ -40,7 +42,7 @@ pub trait VariableBaseMSM: ScalarMul { /// Optimized implementation of multi-scalar multiplication. fn msm_bigint( bases: &[Self::MulBase], - bigints: &[::BigInt], + bigints: &[<::ScalarField as PrimeField>::BigInt], ) -> Self { if Self::NEGATION_IS_CHEAP { msm_bigint_wnaf(bases, bigints) @@ -54,7 +56,7 @@ pub trait VariableBaseMSM: ScalarMul { fn msm_chunks(bases_stream: &J, scalars_stream: &I) -> Self where I: Iterable, - I::Item: Borrow, + I::Item: Borrow<::ScalarField>, J: Iterable, J::Item: Borrow, { @@ -88,7 +90,7 @@ pub trait VariableBaseMSM: ScalarMul { // Compute msm using windowed non-adjacent form fn msm_bigint_wnaf( bases: &[V::MulBase], - bigints: &[::BigInt], + bigints: &[<::ScalarField as PrimeField>::BigInt], ) -> V { let size = ark_std::cmp::min(bases.len(), bigints.len()); let scalars = &bigints[..size]; @@ -100,7 +102,7 @@ fn msm_bigint_wnaf( super::ln_without_floats(size) + 2 }; - let num_bits = V::ScalarField::MODULUS_BIT_SIZE as usize; + let num_bits = ::ScalarField::MODULUS_BIT_SIZE as usize; let digits_count = (num_bits + c - 1) / c; let scalar_digits = scalars .iter() @@ -151,7 +153,7 @@ fn msm_bigint_wnaf( /// Optimized implementation of multi-scalar multiplication. fn msm_bigint( bases: &[V::MulBase], - bigints: &[::BigInt], + bigints: &[<::ScalarField as PrimeField>::BigInt], ) -> V { let size = ark_std::cmp::min(bases.len(), bigints.len()); let scalars = &bigints[..size]; @@ -164,8 +166,8 @@ fn msm_bigint( super::ln_without_floats(size) + 2 }; - let num_bits = V::ScalarField::MODULUS_BIT_SIZE as usize; - let one = V::ScalarField::one().into_bigint(); + let num_bits = ::ScalarField::MODULUS_BIT_SIZE as usize; + let one = ::ScalarField::one().into_bigint(); let zero = V::zero(); let window_starts: Vec<_> = (0..num_bits).step_by(c).collect(); diff --git a/ec/src/scalar_mul/variable_base/stream_pippenger.rs b/ec/src/scalar_mul/variable_base/stream_pippenger.rs index dc62ba4cb..4d1f0b203 100644 --- a/ec/src/scalar_mul/variable_base/stream_pippenger.rs +++ b/ec/src/scalar_mul/variable_base/stream_pippenger.rs @@ -4,11 +4,13 @@ use ark_ff::{PrimeField, Zero}; use ark_std::{borrow::Borrow, vec::Vec}; use hashbrown::HashMap; +use crate::PrimeGroup; + use super::VariableBaseMSM; /// Struct for the chunked Pippenger algorithm. pub struct ChunkedPippenger { - scalars_buffer: Vec<::BigInt>, + scalars_buffer: Vec<<::ScalarField as PrimeField>::BigInt>, bases_buffer: Vec, result: G, buf_size: usize, @@ -40,7 +42,7 @@ impl ChunkedPippenger { pub fn add(&mut self, base: B, scalar: S) where B: Borrow, - S: Borrow<::BigInt>, + S: Borrow<<::ScalarField as PrimeField>::BigInt>, { self.scalars_buffer.push(*scalar.borrow()); self.bases_buffer.push(*base.borrow()); @@ -67,7 +69,7 @@ impl ChunkedPippenger { /// Hash map struct for Pippenger algorithm. pub struct HashMapPippenger { - buffer: HashMap, + buffer: HashMap::ScalarField>, result: G, buf_size: usize, } @@ -87,13 +89,13 @@ impl HashMapPippenger { pub fn add(&mut self, base: B, scalar: S) where B: Borrow, - S: Borrow, + S: Borrow<::ScalarField>, { // update the entry, guarding the possibility that it has been already set. let entry = self .buffer .entry(*base.borrow()) - .or_insert(G::ScalarField::zero()); + .or_insert(::ScalarField::zero()); *entry += *scalar.borrow(); if self.buffer.len() == self.buf_size { let bases = self.buffer.keys().cloned().collect::>(); diff --git a/ec/src/scalar_mul/wnaf.rs b/ec/src/scalar_mul/wnaf.rs index d3e0b5437..44f491855 100644 --- a/ec/src/scalar_mul/wnaf.rs +++ b/ec/src/scalar_mul/wnaf.rs @@ -1,4 +1,4 @@ -use crate::Group; +use crate::PrimeGroup; use ark_ff::{BigInteger, PrimeField}; use ark_std::vec::Vec; @@ -20,7 +20,7 @@ impl WnafContext { Self { window_size } } - pub fn table(&self, mut base: G) -> Vec { + pub fn table(&self, mut base: G) -> Vec { let mut table = Vec::with_capacity(1 << (self.window_size - 1)); let dbl = base.double(); @@ -37,7 +37,7 @@ impl WnafContext { /// multiplication; first, it uses `Self::table` to calculate an /// appropriate table of multiples of `g`, and then uses the wNAF /// algorithm to compute the scalar multiple. - pub fn mul(&self, g: G, scalar: &G::ScalarField) -> G { + pub fn mul(&self, g: G, scalar: &::ScalarField) -> G { let table = self.table(g); self.mul_with_table(&table, scalar).unwrap() } @@ -48,7 +48,7 @@ impl WnafContext { /// `G::ScalarField`. /// /// Returns `None` if the table is too small. - pub fn mul_with_table(&self, base_table: &[G], scalar: &G::ScalarField) -> Option { + pub fn mul_with_table(&self, base_table: &[G], scalar: &::ScalarField) -> Option { if 1 << (self.window_size - 1) > base_table.len() { return None; } diff --git a/ff/src/fields/mod.rs b/ff/src/fields/mod.rs index 4463953dd..d44f695b6 100644 --- a/ff/src/fields/mod.rs +++ b/ff/src/fields/mod.rs @@ -1,3 +1,5 @@ +use core::iter::Product; + use crate::UniformRand; use ark_serialize::{ CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize, @@ -42,7 +44,49 @@ use ark_std::cmp::max; #[cfg(feature = "parallel")] use rayon::prelude::*; -/// The interface for a generic field. + +pub trait AdditiveGroup: + Eq + + 'static + + Sized + + CanonicalSerialize + + CanonicalDeserialize + + Copy + + Clone + + Default + + Send + + Sync + + Hash + + Debug + + Display + + UniformRand + + Zeroize + + Zero + + Neg + + Add + + Sub + + Mul<::Scalar, Output = Self> + + AddAssign + + SubAssign + + MulAssign<::Scalar> + + for<'a> Add<&'a Self, Output = Self> + + for<'a> Sub<&'a Self, Output = Self> + + for<'a> Mul<&'a ::Scalar, Output = Self> + + for<'a> AddAssign<&'a Self> + + for<'a> SubAssign<&'a Self> + + for<'a> MulAssign<&'a ::Scalar> + + for<'a> Add<&'a mut Self, Output = Self> + + for<'a> Sub<&'a mut Self, Output = Self> + + for<'a> Mul<&'a mut ::Scalar, Output = Self> + + for<'a> AddAssign<&'a mut Self> + + for<'a> SubAssign<&'a mut Self> + + for<'a> MulAssign<&'a mut ::Scalar> + + core::iter::Sum + + for<'a> core::iter::Sum<&'a Self> { + type Scalar: Field; + } + +/// The interface for a generic field. /// Types implementing [`Field`] support common field operations such as addition, subtraction, multiplication, and inverses. /// /// ## Defining your own field @@ -113,33 +157,13 @@ pub trait Field: + CanonicalSerializeWithFlags + CanonicalDeserialize + CanonicalDeserializeWithFlags - + Add - + Sub - + Mul + + AdditiveGroup + Div - + AddAssign - + SubAssign - + MulAssign + DivAssign - + for<'a> Add<&'a Self, Output = Self> - + for<'a> Sub<&'a Self, Output = Self> - + for<'a> Mul<&'a Self, Output = Self> + for<'a> Div<&'a Self, Output = Self> - + for<'a> AddAssign<&'a Self> - + for<'a> SubAssign<&'a Self> - + for<'a> MulAssign<&'a Self> + for<'a> DivAssign<&'a Self> - + for<'a> Add<&'a mut Self, Output = Self> - + for<'a> Sub<&'a mut Self, Output = Self> - + for<'a> Mul<&'a mut Self, Output = Self> + for<'a> Div<&'a mut Self, Output = Self> - + for<'a> AddAssign<&'a mut Self> - + for<'a> SubAssign<&'a mut Self> - + for<'a> MulAssign<&'a mut Self> + for<'a> DivAssign<&'a mut Self> - + core::iter::Sum - + for<'a> core::iter::Sum<&'a Self> - + core::iter::Product + for<'a> core::iter::Product<&'a Self> + From + From @@ -147,6 +171,7 @@ pub trait Field: + From + From + From + + Product { type BasePrimeField: PrimeField; diff --git a/ff/src/fields/models/cubic_extension.rs b/ff/src/fields/models/cubic_extension.rs index ff4203f03..35ee818b6 100644 --- a/ff/src/fields/models/cubic_extension.rs +++ b/ff/src/fields/models/cubic_extension.rs @@ -21,7 +21,7 @@ use ark_std::rand::{ use crate::{ fields::{Field, PrimeField}, - LegendreSymbol, SqrtPrecomputation, ToConstraintField, UniformRand, + LegendreSymbol, SqrtPrecomputation, ToConstraintField, UniformRand, AdditiveGroup, }; /// Defines a Cubic extension field from a cubic non-residue. @@ -164,6 +164,10 @@ impl One for CubicExtField

{ } } +impl AdditiveGroup for CubicExtField

{ + type Scalar= Self; +} + type BaseFieldIter

= <

::BaseField as Field>::BasePrimeFieldIter; impl Field for CubicExtField

{ type BasePrimeField = P::BasePrimeField; diff --git a/ff/src/fields/models/fp/mod.rs b/ff/src/fields/models/fp/mod.rs index 7f417ed9a..f7111b450 100644 --- a/ff/src/fields/models/fp/mod.rs +++ b/ff/src/fields/models/fp/mod.rs @@ -18,7 +18,7 @@ use ark_std::{ mod montgomery_backend; pub use montgomery_backend::*; -use crate::{BigInt, BigInteger, FftField, Field, LegendreSymbol, PrimeField, SqrtPrecomputation}; +use crate::{BigInt, BigInteger, FftField, Field, LegendreSymbol, PrimeField, SqrtPrecomputation, AdditiveGroup}; /// A trait that specifies the configuration of a prime field. /// Also specifies how to perform arithmetic on field elements. pub trait FpConfig: Send + Sync + 'static + Sized { @@ -186,6 +186,10 @@ impl, const N: usize> One for Fp { } } +impl, const N: usize> AdditiveGroup for Fp { + type Scalar = Self; +} + impl, const N: usize> Field for Fp { type BasePrimeField = Self; type BasePrimeFieldIter = iter::Once; diff --git a/ff/src/fields/models/quadratic_extension.rs b/ff/src/fields/models/quadratic_extension.rs index f62c7d353..0eba9aeb7 100644 --- a/ff/src/fields/models/quadratic_extension.rs +++ b/ff/src/fields/models/quadratic_extension.rs @@ -22,7 +22,7 @@ use ark_std::rand::{ use crate::{ biginteger::BigInteger, fields::{Field, LegendreSymbol, PrimeField}, - SqrtPrecomputation, ToConstraintField, UniformRand, + SqrtPrecomputation, ToConstraintField, UniformRand, AdditiveGroup, }; /// Defines a Quadratic extension field from a quadratic non-residue. @@ -193,6 +193,10 @@ impl One for QuadExtField

{ } } +impl AdditiveGroup for QuadExtField

{ + type Scalar = Self; +} + type BaseFieldIter

= <

::BaseField as Field>::BasePrimeFieldIter; impl Field for QuadExtField

{ type BasePrimeField = P::BasePrimeField; diff --git a/test-curves/src/bls12_381/g2.rs b/test-curves/src/bls12_381/g2.rs index f4c970910..f8ec4e5ae 100644 --- a/test-curves/src/bls12_381/g2.rs +++ b/test-curves/src/bls12_381/g2.rs @@ -6,7 +6,7 @@ use ark_ec::{ hashing::curve_maps::wb::{IsogenyMap, WBConfig}, models::CurveConfig, short_weierstrass::{self, *}, - AffineRepr, CurveGroup, Group, + AffineRepr, CurveGroup, PrimeGroup, }; use ark_ff::{BigInt, Field, MontFp, Zero}; diff --git a/test-curves/src/bls12_381/g2_swu_iso.rs b/test-curves/src/bls12_381/g2_swu_iso.rs index 0790cf99f..988e30ef1 100644 --- a/test-curves/src/bls12_381/g2_swu_iso.rs +++ b/test-curves/src/bls12_381/g2_swu_iso.rs @@ -80,27 +80,27 @@ pub const ISOGENY_MAP_TO_G2 : IsogenyMap<'_, SwuIsoConfig, g2::Config> = Isogen x_map_numerator: &[ Fq2::new( MontFp!("889424345604814976315064405719089812568196182208668418962679585805340366775741747653930584250892369786198727235542"), - MontFp!("889424345604814976315064405719089812568196182208668418962679585805340366775741747653930584250892369786198727235542")), + MontFp!("889424345604814976315064405719089812568196182208668418962679585805340366775741747653930584250892369786198727235542")), Fq2::new( MontFp!("0"), MontFp!("2668273036814444928945193217157269437704588546626005256888038757416021100327225242961791752752677109358596181706522")), Fq2::new( MontFp!("2668273036814444928945193217157269437704588546626005256888038757416021100327225242961791752752677109358596181706526"), - MontFp!("1334136518407222464472596608578634718852294273313002628444019378708010550163612621480895876376338554679298090853261")), + MontFp!("1334136518407222464472596608578634718852294273313002628444019378708010550163612621480895876376338554679298090853261")), Fq2::new( - MontFp!("3557697382419259905260257622876359250272784728834673675850718343221361467102966990615722337003569479144794908942033"), + MontFp!("3557697382419259905260257622876359250272784728834673675850718343221361467102966990615722337003569479144794908942033"), MontFp!("0")), ], x_map_denominator: &[ Fq2::new( - MontFp!("0"), - MontFp!("4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559715")), + MontFp!("0"), + MontFp!("4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559715")), Fq2::new( - MontFp!("12"), - MontFp!("4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559775")), + MontFp!("12"), + MontFp!("4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559775")), Fq2::new( - MontFp!("1"), + MontFp!("1"), MontFp!("0")), ], diff --git a/test-curves/src/bn384_small_two_adicity/tests.rs b/test-curves/src/bn384_small_two_adicity/tests.rs index 1313324c4..031f87624 100644 --- a/test-curves/src/bn384_small_two_adicity/tests.rs +++ b/test-curves/src/bn384_small_two_adicity/tests.rs @@ -1,5 +1,5 @@ #![allow(unused_imports)] -use ark_ec::{models::short_weierstrass::SWCurveConfig, pairing::Pairing, AffineRepr, CurveGroup}; +use ark_ec::{models::short_weierstrass::SWCurveConfig, pairing::Pairing, AffineRepr, CurveGroup, PrimeGroup}; use ark_ff::{Field, One, UniformRand, Zero}; use ark_std::{rand::Rng, test_rng}; diff --git a/test-templates/src/fields.rs b/test-templates/src/fields.rs index 309ea79ce..dd552a93c 100644 --- a/test-templates/src/fields.rs +++ b/test-templates/src/fields.rs @@ -179,9 +179,9 @@ macro_rules! __test_field { assert_eq!(t1, t2); // Doubling - assert_eq!(a.double(), a + a); - assert_eq!(b.double(), b + b); - assert_eq!(c.double(), c + c); + assert_eq!(ark_ff::Field::double(&a), a + a); + assert_eq!(ark_ff::Field::double(&b), b + b); + assert_eq!(ark_ff::Field::double(&c), c + c); } } @@ -258,9 +258,9 @@ macro_rules! __test_field { assert_eq!(a * (b + c), a * b + a * c, "Distributivity failed"); assert_eq!(b * (a + c), b * a + b * c, "Distributivity failed"); assert_eq!(c * (a + b), c * a + c * b, "Distributivity failed"); - assert_eq!((a + b).square(), a.square() + b.square() + a * b.double(), "Distributivity for square failed"); - assert_eq!((b + c).square(), c.square() + b.square() + c * b.double(), "Distributivity for square failed"); - assert_eq!((c + a).square(), a.square() + c.square() + a * c.double(), "Distributivity for square failed"); + assert_eq!((a + b).square(), a.square() + b.square() + a * ark_ff::Field::double(&b), "Distributivity for square failed"); + assert_eq!((b + c).square(), c.square() + b.square() + c * ark_ff::Field::double(&b), "Distributivity for square failed"); + assert_eq!((c + a).square(), a.square() + c.square() + a * ark_ff::Field::double(&c), "Distributivity for square failed"); } } diff --git a/test-templates/src/groups.rs b/test-templates/src/groups.rs index b223443d2..379ffe077 100644 --- a/test-templates/src/groups.rs +++ b/test-templates/src/groups.rs @@ -2,7 +2,7 @@ #[doc(hidden)] macro_rules! __test_group { ($group: ty) => { - type ScalarField = <$group as Group>::ScalarField; + type ScalarField = <$group as PrimeGroup>::ScalarField; #[test] fn test_add_properties() { let mut rng = &mut ark_std::test_rng(); @@ -366,7 +366,7 @@ macro_rules! test_group { mod $mod_name { use super::*; use ark_ff::*; - use ark_ec::{Group, CurveGroup, ScalarMul, AffineRepr, CurveConfig, short_weierstrass::SWCurveConfig, twisted_edwards::TECurveConfig, scalar_mul::{*, wnaf::*}}; + use ark_ec::{PrimeGroup, CurveGroup, ScalarMul, AffineRepr, CurveConfig, short_weierstrass::SWCurveConfig, twisted_edwards::TECurveConfig, scalar_mul::{*, wnaf::*}}; use ark_serialize::*; use ark_std::{io::Cursor, rand::Rng, vec::Vec, test_rng, vec, Zero, One, UniformRand}; const ITERATIONS: usize = 500; diff --git a/test-templates/src/msm.rs b/test-templates/src/msm.rs index 45705cb80..0c7543298 100644 --- a/test-templates/src/msm.rs +++ b/test-templates/src/msm.rs @@ -1,11 +1,11 @@ use ark_ec::{ scalar_mul::variable_base::{ChunkedPippenger, HashMapPippenger, VariableBaseMSM}, - ScalarMul, + ScalarMul, PrimeGroup, }; use ark_ff::{PrimeField, UniformRand}; use ark_std::vec::Vec; -fn naive_var_base_msm(bases: &[G::MulBase], scalars: &[G::ScalarField]) -> G { +fn naive_var_base_msm(bases: &[G::MulBase], scalars: &[::ScalarField]) -> G { let mut acc = G::zero(); for (base, scalar) in bases.iter().zip(scalars.iter()) { @@ -20,7 +20,7 @@ pub fn test_var_base_msm() { let mut rng = ark_std::test_rng(); let v = (0..SAMPLES) - .map(|_| G::ScalarField::rand(&mut rng)) + .map(|_| ::ScalarField::rand(&mut rng)) .collect::>(); let g = (0..SAMPLES).map(|_| G::rand(&mut rng)).collect::>(); let g = G::batch_convert_to_mul_base(&g); @@ -37,7 +37,7 @@ pub fn test_chunked_pippenger() { let mut rng = ark_std::test_rng(); let v = (0..SAMPLES) - .map(|_| G::ScalarField::rand(&mut rng).into_bigint()) + .map(|_| ::ScalarField::rand(&mut rng).into_bigint()) .collect::>(); let g = (0..SAMPLES).map(|_| G::rand(&mut rng)).collect::>(); let g = G::batch_convert_to_mul_base(&g); @@ -60,7 +60,7 @@ pub fn test_hashmap_pippenger() { let mut v_scal = Vec::new(); let v = (0..SAMPLES) .map(|_| { - let x = G::ScalarField::rand(&mut rng); + let x = ::ScalarField::rand(&mut rng); v_scal.push(x); x.into_bigint() }) diff --git a/test-templates/src/pairing.rs b/test-templates/src/pairing.rs index 8386969ca..ec4fd4e3e 100644 --- a/test-templates/src/pairing.rs +++ b/test-templates/src/pairing.rs @@ -3,7 +3,7 @@ macro_rules! test_pairing { ($mod_name: ident; $Pairing: ty) => { mod $mod_name { pub const ITERATIONS: usize = 100; - use ark_ec::{pairing::*, CurveGroup, Group}; + use ark_ec::{pairing::*, CurveGroup, PrimeGroup}; use ark_ff::{Field, PrimeField}; use ark_std::{test_rng, One, UniformRand, Zero}; #[test]