Skip to content

Commit cab3eb9

Browse files
PratyushmmagicianValarDragon
authoredNov 3, 2022
Improve documentation via better READMEs (arkworks-rs#508)
* Improve documentation via better READMEs * Format * Apply suggestions from code review Co-authored-by: mmagician <[email protected]> * Update ec/README.md Co-authored-by: Dev Ojha <[email protected]> * Fix typo * Improve `ff` documentation according to review comments * Improve comment for `VariableBaseMSM` * Improve repo README Co-authored-by: mmagician <[email protected]> Co-authored-by: Dev Ojha <[email protected]>
1 parent a4362f9 commit cab3eb9

File tree

14 files changed

+404
-30
lines changed

14 files changed

+404
-30
lines changed
 

‎README.md

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
<h1 style="text-align: center;">arkworks::algebra</h1>
1+
<h1 align="center">arkworks::algebra</h1>
22

3-
<p style="text-align: center;">
3+
<p align="center">
44
<img src="https://github.com/arkworks-rs/algebra/workflows/CI/badge.svg?branch=master">
55
<a href="https://github.com/arkworks-rs/algebra/blob/master/LICENSE-APACHE"><img src="https://img.shields.io/badge/license-APACHE-blue.svg"></a>
66
<a href="https://github.com/arkworks-rs/algebra/blob/master/LICENSE-MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
77
<a href="https://deps.rs/repo/github/arkworks-rs/algebra"><img src="https://deps.rs/repo/github/arkworks-rs/algebra/status.svg"></a>
88
</p>
99

10-
The arkworks ecosystem consist of Rust libraries for designing and working with __zero knowledge succinct non-interactive arguments (zkSNARKs)__. This repository contains efficient implementations some of the key algebraic components underlying zkSNARKs: finite fields, elliptic curves, and polynomials.
10+
The arkworks ecosystem consist of Rust libraries for designing and working with *zero knowledge succinct non-interactive arguments (zkSNARKs)*. This repository contains efficient implementations of the key algebraic components underlying zkSNARKs: finite fields, elliptic curves, and polynomials.
1111

1212
This library is released under the MIT License and the Apache v2 License (see [License](#license)).
1313

@@ -17,12 +17,12 @@ This library is released under the MIT License and the Apache v2 License (see [L
1717

1818
This repository contains several Rust crates:
1919

20-
* [`ark-ff`](ff): Provides generic implementations of various finite fields
21-
* [`ark-ec`](ec): Provides generic implementations for different kinds of elliptic curves, along with pairings over these
22-
* [`ark-poly`](poly): Implements univariate, multivariate, and multilinear polynomials, and FFTs over finite fields.
23-
* [`ark-serialize`](serialize): Provides efficient serialization and point compression for finite fields and elliptic curves
20+
* [`ark-ff`](ff): Generic abstractions for, and implementations of various kinds of finite fields
21+
* [`ark-ec`](ec): Generic abstractions for prime-order groups, and implementations of various kinds of (pairing-friendly and standard) elliptic curves
22+
* [`ark-poly`](poly): Interfaces for univariate, multivariate, and multilinear polynomials, and FFTs over finite fields
23+
* [`ark-serialize`](serialize): Efficient interfaces for serialization and point compression for finite fields and elliptic curves
2424

25-
In addition, the [`curves`](https://github.com/arkworks-rs/curves) repository contains implementations of popular elliptic curves; see [here](https://github.com/arkworks-rs/curves/README.md) for details.
25+
In addition, the [`curves`](https://github.com/arkworks-rs/curves) repository contains concrete implementations of popular elliptic curves; see [here](https://github.com/arkworks-rs/curves/README.md) for details.
2626

2727
## Build guide
2828

@@ -67,7 +67,7 @@ RUSTFLAGS="-C target-feature=+bmi2,+adx" cargo +nightly [test/build/bench] --fea
6767
To enable this in the `Cargo.toml` of your own projects, enable the `asm` feature flag:
6868

6969
```toml
70-
ark-ff = { version = "0.3.0", features = [ "asm" ] }
70+
ark-ff = { version = "0.4", features = [ "asm" ] }
7171
```
7272

7373
Note that because inline assembly support in Rust is currently unstable, using this backend requires using the Nightly compiler at the moment.

‎ec/README.md

+154-8
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,164 @@
66
<a href="https://deps.rs/repo/github/arkworks-rs/algebra"><img src="https://deps.rs/repo/github/arkworks-rs/algebra/status.svg"></a>
77
</p>
88

9-
This crate defines Elliptic Curve traits, curve models that follow these traits, and multi-scalar multiplications.
9+
`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.
1010
Implementations of particular curves using these curve models can be found in [`arkworks-rs/curves`](https://github.com/arkworks-rs/curves/README.md).
1111

12-
The available elliptic curve traits are:
12+
## Usage
1313

14-
* [`AffineRepr`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs#L223) - Interface for elliptic curve points in the 'canonical form' for serialization.
15-
* [`CurveGroup`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs#L118) - Interface for elliptic curve points in a representation that is more efficient for most computation.
16-
* [`Pairing`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs#L41) - Pairing friendly elliptic curves (Contains the pairing function, and acts as a wrapper type on G1, G2, GT, and the relevant fields).
17-
* [`CurveCycle`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs#L319) - Trait representing a cycle of elliptic curves.
18-
* [`PairingFriendlyCycle`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/lib.rs#L331) - Trait representing a cycle of pairing friendly elliptic curves.
14+
### The `Group` trait
1915

20-
The elliptic curve models implemented are:
16+
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:
17+
18+
```rust
19+
use ark_ec::Group;
20+
use ark_ff::{PrimeField, Field};
21+
// We'll use the BLS12-381 G1 curve for this example.
22+
// This group has a prime order `r`, and is associated with a prime field `Fr`.
23+
use ark_test_curves::bls12_381::{G1Projective as G, Fr as ScalarField};
24+
use ark_std::{Zero, UniformRand, ops::Mul};
25+
26+
let mut rng = ark_std::test_rng();
27+
// Let's sample uniformly random group elements:
28+
let a = G::rand(&mut rng);
29+
let b = G::rand(&mut rng);
30+
31+
// We can add elements, ...
32+
let c = a + b;
33+
// ... subtract them, ...
34+
let d = a - b;
35+
// ... and double them.
36+
assert_eq!(c + d, a.double());
37+
// We can also negate elements, ...
38+
let e = -a;
39+
// ... and check that negation satisfies the basic group law
40+
assert_eq!(e + a, G::zero());
41+
42+
// We can also multiply group elements by elements of the corresponding scalar field
43+
// (an act known as *scalar multiplication*)
44+
let scalar = ScalarField::rand(&mut rng);
45+
let e = c.mul(scalar);
46+
let f = e.mul(scalar.inverse().unwrap());
47+
assert_eq!(f, c);
48+
```
49+
50+
## Scalar multiplication
51+
52+
While the `Group` trait already produces scalar multiplication routines, in many cases one can take advantage of
53+
the group structure to perform scalar multiplication more efficiently. To allow such specialization, `ark-ec` provides
54+
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()`.
55+
56+
```rust
57+
use ark_ec::{Group, VariableBaseMSM};
58+
use ark_ff::{PrimeField, Field};
59+
// We'll use the BLS12-381 G1 curve for this example.
60+
// This group has a prime order `r`, and is associated with a prime field `Fr`.
61+
use ark_test_curves::bls12_381::{G1Projective as G, G1Affine as GAffine, Fr as ScalarField};
62+
use ark_std::{Zero, UniformRand};
63+
64+
let mut rng = ark_std::test_rng();
65+
// Let's sample uniformly random group elements:
66+
let a = GAffine::rand(&mut rng);
67+
let b = GAffine::rand(&mut rng);
68+
69+
let s1 = ScalarField::rand(&mut rng);
70+
let s2 = ScalarField::rand(&mut rng);
71+
72+
// Note that we're using the `GAffine` type here, as opposed to `G`.
73+
// This is because MSMs are more efficient when the group elements are in affine form. (See below for why.)
74+
//
75+
// The `VariableBaseMSM` trait allows specializing the input group element representation to allow
76+
// for more efficient implementations.
77+
let result = G::msm(&[a, b], &[s1, s2]);
78+
assert_eq!(result, a * s1 + b * s2);
79+
```
80+
81+
### Elliptic curve groups
82+
83+
There are two traits that are important when working with elliptic curves
84+
over finite fields: [`CurveGroup`], and [`AffineRepr`]. Both traits
85+
represent elements of the same curve, but provide different underlying representations.
86+
In particular, the [`CurveGroup`] representation of a curve point is generally
87+
more efficient for arithmetic, but does not provide a unique representative
88+
for a curve point. An [`AffineRepr`] representation, on the other hand, *is* unique,
89+
but is slower for most arithmetic operations. Let's explore how and when to use
90+
these:
91+
92+
```rust
93+
use ark_ec::{AffineRepr, Group, CurveGroup, VariableBaseMSM};
94+
use ark_ff::{PrimeField, Field};
95+
use ark_test_curves::bls12_381::{G1Projective as G, G1Affine as GAffine, Fr as ScalarField};
96+
use ark_std::{Zero, UniformRand};
97+
98+
let mut rng = ark_std::test_rng();
99+
// Let's generate an elliptic curve group element in the `CurveGroup` representation
100+
let a = G::rand(&mut rng);
101+
// We can convert it the `AffineRepr` representation...
102+
let a_aff = a.into_affine();
103+
// ... and check that the two representations are equal.
104+
assert_eq!(a_aff, a);
105+
// We can also convert back to the `CurveGroup` representation:
106+
assert_eq!(a, a_aff.into_group());
107+
108+
// As a general rule, most group operations are slower when elements
109+
// are represented as `AffineRepr`. However, adding an `AffineRepr`
110+
// point to a `CurveGroup` one is usually slightly more efficient than
111+
// adding two `CurveGroup` points.
112+
let d = a + a_aff;
113+
assert_eq!(d, a.double());
114+
115+
// This efficiency also translates into more efficient scalar multiplication routines.
116+
let scalar = ScalarField::rand(&mut rng);
117+
let mul_result = a_aff * scalar;
118+
assert_eq!(a * scalar, mul_result);
119+
120+
// Finally, while not recommended, users can directly construct group elements
121+
// from the x and y coordinates of the curve points. This is useful when implementing algorithms
122+
// like hash-to-curve.
123+
let a_x = a_aff.x;
124+
let a_y = a_aff.y;
125+
let is_at_infinity = a_aff.is_zero();
126+
// This check ensures that `new_a` is indeed in the curve group, and in particular
127+
// is within the prime-order group.
128+
let new_a = GAffine::new(a_x, a_y);
129+
assert_eq!(a_aff, new_a);
130+
assert!(new_a.is_on_curve());
131+
assert!(new_a.is_in_correct_subgroup_assuming_on_curve());
132+
```
133+
134+
Besides the foregoing abstract interfaces for elliptic curve groups, `ark-ec` also provides
135+
the following concrete instantiations of common elliptic curve models:
21136

22137
* [*Short Weierstrass*](https://github.com/arkworks-rs/algebra/blob/master/ec/src/models/short_weierstrass.rs) curves. The `AffineRepr` in this case is in typical Short Weierstrass point representation, and the `CurveGroup` is using points in [Jacobian Coordinates](https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates).
23138
* [*Twisted Edwards*](https://github.com/arkworks-rs/algebra/blob/master/ec/src/models/twisted_edwards.rs) curves. The `AffineRepr` in this case is in standard Twisted Edwards curve representation, whereas the `CurveGroup` uses points in [Extended Twisted Edwards Coordinates](https://eprint.iacr.org/2008/522.pdf).
139+
140+
### Pairings
141+
142+
[`Pairing`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/pairing.rs) 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](https://github.com/arkworks-rs/algebra/blob/master/ec/src/models/bls12/mod.rs) and [Barreto-Naehrig](https://github.com/arkworks-rs/algebra/blob/master/ec/src/models/bn/mod.rs) families.
143+
144+
```rust
145+
use ark_ec::{pairing::Pairing, AffineRepr};
146+
use ark_ff::Field;
147+
use ark_std::UniformRand;
148+
149+
use ark_test_curves::bls12_381::{Bls12_381, G1Projective as G1, G2Projective as G2, Fq12 as Fq12};
150+
use ark_test_curves::bls12_381::Fr as ScalarField;
151+
152+
// The pairing engine is parameterized by the scalar field of the curve.
153+
let mut rng = ark_std::test_rng();
154+
let s = ScalarField::rand(&mut rng);
155+
let a = G1::rand(&mut rng);
156+
let b = G2::rand(&mut rng);
157+
158+
// We can compute the pairing of two points on the curve, either monolithically...
159+
let e1 = Bls12_381::pairing(a, b);
160+
// ... or in two steps. First, we compute the Miller loop...
161+
let ml_result = Bls12_381::miller_loop(a, b);
162+
// ... and then the final exponentiation.
163+
let e2 = Bls12_381::final_exponentiation(ml_result).unwrap();
164+
assert_eq!(e1, e2);
165+
```
166+
167+
### Hash-to-group
168+
169+
`ark-ec` also provides traits for hashing to elliptic curve groups. The [`HashToCurve`](https://github.com/arkworks-rs/algebra/blob/master/ec/src/hashing/mod.rs) trait allows users to hash arbitrary byte strings to elliptic curve group elements, and allows using different hashing strategies.

‎ec/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
clippy::suspicious_op_assign_impl,
1313
clippy::many_single_char_names
1414
)]
15+
#![doc = include_str!("../README.md")]
1516

1617
#[macro_use]
1718
extern crate derivative;

‎ff/README.md

+97
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,100 @@ The above two models serve as abstractions for constructing the extension fields
3636
- [`Fp6_2over3`](https://github.com/arkworks-rs/algebra/blob/master/ff/src/fields/models/fp6_2over3.rs#L48) - Extension tower: quadratic extension on a cubic extension field, i.e. `BaseField = Fp3`, but `BasePrimeField = Fp`.
3737
- [`Fp6_3over2`](https://github.com/arkworks-rs/algebra/blob/master/ff/src/fields/models/fp6_3over2.rs#L49) - Extension tower, similar to the above except that the towering order is reversed: it's a cubic extension on a quadratic extension field, i.e. `BaseField = Fp2`, but `BasePrimeField = Fp`. Only this latter one is exported by default as `Fp6`.
3838
- [`Fp12_2over3over2`](https://github.com/arkworks-rs/algebra/blob/master/ff/src/fields/models/fp12_2over3over2.rs#L83) - Extension tower: quadratic extension of `Fp6_3over2`, i.e. `BaseField = Fp6`.
39+
40+
## Usage
41+
42+
There are two important traits when working with finite fields: [`Field`],
43+
and [`PrimeField`]. Let's explore these via examples.
44+
45+
### [`Field`]
46+
47+
The [`Field`] trait provides a generic interface for any finite field.
48+
Types implementing [`Field`] support common field operations
49+
such as addition, subtraction, multiplication, and inverses.
50+
51+
```rust
52+
use ark_ff::Field;
53+
// We'll use a field associated with the BLS12-381 pairing-friendly
54+
// group for this example.
55+
use ark_test_curves::bls12_381::Fq2 as F;
56+
// `ark-std` is a utility crate that enables `arkworks` libraries
57+
// to easily support `std` and `no_std` workloads, and also re-exports
58+
// useful crates that should be common across the entire ecosystem, such as `rand`.
59+
use ark_std::{One, UniformRand};
60+
61+
let mut rng = ark_std::test_rng();
62+
// Let's sample uniformly random field elements:
63+
let a = F::rand(&mut rng);
64+
let b = F::rand(&mut rng);
65+
66+
// We can add...
67+
let c = a + b;
68+
// ... subtract ...
69+
let d = a - b;
70+
// ... double elements ...
71+
assert_eq!(c + d, a.double());
72+
73+
// ... multiply ...
74+
let e = c * d;
75+
// ... square elements ...
76+
assert_eq!(e, a.square() - b.square());
77+
78+
// ... and compute inverses ...
79+
assert_eq!(a.inverse().unwrap() * a, F::one()); // have to to unwrap, as `a` could be zero.
80+
```
81+
82+
In some cases, it is useful to be able to compute square roots of field elements
83+
(e.g.: for point compression of elliptic curve elements).
84+
To support this, users can implement the `sqrt`-related methods for their field type. This method
85+
is already implemented for prime fields (see below), and also for quadratic extension fields.
86+
87+
The `sqrt`-related methods can be used as follows:
88+
89+
```rust
90+
use ark_ff::Field;
91+
// As before, we'll use a field associated with the BLS12-381 pairing-friendly
92+
// group for this example.
93+
use ark_test_curves::bls12_381::Fq2 as F;
94+
use ark_std::{One, UniformRand};
95+
96+
let mut rng = ark_std::test_rng();
97+
let a = F::rand(&mut rng);
98+
99+
// We can check if a field element is a square by computing its Legendre symbol...
100+
if a.legendre().is_qr() {
101+
// ... and if it is, we can compute its square root.
102+
let b = a.sqrt().unwrap();
103+
assert_eq!(b.square(), a);
104+
} else {
105+
// Otherwise, we can check that the square root is `None`.
106+
assert_eq!(a.sqrt(), None);
107+
}
108+
```
109+
110+
### [`PrimeField`]
111+
112+
If the field is of prime order, then users can choose
113+
to implement the [`PrimeField`] trait for it. This provides access to the following
114+
additional APIs:
115+
116+
```rust
117+
use ark_ff::{Field, PrimeField, FpConfig, BigInteger};
118+
// Now we'll use the prime field underlying the BLS12-381 G1 curve.
119+
use ark_test_curves::bls12_381::Fq as F;
120+
use ark_std::{One, Zero, UniformRand};
121+
122+
let mut rng = ark_std::test_rng();
123+
let a = F::rand(&mut rng);
124+
// We can access the prime modulus associated with `F`:
125+
let modulus = <F as PrimeField>::MODULUS;
126+
assert_eq!(a.pow(&modulus), a);
127+
128+
// We can convert field elements to integers in the range [0, MODULUS - 1]:
129+
let one: num_bigint::BigUint = F::one().into();
130+
assert_eq!(one, num_bigint::BigUint::one());
131+
132+
// We can construct field elements from an arbitrary sequence of bytes:
133+
let n = F::from_le_bytes_mod_order(&modulus.to_bytes_le());
134+
assert_eq!(n, F::zero());
135+
```

‎ff/src/biginteger/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ pub trait BigInteger:
797797
/// zero.mul2();
798798
/// assert_eq!(zero, B::from(0u64));
799799
///
800-
/// let mut arr : [bool; 64] = [false; 64];
800+
/// let mut arr: [bool; 64] = [false; 64];
801801
/// arr[0] = true;
802802
/// let mut mul = B::from_bits_be(&arr);
803803
/// mul.mul2();
@@ -822,7 +822,7 @@ pub trait BigInteger:
822822
/// zero.muln(5);
823823
/// assert_eq!(zero, B::from(0u64));
824824
///
825-
/// let mut arr : [bool; 64] = [false; 64];
825+
/// let mut arr: [bool; 64] = [false; 64];
826826
/// arr[4] = true;
827827
/// let mut mul = B::from_bits_be(&arr);
828828
/// mul.muln(5);
@@ -865,7 +865,7 @@ pub trait BigInteger:
865865
/// assert_eq!(one, thirty_two_div);
866866
///
867867
/// // Edge-Case
868-
/// let mut arr : [bool; 64] = [false; 64];
868+
/// let mut arr: [bool; 64] = [false; 64];
869869
/// arr[4] = true;
870870
/// let mut div = B::from_bits_le(&arr);
871871
/// div.divn(5);
@@ -941,7 +941,7 @@ pub trait BigInteger:
941941
/// ```
942942
/// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
943943
///
944-
/// let mut arr : [bool; 64] = [false; 64];
944+
/// let mut arr: [bool; 64] = [false; 64];
945945
/// arr[63] = true;
946946
/// let mut one = B::from(1u64);
947947
/// assert_eq!(B::from_bits_be(&arr), one);
@@ -955,7 +955,7 @@ pub trait BigInteger:
955955
/// ```
956956
/// use ark_ff::{biginteger::BigInteger64 as B, BigInteger as _};
957957
///
958-
/// let mut arr : [bool; 64] = [false; 64];
958+
/// let mut arr: [bool; 64] = [false; 64];
959959
/// arr[0] = true;
960960
/// let mut one = B::from(1u64);
961961
/// assert_eq!(B::from_bits_le(&arr), one);

‎ff/src/fields/field_hashers/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ pub trait HashToField<F: Field>: Sized {
2828
/// # Examples
2929
///
3030
/// ```
31-
/// use ark_test_curves::bls12_381::Fq;
3231
/// use ark_ff::fields::field_hashers::{DefaultFieldHasher, HashToField};
32+
/// use ark_test_curves::bls12_381::Fq;
3333
/// use sha2::Sha256;
3434
///
3535
/// let hasher = <DefaultFieldHasher<Sha256> as HashToField<Fq>>::new(&[1, 2, 3]);

‎ff/src/fields/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,7 @@ mod std_tests {
387387
#[cfg(test)]
388388
mod no_std_tests {
389389
use super::*;
390-
use ark_std::str::FromStr;
391-
use ark_std::test_rng;
390+
use ark_std::{str::FromStr, test_rng};
392391
use num_bigint::*;
393392

394393
// TODO: only Fr & FrConfig should need to be imported.

0 commit comments

Comments
 (0)
Please sign in to comment.