Skip to content

Commit

Permalink
Merge branch 'main' into minimize_batch_merkle_proofs
Browse files Browse the repository at this point in the history
  • Loading branch information
diegokingston authored Oct 4, 2024
2 parents a28da76 + bec0b1a commit 6b595aa
Show file tree
Hide file tree
Showing 19 changed files with 1,826 additions and 508 deletions.
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ This library provides efficient implementation of cryptographic primitives used

</div>

## Examples - mini apps

Below is a list of examples to understand lambdaworks and learn what you can build with the tools provided.

- [Merkle Tree CLI](./examples/merkle-tree-cli/)
- [Proving Miden](./examples/prove-miden/)
- [Shamir's secret sharing](./examples/shamir_secret_sharing/)
- [BabySNARK](./examples/baby-snark/)
- [Pinocchio](./examples/pinocchio/)

## Why we built lambdaworks

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.
Expand All @@ -41,14 +51,6 @@ Most of math and crypto crates supports no-std without allocation with `no-defau

Both Math and Crypto support wasm with target `wasm32-unknown-unknown`. To see an example of how to use this to deploy a verifier in a browser, check the Cairo Prover wasm-pack verifier.

## Examples - mini apps

- [Merkle Tree CLI](https://github.com/lambdaclass/lambdaworks/tree/main/examples/merkle-tree-cli)
- [Proving Miden](https://github.com/lambdaclass/lambdaworks/tree/main/examples/prove-miden)
- [Shamir's secret sharing](https://github.com/lambdaclass/lambdaworks/tree/main/examples/shamir_secret_sharing)
- [BabySNARK](https://github.com/lambdaclass/lambdaworks/tree/main/examples/baby-snark)
- [Pinocchio](https://github.com/lambdaclass/lambdaworks/tree/main/examples/pinocchio)

## Exercises and Challenges

- [lambdaworks exercises and challenges](https://github.com/lambdaclass/lambdaworks_exercises/tree/main)
Expand Down
2 changes: 1 addition & 1 deletion math/benches/criterion_elliptic_curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ use elliptic_curves::{
criterion_group!(
name = elliptic_curve_benches;
config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None)));
targets = bn_254_elliptic_curve_benchmarks,bls12_377_elliptic_curve_benchmarks,bls12_381_elliptic_curve_benchmarks
targets = bn_254_elliptic_curve_benchmarks,bls12_381_elliptic_curve_benchmarks,bls12_377_elliptic_curve_benchmarks
);
criterion_main!(elliptic_curve_benches);
4 changes: 2 additions & 2 deletions math/benches/criterion_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use criterion::{criterion_group, criterion_main, Criterion};
use pprof::criterion::{Output, PProfProfiler};

mod fields;
use fields::mersenne31::mersenne31_ops_benchmarks;
use fields::mersenne31::{mersenne31_extension_ops_benchmarks, mersenne31_ops_benchmarks};
use fields::mersenne31_montgomery::mersenne31_mont_ops_benchmarks;
use fields::{
stark252::starkfield_ops_benchmarks, u64_goldilocks::u64_goldilocks_ops_benchmarks,
Expand All @@ -12,6 +12,6 @@ use fields::{
criterion_group!(
name = field_benches;
config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None)));
targets = starkfield_ops_benchmarks, mersenne31_ops_benchmarks, mersenne31_mont_ops_benchmarks, u64_goldilocks_ops_benchmarks, u64_goldilocks_montgomery_ops_benchmarks
targets = mersenne31_ops_benchmarks, mersenne31_extension_ops_benchmarks, mersenne31_mont_ops_benchmarks, starkfield_ops_benchmarks, u64_goldilocks_ops_benchmarks, u64_goldilocks_montgomery_ops_benchmarks
);
criterion_main!(field_benches);
16 changes: 15 additions & 1 deletion math/benches/elliptic_curves/bls12_381.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use lambdaworks_math::{
elliptic_curve::{
short_weierstrass::{
curves::bls12_381::{
curve::BLS12381Curve, pairing::BLS12381AtePairing, twist::BLS12381TwistCurve,
curve::BLS12381Curve,
pairing::{final_exponentiation, miller, BLS12381AtePairing},
twist::BLS12381TwistCurve,
},
traits::Compress,
},
Expand All @@ -24,6 +26,8 @@ pub fn bls12_381_elliptic_curve_benchmarks(c: &mut Criterion) {
let a_g2 = BLS12381TwistCurve::generator();
let b_g2 = BLS12381TwistCurve::generator();

let miller_loop_output = miller(&a_g2, &a_g1);

let mut group = c.benchmark_group("BLS12-381 Ops");
group.significance_level(0.1).sample_size(10000);
group.throughput(criterion::Throughput::Elements(1));
Expand Down Expand Up @@ -93,4 +97,14 @@ pub fn bls12_381_elliptic_curve_benchmarks(c: &mut Criterion) {
))
});
});

// Miller
group.bench_function("Miller", |bencher| {
bencher.iter(|| black_box(miller(black_box(&a_g2), black_box(&a_g1))))
});

// Final Exponentiation Optimized
group.bench_function("Final Exponentiation", |bencher| {
bencher.iter(|| black_box(final_exponentiation(black_box(&miller_loop_output))))
});
}
64 changes: 63 additions & 1 deletion math/benches/fields/mersenne31.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
use std::hint::black_box;

use criterion::Criterion;
use lambdaworks_math::field::{element::FieldElement, fields::mersenne31::field::Mersenne31Field};
use lambdaworks_math::field::{
element::FieldElement,
fields::mersenne31::{
extensions::{Degree2ExtensionField, Degree4ExtensionField},
field::Mersenne31Field,
},
};
use rand::random;

pub type F = FieldElement<Mersenne31Field>;
pub type Fp2E = FieldElement<Degree2ExtensionField>;
pub type Fp4E = FieldElement<Degree4ExtensionField>;

#[inline(never)]
#[no_mangle]
Expand All @@ -17,6 +25,60 @@ pub fn rand_field_elements(num: usize) -> Vec<(F, F)> {
result
}

//TODO: Check if this is the correct way to bench.
pub fn rand_fp4e(num: usize) -> Vec<(Fp4E, Fp4E)> {
let mut result = Vec::with_capacity(num);
for _ in 0..result.capacity() {
result.push((
Fp4E::new([
Fp2E::new([F::new(random()), F::new(random())]),
Fp2E::new([F::new(random()), F::new(random())]),
]),
Fp4E::new([
Fp2E::new([F::new(random()), F::new(random())]),
Fp2E::new([F::new(random()), F::new(random())]),
]),
));
}
result
}

pub fn mersenne31_extension_ops_benchmarks(c: &mut Criterion) {
let input: Vec<Vec<(Fp4E, Fp4E)>> = [1000000].into_iter().map(rand_fp4e).collect::<Vec<_>>();

let mut group = c.benchmark_group("Mersenne31 Fp4 operations");

for i in input.clone().into_iter() {
group.bench_with_input(format!("Mul of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(x) * black_box(y));
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Square of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).square());
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Inv of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).inv().unwrap());
}
});
});
}
}

pub fn mersenne31_ops_benchmarks(c: &mut Criterion) {
let input: Vec<Vec<(F, F)>> = [1, 10, 100, 1000, 10000, 100000, 1000000]
.into_iter()
Expand Down
139 changes: 126 additions & 13 deletions math/src/elliptic_curve/short_weierstrass/curves/bls12_377/curve.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
use super::field_extension::BLS12377PrimeField;
use super::{
field_extension::{BLS12377PrimeField, Degree2ExtensionField},
twist::BLS12377TwistCurve,
};
use crate::cyclic_group::IsGroup;
use crate::elliptic_curve::short_weierstrass::point::ShortWeierstrassProjectivePoint;
use crate::elliptic_curve::traits::IsEllipticCurve;
use crate::unsigned_integer::element::U256;

use crate::{
elliptic_curve::short_weierstrass::traits::IsShortWeierstrass, field::element::FieldElement,
};

pub const SUBGROUP_ORDER: U256 =
U256::from_hex_unchecked("12ab655e9a2ca55660b44d1e5c37b00159aa76fed00000010a11800000000001");

pub const CURVE_COFACTOR: U256 =
U256::from_hex_unchecked("0x30631250834960419227450344600217059328");

pub type BLS12377FieldElement = FieldElement<BLS12377PrimeField>;
pub type BLS12377TwistCurveFieldElement = FieldElement<Degree2ExtensionField>;

/// The description of the curve.
#[derive(Clone, Debug)]
pub struct BLS12377Curve;
Expand Down Expand Up @@ -32,6 +47,71 @@ impl IsShortWeierstrass for BLS12377Curve {
}
}

/// This is equal to the frobenius trace of the BLS12 377 curve minus one or seed value z.
pub const MILLER_LOOP_CONSTANT: u64 = 0x8508c00000000001;

/// 𝛽 : primitive cube root of unity of 𝐹ₚ that §satisfies the minimal equation
/// 𝛽² + 𝛽 + 1 = 0 mod 𝑝
pub const CUBE_ROOT_OF_UNITY_G1: BLS12377FieldElement = FieldElement::from_hex_unchecked(
"0x1ae3a4617c510eabc8756ba8f8c524eb8882a75cc9bc8e359064ee822fb5bffd1e945779fffffffffffffffffffffff",
);

/// x-coordinate of 𝜁 ∘ 𝜋_q ∘ 𝜁⁻¹, where 𝜁 is the isomorphism u:E'(𝔽ₚ₆) −> E(𝔽ₚ₁₂) from the twist to E
pub const ENDO_U: BLS12377TwistCurveFieldElement =
BLS12377TwistCurveFieldElement::const_from_raw([
FieldElement::from_hex_unchecked(
"9B3AF05DD14F6EC619AAF7D34594AABC5ED1347970DEC00452217CC900000008508C00000000002",
),
FieldElement::from_hex_unchecked("0"),
]);

/// y-coordinate of 𝜁 ∘ 𝜋_q ∘ 𝜁⁻¹, where 𝜁 is the isomorphism u:E'(𝔽ₚ₆) −> E(𝔽ₚ₁₂) from the twist to E
pub const ENDO_V: BLS12377TwistCurveFieldElement =
BLS12377TwistCurveFieldElement::const_from_raw([
FieldElement::from_hex_unchecked("1680A40796537CAC0C534DB1A79BEB1400398F50AD1DEC1BCE649CF436B0F6299588459BFF27D8E6E76D5ECF1391C63"),
FieldElement::from_hex_unchecked("0"),
]);

impl ShortWeierstrassProjectivePoint<BLS12377Curve> {
/// Returns 𝜙(P) = (𝑥, 𝑦) ⇒ (𝛽𝑥, 𝑦), where 𝛽 is the Cube Root of Unity in the base prime field
/// https://eprint.iacr.org/2022/352.pdf 2 Preliminaries
fn phi(&self) -> Self {
let mut a = self.clone();
a.0.value[0] = a.x() * CUBE_ROOT_OF_UNITY_G1;
a
}

/// 𝜙(P) = −𝑢²P
/// https://eprint.iacr.org/2022/352.pdf 4.3 Prop. 4
pub fn is_in_subgroup(&self) -> bool {
self.operate_with_self(MILLER_LOOP_CONSTANT)
.operate_with_self(MILLER_LOOP_CONSTANT)
.neg()
== self.phi()
}
}

impl ShortWeierstrassProjectivePoint<BLS12377TwistCurve> {
/// 𝜓(P) = 𝜁 ∘ 𝜋ₚ ∘ 𝜁⁻¹, where 𝜁 is the isomorphism u:E'(𝔽ₚ₆) −> E(𝔽ₚ₁₂) from the twist to E,, 𝜋ₚ is the p-power frobenius endomorphism
/// and 𝜓 satisifies minmal equation 𝑋² + 𝑡𝑋 + 𝑞 = 𝑂
/// https://eprint.iacr.org/2022/352.pdf 4.2 (7)
/// ψ(P) = (ψ_x * conjugate(x), ψ_y * conjugate(y), conjugate(z))
fn psi(&self) -> Self {
let [x, y, z] = self.coordinates();
Self::new([
x.conjugate() * ENDO_U,
y.conjugate() * ENDO_V,
z.conjugate(),
])
}

/// 𝜓(P) = 𝑢P, where 𝑢 = SEED of the curve
/// https://eprint.iacr.org/2022/352.pdf 4.2
pub fn is_in_subgroup(&self) -> bool {
self.psi() == self.operate_with_self(MILLER_LOOP_CONSTANT)
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -43,17 +123,18 @@ mod tests {
use super::BLS12377Curve;

#[allow(clippy::upper_case_acronyms)]
type FEE = FieldElement<BLS12377PrimeField>;
type FpE = FieldElement<BLS12377PrimeField>;
type Fp2 = FieldElement<Degree2ExtensionField>;

fn point_1() -> ShortWeierstrassProjectivePoint<BLS12377Curve> {
let x = FEE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea");
let y = FEE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2");
let x = FpE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea");
let y = FpE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2");
BLS12377Curve::create_point_from_affine(x, y).unwrap()
}

fn point_1_times_5() -> ShortWeierstrassProjectivePoint<BLS12377Curve> {
let x = FEE::new_base("3c852d5aab73fbb51e57fbf5a0a8b5d6513ec922b2611b7547bfed74cba0dcdfc3ad2eac2733a4f55d198ec82b9964");
let y = FEE::new_base("a71425e68e55299c64d7eada9ae9c3fb87a9626b941d17128b64685fc07d0e635f3c3a512903b4e0a43e464045967b");
let x = FpE::new_base("3c852d5aab73fbb51e57fbf5a0a8b5d6513ec922b2611b7547bfed74cba0dcdfc3ad2eac2733a4f55d198ec82b9964");
let y = FpE::new_base("a71425e68e55299c64d7eada9ae9c3fb87a9626b941d17128b64685fc07d0e635f3c3a512903b4e0a43e464045967b");
BLS12377Curve::create_point_from_affine(x, y).unwrap()
}

Expand Down Expand Up @@ -101,9 +182,9 @@ mod tests {
let point_1 = point_1().to_affine();

// Create point 2
let x = FEE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea") * FEE::from(2);
let y = FEE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2") * FEE::from(2);
let z = FEE::from(2);
let x = FpE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea") * FpE::from(2);
let y = FpE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2") * FpE::from(2);
let z = FpE::from(2);
let point_2 = ShortWeierstrassProjectivePoint::<BLS12377Curve>::new([x, y, z]);

let first_algorithm_result = point_2.operate_with(&point_1).to_affine();
Expand All @@ -115,15 +196,15 @@ mod tests {
#[test]
fn create_valid_point_works() {
let p = point_1();
assert_eq!(*p.x(), FEE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea"));
assert_eq!(*p.y(), FEE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2"));
assert_eq!(*p.z(), FEE::new_base("1"));
assert_eq!(*p.x(), FpE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea"));
assert_eq!(*p.y(), FpE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2"));
assert_eq!(*p.z(), FpE::new_base("1"));
}

#[test]
fn create_invalid_points_panics() {
assert_eq!(
BLS12377Curve::create_point_from_affine(FEE::from(1), FEE::from(1)).unwrap_err(),
BLS12377Curve::create_point_from_affine(FpE::from(1), FpE::from(1)).unwrap_err(),
EllipticCurveError::InvalidPoint
)
}
Expand All @@ -144,4 +225,36 @@ mod tests {
g.operate_with_self(3_u16)
);
}

#[test]
fn generator_g1_is_in_subgroup() {
let g = BLS12377Curve::generator();
assert!(g.is_in_subgroup())
}

#[test]
fn point1_is_in_subgroup() {
let p = point_1();
assert!(p.is_in_subgroup())
}

#[test]
fn arbitrary_g1_point_is_in_subgroup() {
let g = BLS12377Curve::generator().operate_with_self(32u64);
assert!(g.is_in_subgroup())
}
#[test]
fn generator_g2_is_in_subgroup() {
let g = BLS12377TwistCurve::generator();
assert!(g.is_in_subgroup())
}

#[test]
fn g2_conjugate_works() {
let a = Fp2::zero();
let mut expected = a.conjugate();
expected = expected.conjugate();

assert_eq!(a, expected);
}
}
Loading

0 comments on commit 6b595aa

Please sign in to comment.