`ark-ec`

defines traits and algorithms for working with different kinds of additive groups, with a focus on groups arising from elliptic curves. It further provides concrete instantiations of these traits for various elliptic curve models, including popular families of pairing-friendly curves such as the BLS12 family of curves.
Implementations of particular curves using these curve models can be found in `arkworks-rs/curves`

.

## Usage

### The `Group`

trait

Many cryptographic protocols use as core building-blocks prime-order groups. The `Group`

trait is an abstraction that represents elements of such abelian prime-order groups. It provides methods for performing common operations on group elements:

```
use Group;
use ;
// 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`.
use ;
use ;
let mut rng = test_rng;
// Let's sample uniformly random group elements:
let a = rand;
let b = rand;
// We can add elements, ...
let c = a + b;
// ... subtract them, ...
let d = a - b;
// ... and double them.
assert_eq!;
// We can also negate elements, ...
let e = -a;
// ... and check that negation satisfies the basic group law
assert_eq!;
// We can also multiply group elements by elements of the corresponding scalar field
// (an act known as *scalar multiplication*)
let scalar = rand;
let e = c.mul;
let f = e.mul;
assert_eq!;
```

## Scalar multiplication

While the `Group`

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()`

.

```
use ;
use ;
// 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`.
use ;
use ;
let mut rng = test_rng;
// Let's sample uniformly random group elements:
let a = rand;
let b = rand;
let s1 = rand;
let s2 = rand;
// 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
// for more efficient implementations.
let r = msm.unwrap;
assert_eq!;
```

### Elliptic curve groups

There are two traits that are important when working with elliptic curves
over finite fields: [`CurveGroup`

], and [`AffineRepr`

]. Both traits
represent elements of the same curve, but provide different underlying representations.
In particular, the [`CurveGroup`

] representation of a curve point is generally
more efficient for arithmetic, but does not provide a unique representative
for a curve point. An [`AffineRepr`

] representation, on the other hand, *is* unique,
but is slower for most arithmetic operations. Let's explore how and when to use
these:

```
use ;
use ;
use ;
use ;
let mut rng = test_rng;
// Let's generate an elliptic curve group element in the `CurveGroup` representation
let a = rand;
// We can convert it the `AffineRepr` representation...
let a_aff = a.into_affine;
// ... and check that the two representations are equal.
assert_eq!;
// We can also convert back to the `CurveGroup` representation:
assert_eq!;
// 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!;
// This efficiency also translates into more efficient scalar multiplication routines.
let scalar = rand;
let mul_result = a_aff * scalar;
assert_eq!;
// Finally, while not recommended, users can directly construct group elements
// from the x and y coordinates of the curve points. This is useful when implementing algorithms
// like hash-to-curve.
let a_x = a_aff.x;
let a_y = a_aff.y;
let is_at_infinity = a_aff.is_zero;
// This check ensures that `new_a` is indeed in the curve group, and in particular
// is within the prime-order group.
let new_a = new;
assert_eq!;
assert!;
assert!;
```

Besides the foregoing abstract interfaces for elliptic curve groups, `ark-ec`

also provides
the following concrete instantiations of common elliptic curve models:

*Short Weierstrass*curves. The`AffineRepr`

in this case is in typical Short Weierstrass point representation, and the`CurveGroup`

is using points in Jacobian Coordinates.*Twisted Edwards*curves. The`AffineRepr`

in this case is in standard Twisted Edwards curve representation, whereas the`CurveGroup`

uses points in Extended Twisted Edwards Coordinates.

### Pairings

`Pairing`

is a trait that defines the interface for a pairing-friendly elliptic curve. Besides the general interface, we provide concrete instantiations of popular pairing-friendly families of curves, such as the Barreto-Lynn-Scott and Barreto-Naehrig families.

```
use ;
use Field;
use UniformRand;
use ;
use Fr as ScalarField;
// The pairing engine is parameterized by the scalar field of the curve.
let mut rng = test_rng;
let s = rand;
let a = G1 rand;
let b = G2 rand;
// We can compute the pairing of two points on the curve, either monolithically...
let e1 = pairing;
// ... or in two steps. First, we compute the Miller loop...
let ml_result = miller_loop;
// ... and then the final exponentiation.
let e2 = final_exponentiation.unwrap;
assert_eq!;
```

### Hash-to-group

`ark-ec`

also provides traits for hashing to elliptic curve groups. The `HashToCurve`

trait allows users to hash arbitrary byte strings to elliptic curve group elements, and allows using different hashing strategies.