Skip to content

Commit

Permalink
Merge branch 'main' into feat/added_check_to_from_hex_unchecked
Browse files Browse the repository at this point in the history
  • Loading branch information
MauroToscano authored Aug 31, 2023
2 parents 23fcebc + 0b60db9 commit 0c757a9
Show file tree
Hide file tree
Showing 16 changed files with 412 additions and 412 deletions.
175 changes: 52 additions & 123 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,15 @@ From the heights of these towers of fields, forty centuries of mathematics look
[![Telegram Chat][tg-badge]][tg-url]
[![codecov](https://img.shields.io/codecov/c/github/lambdaclass/lambdaworks)](https://codecov.io/gh/lambdaclass/lambdaworks)

[tg-badge]: https://img.shields.io/static/v1?color=green&logo=telegram&label=chat&style=flat&message=join
[tg-url]: https://t.me/+98Whlzql7Hs0MDZh
[tg-badge]: https://img.shields.io/endpoint?url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Flambdaworks%2F&logo=telegram&label=chat&color=neon
[tg-url]: https://t.me/lambdaworks

</div>

Zero-Knowledge and Validity Proofs have gained a lot of attention over the last few years. We strongly believe in this potential and that is why we decided to start working in this challenging ecosystem, where math, cryptography and distributed systems meet. The main barrier in the beginning was not the cryptography or math but the lack of good libraries which are performant and developer friendly. There are some exceptions, though, like gnark or halo2. Some have nice APIs and are easy to work with, but they are not written in Rust, and some are written in Rust but have poor programming and engineering practices. Most of them don't have support for CUDA, Metal and WebGPU or distributed FFT calculation using schedulers like Dask.

So, we decided to build our library, focusing on performance, with clear documentation and developer-focused. Our core team is a group of passionate people from different backgrounds and different strengths; we think that the whole is greater than just the addition of the parts. We don't want to be a compilation of every research result in the ZK space. We want this to be a library that can be used in production, not just in academic research. We want to offer developers the main building blocks and proof systems so that they can build their applications on top of this library.

## 📊 Benchmarks

Benchmark results are hosted [here](https://lambdaclass.github.io/lambdaworks/bench).

These are the results of execution of the benchmarks for finite field arithmetic using the STARK field prime (p = 3618502788666131213697322783095070105623107215331596699973092056135872020481). Benchmark results were run with AMD Ryzen 7 PRO 4750G with Radeon Graphics (32 GB RAM) using Ubuntu 20.04.6 LTS

| | arkworks | lambdaworks |
| -------- | --------- | ----------- |
| `add` | 15.170 μs | 13.042 μs |
| `sub` | 15.493 μs | 14.888 μs |
| `mul` | 60.462 μs | 57.014 μs |
| `invert` | 35.475 ms | 35.216 ms |
| `sqrt` | 126.39 ms | 133.74 ms |
| `pow` | 12.139 ms | 12.148 ms |

To run them locally, you will need `cargo-criterion` and `cargo-flamegraph`. Install it with:

```bash
cargo install cargo-criterion
```

Run the complete benchmark suite with:

```bash
make benchmarks
```

Run a specific benchmark suite with `cargo`, for example to run the one for `field`:

```bash
make benchmark BENCH=field
```

You can check the generated HTML report in `target/criterion/reports/index.html`

## Provers and Polynomial Commitment Schemes using LambdaWorks
- [Cairo STARK LambdaWorks prover](https://github.com/lambdaclass/lambdaworks_cairo_prover/tree/main)
- [Plonk LambdaWorks prover](https://github.com/lambdaclass/lambdaworks_plonk_prover)
Expand Down Expand Up @@ -81,92 +46,6 @@ If you use ```Lambdaworks``` libraries in your research projects, please cite th
}
```

## Building blocks

- Finite Field Algebra
- Elliptic curve models
- Elliptic curve operations
- Arithmetization schemes
- Polynomial commitment schemes
- PIOP
- Cryptographic tools
- Advanced tools: aggregation, recursion, accumulation
- Protocols
- Gadgets

## Blocks

### Finite Field Algebra

- Big integer representation
- Basic algebra: addition, multiplication, subtraction, inversion, square root (Tonelli–Shanks) ✔️
- Field extensions ✔️
- Number theoretic transform ✔️
- Polynomial operations ✔️
- Fast Fourier Transform ✔️
- Montgomery ✔️ and Barrett

### Elliptic curve models

- BLS12-381 ✔️
- BLS12-377 (H)
- secp256k1 (H)
- Ed25519 (H)
- Jubjub (M)
- BN254 (M)
- Pasta: Pallas and Vesta (L)
- Forms:
1. Affine ✔️
2. Projective ✔️
3. Montgomery (M)
4. Twisted Edwards (H)
5. Jacobi (L)

### Elliptic curve operations

- Add, double, scalar multiplication. ✔️
- Multiscalar multiplication (Pippenger) ✔️
- Weyl, Tate and Ate pairings. ✔️

### Arithmetization

- R1CS - gadgets (H)
- AIR ✔️
- Plonkish ✔️
- ACIR (L)

### Polynomial commitment schemes

- KZG and variants ✔️
- Hashing / Merkle trees ✔️
- Inner product arguments
- Dory (L)

### PIOP/PCS

- Groth16
- Plonk ✔️
- Marlin
- FRI ✔️

### [Crypto primitives](https://github.com/RustCrypto)

- Pseudorandom generator
- Hashes
- Blake2
- Keccak
- Poseidon
- Pedersen
- Encryption schemes
- AES
- ChaCha20
- Rescue
- ElGamal

### Protocol

- Fiat-Shamir ✔️

### Gadgets

## Fuzzers
Expand All @@ -184,3 +63,53 @@ To serve the documentation locally, first install both [mdbook](https://rust-lan
``` shell
make docs
```

## 📊 Benchmarks

Benchmark results are hosted [here](https://lambdaclass.github.io/lambdaworks/bench).

These are the results of execution of the benchmarks for finite field arithmetic using the STARK field prime (p = 3618502788666131213697322783095070105623107215331596699973092056135872020481).

Differences of 3% are common for some measurements, so small differences are not statistically relevant.

ARM - M1

| Operation| N | Arkworks | Lambdaworks |
| -------- | --- | --------- | ----------- |
| `mul` | 10k | 112 μs | 115 μs |
| `add` | 1M | 8.5 ms | 7.0 ms |
| `sub` | 1M | 7.53 ms | 7.12 ms |
| `pow` | 10k | 11.2 ms | 12.4 ms |
| `invert` | 10k | 30.0 ms | 27.2 ms |

x86 - AMD Ryzen 7 PRO

| Operation | N | Arkworks (ASM)* | Lambdaworks |
| -------- | --- | --------- | ----------- |
| `mul` | 10k | 118.9 us | 95.7 us |
| `add` | 1M | 6.8 ms | 5.4 ms |
| `sub` | 1M | 6.6 ms | 5.2 ms |
| `pow` | 10k | 10.6 ms | 9.4 ms |
| `invert` | 10k | 34.2 ms | 35.74 ms |

*assembly feature was enabled manually for that bench, and is not activated by default when running criterion

To run them locally, you will need `cargo-criterion` and `cargo-flamegraph`. Install it with:

```bash
cargo install cargo-criterion
```

Run the complete benchmark suite with:

```bash
make benchmarks
```

Run a specific benchmark suite with `cargo`, for example to run the one for `field`:

```bash
make benchmark BENCH=field
```

You can check the generated HTML report in `target/criterion/reports/index.html`
1 change: 1 addition & 0 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ ark-ff = { git = "https://github.com/arkworks-rs/algebra", rev = "ef8f758" }
ark-test-curves = { git = "https://github.com/arkworks-rs/algebra", rev = "ef8f758" }
ark-std = "0.4.0"
rand = "0.8.5"
rand_chacha = "0.3.1"

[dependencies.lambdaworks-math]
path = "../math"
Expand Down
77 changes: 34 additions & 43 deletions benches/benches/add.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,26 @@
use std::ops::Add;
use std::{ops::Add, time::Duration};

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use lambdaworks_math::traits::ByteConversion;
use rand::RngCore;
use utils::generate_random_elements;

use crate::utils::to_lambdaworks_vec;

pub mod utils;

const BENCHMARK_NAME: &str = "add";

pub fn criterion_benchmark(c: &mut Criterion) {
let arkworks_vec = generate_random_elements(2000000);

// arkworks-ff
{
use ark_std::{test_rng, UniformRand};
use ark_test_curves::starknet_fp::Fq as F;

let mut rng = test_rng();

let mut v = Vec::new();
for _i in 0..10000 {
let a = F::rand(&mut rng);
v.push(a);
}

c.bench_function(
&format!(
"{} | ark-ff - branch: faster-benchmarks-and-starknet-field",
BENCHMARK_NAME
),
&format!("{} 1M elements | ark-ff - ef8f758", BENCHMARK_NAME),
|b| {
b.iter(|| {
let mut iter = v.iter();
let mut iter = arkworks_vec.iter();

for _i in 0..5000 {
for _i in 0..1000000 {
let a = iter.next().unwrap();
let b = iter.next().unwrap();
black_box(black_box(&a).add(black_box(b)));
Expand All @@ -41,32 +32,32 @@ pub fn criterion_benchmark(c: &mut Criterion) {

// lambdaworks-math
{
use lambdaworks_math::field::{
element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField,
};
let mut v = Vec::new();
let mut buf = [0u8; 32];
for _i in 0..10000 {
rand::thread_rng().fill_bytes(&mut buf[..]);

let a = FieldElement::<Stark252PrimeField>::from_bytes_be(&buf).unwrap();

v.push(a);
}
let lambdaworks_vec = to_lambdaworks_vec(&arkworks_vec);

c.bench_function(&format!("{} | lambdaworks", BENCHMARK_NAME,), |b| {
b.iter(|| {
let mut iter = v.iter();
c.bench_function(
&format!("{} 1M elements | lambdaworks", BENCHMARK_NAME,),
|b| {
b.iter(|| {
let mut iter = lambdaworks_vec.iter();

for _i in 0..5000 {
let a = iter.next().unwrap();
let b = iter.next().unwrap();
black_box(black_box(&a).add(black_box(b)));
}
});
});
for _i in 0..1000000 {
let a = iter.next().unwrap();
let b = iter.next().unwrap();
black_box(black_box(&a).add(black_box(b)));
}
});
},
);
}
}

criterion_group!(benches, criterion_benchmark);
criterion_group! {
name = benches;
// This can be any expression that returns a `Criterion` object.
config = Criterion::default()
.significance_level(0.01)
.measurement_time(Duration::from_secs(15))
.sample_size(300);
targets = criterion_benchmark
}
criterion_main!(benches);
57 changes: 20 additions & 37 deletions benches/benches/invert.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,23 @@
use ark_ff::Field;
use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
use lambdaworks_math::traits::ByteConversion;
use rand::RngCore;
use utils::generate_random_elements;

use crate::utils::to_lambdaworks_vec;

pub mod utils;

const BENCHMARK_NAME: &str = "invert";

pub fn criterion_benchmark(c: &mut Criterion) {
let arkworks_vec = generate_random_elements(10000).to_vec();

// arkworks-ff
{
use ark_std::{test_rng, UniformRand};
use ark_test_curves::starknet_fp::Fq as F;

let mut rng = test_rng();

let mut v = Vec::new();
for _i in 0..10000 {
let a = F::rand(&mut rng);
v.push(a);
}

c.bench_function(
&format!(
"{} | ark-ff - branch: faster-benchmarks-and-starknet-field",
BENCHMARK_NAME
),
&format!("{} 10000 elements| ark-ff - ef8f758", BENCHMARK_NAME),
|b| {
b.iter_batched(
|| v.clone(),
|| arkworks_vec.clone(),
|mut v| {
for mut elem in v.iter_mut() {
black_box(black_box(&mut elem).inverse_in_place());
Expand All @@ -40,26 +31,18 @@ pub fn criterion_benchmark(c: &mut Criterion) {

// lambdaworks-math
{
use lambdaworks_math::field::{
element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField,
};
let mut v = Vec::new();
let mut buf = [0u8; 32];
for _i in 0..10000 {
rand::thread_rng().fill_bytes(&mut buf[..]);
let lambdaworks_vec = to_lambdaworks_vec(&arkworks_vec);

let a = FieldElement::<Stark252PrimeField>::from_bytes_be(&buf).unwrap();

v.push(a);
}

c.bench_function(&format!("{} | lambdaworks", BENCHMARK_NAME,), |b| {
b.iter(|| {
for elem in v.iter() {
black_box(black_box(&elem).inv());
}
});
});
c.bench_function(
&format!("{} 10000 elements | lambdaworks", BENCHMARK_NAME,),
|b| {
b.iter(|| {
for elem in lambdaworks_vec.iter() {
black_box(black_box(&elem).inv());
}
});
},
);
}
}

Expand Down
Loading

0 comments on commit 0c757a9

Please sign in to comment.