Skip to content

Commit

Permalink
Add AdditiveGroup trait + Field: AdditiveGroup. (#507)
Browse files Browse the repository at this point in the history
  • Loading branch information
mmaker committed Jan 19, 2023
1 parent 0a502bc commit 9e68c0d
Show file tree
Hide file tree
Showing 23 changed files with 151 additions and 125 deletions.
8 changes: 4 additions & 4 deletions bench-templates/src/macros/ec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 =
Expand Down
18 changes: 9 additions & 9 deletions ec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down Expand Up @@ -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`.
Expand All @@ -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);
Expand All @@ -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};
Expand All @@ -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());
Expand Down
52 changes: 11 additions & 41 deletions ec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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<Output = Self>
+ Add<Self, Output = Self>
+ Sub<Self, Output = Self>
+ Mul<<Self as Group>::ScalarField, Output = Self>
+ AddAssign<Self>
+ SubAssign<Self>
+ MulAssign<<Self as Group>::ScalarField>
+ for<'a> Add<&'a Self, Output = Self>
+ for<'a> Sub<&'a Self, Output = Self>
+ for<'a> Mul<&'a <Self as Group>::ScalarField, Output = Self>
+ for<'a> AddAssign<&'a Self>
+ for<'a> SubAssign<&'a Self>
+ for<'a> MulAssign<&'a <Self as Group>::ScalarField>
+ core::iter::Sum<Self>
+ for<'a> core::iter::Sum<&'a Self>
pub trait PrimeGroup: AdditiveGroup<Scalar = Self::ScalarField>
{
/// The scalar field `F_r`, where `r` is the order of this group.
type ScalarField: PrimeField;
Expand Down Expand Up @@ -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 = <Self as CurveGroup>::ScalarField>
+ Add<Self::Affine, Output = Self>
+ AddAssign<Self::Affine>
// + for<'a> Add<&'a Self::Affine, Output = Self>
Expand All @@ -133,14 +102,15 @@ pub trait CurveGroup:
+ core::iter::Sum<Self::Affine>
+ for<'a> core::iter::Sum<&'a Self::Affine>
{
type Config: CurveConfig<ScalarField = Self::ScalarField, BaseField = Self::BaseField>;
type Config: CurveConfig<ScalarField = <Self as PrimeGroup>::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 = <Self as PrimeGroup>::ScalarField,
BaseField = Self::BaseField,
> + From<Self>
+ Into<Self>;
Expand Down Expand Up @@ -278,7 +248,7 @@ where
Self::E2: MulAssign<<Self::E1 as CurveGroup>::BaseField>,
{
type E1: CurveGroup<
BaseField = <Self::E2 as Group>::ScalarField,
BaseField = <Self::E2 as PrimeGroup>::ScalarField,
ScalarField = <Self::E2 as CurveGroup>::BaseField,
>;
type E2: CurveGroup;
Expand All @@ -289,12 +259,12 @@ pub trait PairingFriendlyCycle: CurveCycle {
type Engine1: pairing::Pairing<
G1 = Self::E1,
G1Affine = <Self::E1 as CurveGroup>::Affine,
ScalarField = <Self::E1 as Group>::ScalarField,
ScalarField = <Self::E1 as PrimeGroup>::ScalarField,
>;

type Engine2: pairing::Pairing<
G1 = Self::E2,
G1Affine = <Self::E2 as CurveGroup>::Affine,
ScalarField = <Self::E2 as Group>::ScalarField,
ScalarField = <Self::E2 as PrimeGroup>::ScalarField,
>;
}
11 changes: 8 additions & 3 deletions ec/src/models/short_weierstrass/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand Down Expand Up @@ -160,7 +160,11 @@ impl<P: SWCurveConfig> Zero for Projective<P> {
}
}

impl<P: SWCurveConfig> Group for Projective<P> {
impl<P: SWCurveConfig> AdditiveGroup for Projective<P> {
type Scalar = P::ScalarField;
}

impl<P: SWCurveConfig> PrimeGroup for Projective<P> {
type ScalarField = P::ScalarField;

#[inline]
Expand Down Expand Up @@ -283,6 +287,7 @@ impl<P: SWCurveConfig> Group for Projective<P> {
impl<P: SWCurveConfig> CurveGroup for Projective<P> {
type Config = P;
type BaseField = P::BaseField;
type ScalarField = P::ScalarField;
type Affine = Affine<P>;
type FullGroup = Affine<P>;

Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/short_weierstrass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
12 changes: 9 additions & 3 deletions ec/src/models/twisted_edwards/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand Down Expand Up @@ -150,7 +150,11 @@ impl<P: TECurveConfig> Zero for Projective<P> {
}
}

impl<P: TECurveConfig> Group for Projective<P> {
impl<P: TECurveConfig> AdditiveGroup for Projective<P> {
type Scalar = P::ScalarField;
}

impl<P: TECurveConfig> PrimeGroup for Projective<P> {
type ScalarField = P::ScalarField;

fn generator() -> Self {
Expand Down Expand Up @@ -201,6 +205,7 @@ impl<P: TECurveConfig> CurveGroup for Projective<P> {
type Config = P;
type BaseField = P::BaseField;
type Affine = Affine<P>;
type ScalarField = P::ScalarField;
type FullGroup = Affine<P>;

fn normalize_batch(v: &[Self]) -> Vec<Self::Affine> {
Expand All @@ -226,6 +231,7 @@ impl<P: TECurveConfig> CurveGroup for Projective<P> {
})
.collect()
}

}

impl<P: TECurveConfig> Neg for Projective<P> {
Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/twisted_edwards/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 7 additions & 3 deletions ec/src/pairing.rs
Original file line number Diff line number Diff line change
@@ -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,
};
Expand All @@ -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.
Expand Down Expand Up @@ -265,7 +265,11 @@ impl<P: Pairing> Distribution<PairingOutput<P>> for Standard {
}
}

impl<P: Pairing> Group for PairingOutput<P> {
impl<P: Pairing> AdditiveGroup for PairingOutput<P> {
type Scalar = P::ScalarField;
}

impl<P: Pairing> PrimeGroup for PairingOutput<P> {
type ScalarField = P::ScalarField;

fn generator() -> Self {
Expand Down
2 changes: 2 additions & 0 deletions ec/src/scalar_mul/fixed_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions ec/src/scalar_mul/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -20,7 +20,7 @@ fn ln_without_floats(a: usize) -> usize {
}

pub trait ScalarMul:
Group
PrimeGroup
+ Add<Self::MulBase, Output = Self>
+ AddAssign<Self::MulBase>
+ for<'a> Add<&'a Self::MulBase, Output = Self>
Expand Down
Loading

0 comments on commit 9e68c0d

Please sign in to comment.