Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AdditiveGroup trait + Field: AdditiveGroup #577

Merged
merged 13 commits into from
May 10, 2023
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Breaking changes

- [\#577](https://github.com/arkworks-rs/algebra/pull/577) (`ark-ff`, `ark-ec`) Add `AdditiveGroup`, a trait for additive groups (equipped with scalar field).

### Features

### Improvements
Expand Down
9 changes: 5 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 as PrimeGroup>::ScalarField;
fn rand(c: &mut $crate::criterion::Criterion) {
let name = format!("{}::{}", $curve_name, stringify!($Group));
use ark_std::UniformRand;
Expand All @@ -18,11 +18,12 @@ macro_rules! ec_bench {
}

fn arithmetic(c: &mut $crate::criterion::Criterion) {
use ark_ec::{CurveGroup, Group};
use ark_ff::AdditiveGroup;
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 as PrimeGroup>::ScalarField;
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
let mut arithmetic =
Expand Down
2 changes: 2 additions & 0 deletions bench-templates/src/macros/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ macro_rules! f_bench {
macro_rules! field_common {
($bench_group_name:expr, $F:ident) => {
fn arithmetic(c: &mut $crate::criterion::Criterion) {
use ark_ff::AdditiveGroup;

let name = format!("{}::{}", $bench_group_name, stringify!($F));
const SAMPLES: usize = 1000;
let mut rng = ark_std::test_rng();
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::{AdditiveGroup, 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::{AdditiveGroup, 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
58 changes: 8 additions & 50 deletions ec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ 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;

pub use ark_ff::AdditiveGroup;

pub mod models;
pub use self::models::*;

Expand All @@ -47,57 +48,14 @@ 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;

/// Returns a fixed generator of this group.
#[must_use]
fn generator() -> Self;

/// Doubles `self`.
#[must_use]
fn double(&self) -> Self {
let mut copy = *self;
copy.double_in_place();
copy
}

/// Double `self` in place.
fn double_in_place(&mut self) -> &mut Self;

/// Performs scalar multiplication of this element.
fn mul_bigint(&self, other: impl AsRef<[u64]>) -> Self;

Expand All @@ -121,7 +79,7 @@ pub trait Group:
///
/// The point is guaranteed to be in the correct prime order subgroup.
pub trait CurveGroup:
Group
PrimeGroup
+ Add<Self::Affine, Output = Self>
+ AddAssign<Self::Affine>
// + for<'a> Add<&'a Self::Affine, Output = Self>
Expand Down Expand Up @@ -278,7 +236,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 +247,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,
>;
}
2 changes: 1 addition & 1 deletion ec/src/models/bls12/g2.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ark_ff::{BitIteratorBE, Field, Fp2};
use ark_ff::{AdditiveGroup, BitIteratorBE, Field, Fp2};
use ark_serialize::*;
use ark_std::{vec::Vec, One};

Expand Down
5 changes: 4 additions & 1 deletion ec/src/models/bn/g2.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use ark_ff::fields::{Field, Fp2};
use ark_ff::{
fields::{Field, Fp2},
AdditiveGroup,
};
use ark_serialize::*;
use ark_std::vec::Vec;
use num_traits::One;
Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/bw6/g2.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ark_ff::{BitIteratorBE, Field};
use ark_ff::{AdditiveGroup, BitIteratorBE, Field};
use ark_serialize::*;
use ark_std::vec::Vec;
use num_traits::One;
Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/mnt4/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
use ark_ff::{
fp2::{Fp2, Fp2Config},
fp4::{Fp4, Fp4Config},
CyclotomicMultSubgroup, Field, PrimeField,
AdditiveGroup, CyclotomicMultSubgroup, Field, PrimeField,
};
use itertools::Itertools;
use num_traits::{One, Zero};
Expand Down
4 changes: 1 addition & 3 deletions ec/src/models/mnt6/g2.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use core::ops::Neg;

use crate::{
mnt6::MNT6Config,
models::mnt6::MNT6,
Expand All @@ -8,7 +6,7 @@ use crate::{
};
use ark_ff::fields::{Field, Fp3};
use ark_serialize::*;
use ark_std::vec::Vec;
use ark_std::{ops::Neg, vec::Vec};
use num_traits::One;

pub type G2Affine<P> = Affine<<P as MNT6Config>::G2Config>;
Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/mnt6/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
use ark_ff::{
fp3::{Fp3, Fp3Config},
fp6_2over3::{Fp6, Fp6Config},
CyclotomicMultSubgroup, Field, PrimeField,
AdditiveGroup, CyclotomicMultSubgroup, Field, PrimeField,
};
use itertools::Itertools;
use num_traits::{One, Zero};
Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/short_weierstrass/affine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use ark_std::{
One, Zero,
};

use ark_ff::{fields::Field, PrimeField, ToConstraintField, UniformRand};
use ark_ff::{fields::Field, AdditiveGroup, PrimeField, ToConstraintField, UniformRand};

use zeroize::Zeroize;

Expand Down
23 changes: 15 additions & 8 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::{fields::Field, AdditiveGroup, 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,13 +160,11 @@ impl<P: SWCurveConfig> Zero for Projective<P> {
}
}

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

#[inline]
fn generator() -> Self {
Affine::generator().into()
}
const ZERO: Self =
Self::new_unchecked(P::BaseField::ONE, P::BaseField::ONE, P::BaseField::ZERO);

/// Sets `self = 2 * self`. Note that Jacobian formulae are incomplete, and
/// so doubling cannot be computed as `self + self`. Instead, this
Expand Down Expand Up @@ -273,6 +271,15 @@ impl<P: SWCurveConfig> Group for Projective<P> {
self
}
}
}

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

#[inline]
fn generator() -> Self {
Affine::generator().into()
}

#[inline]
fn mul_bigint(&self, other: impl AsRef<[u64]>) -> Self {
Expand Down
4 changes: 2 additions & 2 deletions ec/src/models/short_weierstrass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use ark_serialize::{
};
use ark_std::io::{Read, Write};

use ark_ff::fields::Field;
use ark_ff::{fields::Field, AdditiveGroup};

use crate::{scalar_mul::variable_base::VariableBaseMSM, AffineRepr, Group};
use crate::{scalar_mul::variable_base::VariableBaseMSM, AffineRepr};

use num_traits::Zero;

Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/twisted_edwards/affine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use ark_std::{
use num_traits::{One, Zero};
use zeroize::Zeroize;

use ark_ff::{fields::Field, PrimeField, ToConstraintField, UniformRand};
use ark_ff::{fields::Field, AdditiveGroup, PrimeField, ToConstraintField, UniformRand};

use super::{Projective, TECurveConfig, TEFlags};
use crate::AffineRepr;
Expand Down
Loading