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

Optimize ec add affine #628

Closed
wants to merge 60 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
7358973
Draft benches
MauroToscano Oct 20, 2023
d122408
Refactor
MauroToscano Oct 20, 2023
f6665cc
Update text
MauroToscano Oct 20, 2023
2e0b8c2
Clippy
MauroToscano Oct 20, 2023
35fba5f
Change point for generator to avoid falling in a small subgroup
MauroToscano Oct 20, 2023
350f684
Change to doubles
MauroToscano Oct 20, 2023
2760308
Re add logic
MauroToscano Oct 20, 2023
57585de
Only lambdaworks bench
MauroToscano Oct 20, 2023
db82eb0
Add iai bench
MauroToscano Oct 20, 2023
8737711
Add bench
MauroToscano Oct 20, 2023
e0c9a1d
Inline never
MauroToscano Oct 20, 2023
71a82f7
Test
MauroToscano Oct 20, 2023
add8da0
Revert
MauroToscano Oct 20, 2023
a7e9b83
Re code
MauroToscano Oct 20, 2023
36ee9ee
Jacobian fix
MauroToscano Oct 23, 2023
58fa81e
Add skeleton for testing point doubling
entropidelic Oct 23, 2023
4b5b176
Keep working on test
entropidelic Oct 23, 2023
6beac54
Add skeleton test for operating with other point
entropidelic Oct 23, 2023
50aca5d
Add expected point in operate with other test
entropidelic Oct 23, 2023
5f26dca
Fix some bugs
entropidelic Oct 23, 2023
b678e5c
Doubling a point test passing
entropidelic Oct 23, 2023
dff6aa3
add references to algorithms used
entropidelic Oct 23, 2023
1886b4e
Polish algorithm for readibility
entropidelic Oct 24, 2023
743b850
Merge remote-tracking branch 'origin/main' into optimize-ec-add
entropidelic Oct 24, 2023
ca8c59a
operate with affine
juan518munoz Oct 23, 2023
c68b2e2
op w/ affine test
juan518munoz Oct 24, 2023
8822483
double fun & op w affine
juan518munoz Oct 24, 2023
5798f3a
w affine work
juan518munoz Oct 24, 2023
9bad335
rmv include
juan518munoz Oct 24, 2023
ee28f65
tests
juan518munoz Oct 24, 2023
9eda86b
mod test order
juan518munoz Oct 24, 2023
6ebae08
Add some tests
entropidelic Oct 24, 2023
43213ab
rmv comments
juan518munoz Oct 24, 2023
f2b4ed6
cargo fmt
juan518munoz Oct 24, 2023
6c2a505
Fix test compress_decompress_2g
entropidelic Oct 24, 2023
6762e0f
Fix test_add_accumulate_line_adds_points_correctly
entropidelic Oct 24, 2023
c8d99e6
Fix test_double_accumulate_line_doubles_point_correctly
entropidelic Oct 24, 2023
ccc0566
Fix add_points test
entropidelic Oct 24, 2023
cf4af19
Fix test msm_with_c_2_3_hiding_3_4_is_18_over_elliptic_curves
entropidelic Oct 24, 2023
92d3fb5
Merge branch 'optimize-ec-add' into optimize-ec-add-affine
juan518munoz Oct 24, 2023
84f0faa
Fix serialization of short weierstrass points
entropidelic Oct 24, 2023
e86dd9d
Comment one test
entropidelic Oct 24, 2023
f5efff4
Save optimizations
entropidelic Oct 24, 2023
64976ba
Remove prints
entropidelic Oct 24, 2023
7526e67
Fix all tests
entropidelic Oct 24, 2023
4ffc06b
Merge branch 'optimize-ec-add' into optimize-ec-add-affine
juan518munoz Oct 24, 2023
b342807
fix compile on no default
juan518munoz Oct 24, 2023
87c001d
fix test using wrong fun
juan518munoz Oct 24, 2023
33d367f
clippy flag to surpress warning
juan518munoz Oct 24, 2023
8b6606a
rmv clippy warn, will fail either way
juan518munoz Oct 24, 2023
8ee7a56
Polish some details
entropidelic Oct 24, 2023
0cd1750
Merge branch 'optimize-ec-add' into optimize-ec-add-affine
juan518munoz Oct 25, 2023
d2713bc
wrap affine add in result, document
juan518munoz Oct 25, 2023
5b6e7a2
Re work benchmark
MauroToscano Oct 25, 2023
331fdf9
Remove clones from operate_with_affine algorithm
entropidelic Oct 25, 2023
f5d3002
Merge remote-tracking branch 'origin/optimize-ec-add-affine' into opt…
entropidelic Oct 25, 2023
a1cbe4e
Format
entropidelic Oct 25, 2023
8a1a2d3
Remove calls to double
entropidelic Oct 25, 2023
c2531fe
Remove unused import
entropidelic Oct 25, 2023
9c6e663
Remove comment
entropidelic Oct 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 31 additions & 24 deletions benches/benches/point.rs
Original file line number Diff line number Diff line change
@@ -1,70 +1,77 @@
use std::ops::{Add, AddAssign};

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use lambdaworks_math::{
cyclic_group::IsGroup,
elliptic_curve::{short_weierstrass::curves::stark_curve::StarkCurve, traits::IsEllipticCurve},
};
use starknet_curve::{curve_params::GENERATOR, AffinePoint, ProjectivePoint};
use std::ops::AddAssign;

const BENCHMARK_NAME: &str = "point";

pub fn criterion_benchmark(c: &mut Criterion) {
let initial_projective_point = ProjectivePoint::from(&GENERATOR);
let second_project_point = initial_projective_point;
let starknet_rs_affine_generator = GENERATOR;

let starknet_rs_initial_projective =
ProjectivePoint::from_affine_point(&GENERATOR.add(&GENERATOR));
// This is the code we are going to bench
// We test it once outside the bench to check the result matches with Lambdaworks
let mut projective_point = initial_projective_point;
let mut projective_point_rs = starknet_rs_initial_projective;
for _i in 0..10000 {
projective_point.add_assign(&second_project_point);
projective_point_rs.add_assign(&starknet_rs_affine_generator);
}

let starknet_rs_x = AffinePoint::from(&projective_point).x.to_string();
println!("Starknet RS result X: {} ", starknet_rs_x);
let starknet_rs_y = AffinePoint::from(&projective_point).y.to_string();
print!("Starknet RS result Y: {} ", starknet_rs_y);
let starknet_rs_x = AffinePoint::from(&projective_point_rs).x;
println!("Starknet RS result - X: {:#x} ", starknet_rs_x);
let starknet_rs_y = AffinePoint::from(&projective_point_rs).y;
println!("Starknet RS result - Y: {:#x} ", starknet_rs_y);

{
c.bench_function(
&format!("{} 10k Operations | Starknet RS ", BENCHMARK_NAME),
&format!(
"{} 10k Operations with Affine | Starknet RS ",
BENCHMARK_NAME
),
|b| {
b.iter(|| {
let mut projective_point = initial_projective_point;
// We loop to have a higher variance of numbers, and make the time of the clones not relevant
let mut projective_point_rs = starknet_rs_initial_projective;
for _i in 0..10000 {
projective_point.add_assign(&second_project_point);
projective_point_rs.add_assign(black_box(&starknet_rs_affine_generator));
}
projective_point
projective_point_rs
});
},
);
}

let initial_projective_point = StarkCurve::generator();
let second_projective_point = initial_projective_point.clone();
let lambdaworks_affine_generator = StarkCurve::generator();

// This is the code we are going to bench
// We test it once outside the bench to check the result matches with Starknet RS
let mut projective_point = initial_projective_point.clone();
let lambdaworks_rs_initial_projective =
StarkCurve::generator().operate_with(&StarkCurve::generator());

let mut projective_point = lambdaworks_rs_initial_projective.clone();
for _i in 0..10000 {
projective_point =
black_box(projective_point.operate_with(black_box(&second_projective_point)));
black_box(projective_point.operate_with(black_box(&lambdaworks_affine_generator)));
}

let lambdaworks_x = projective_point.to_affine().x().to_string();
let lambdaworks_y = projective_point.to_affine().y().to_string();
println!("Lambdaworks result, X: {}", lambdaworks_x);
println!("Lambdaworks result, Y: {}", lambdaworks_y);
println!("Lambdaworks result - X: {}", lambdaworks_x);
println!("Lambdaworks result - Y: {}", lambdaworks_y);

{
c.bench_function(
&format!("{} 10k Operations | Lambdaworks", BENCHMARK_NAME),
|b| {
b.iter(|| {
let mut projective_point = initial_projective_point.clone();
let mut projective_point = lambdaworks_rs_initial_projective.clone();
for _i in 0..10000 {
projective_point = black_box(
projective_point.operate_with(black_box(&second_projective_point)),
);
projective_point = projective_point
.operate_with_affine(black_box(&lambdaworks_affine_generator));
// .unwrap();
}
projective_point
});
Expand Down
15 changes: 0 additions & 15 deletions crypto/src/commitments/kzg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,19 +411,4 @@ mod tests {

assert_eq!(srs, deserialized);
}

#[test]
fn load_srs_from_file() {
type TestSrsType = StructuredReferenceString<
ShortWeierstrassProjectivePoint<BLS12381Curve>,
ShortWeierstrassProjectivePoint<BLS12381TwistCurve>,
>;

let base_dir = env!("CARGO_MANIFEST_DIR");
let srs_file = base_dir.to_owned() + "/src/commitments/test_srs/srs_3_g1_elements.bin";

let srs = TestSrsType::from_file(&srs_file).unwrap();

assert_eq!(srs.powers_main_group.len(), 3);
}
}
4 changes: 4 additions & 0 deletions math/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,7 @@ harness = false
name = "criterion_metal"
harness = false
required-features = ["metal"]

[[bench]]
name = "iai_point_add"
harness = false
37 changes: 37 additions & 0 deletions math/benches/iai_point_add.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::ops::AddAssign;

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use lambdaworks_math::{
cyclic_group::IsGroup,
elliptic_curve::{
short_weierstrass::{
curves::stark_curve::StarkCurve, point::ShortWeierstrassProjectivePoint,
},
traits::{FromAffine, IsEllipticCurve},
},
field::{
element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField,
},
};

const BENCHMARK_NAME: &str = "point";

#[inline(never)]
pub fn add_for_bench() -> ShortWeierstrassProjectivePoint<StarkCurve> {
let initial_projective_point = StarkCurve::generator();
let second_projective_point = initial_projective_point.clone();

// This is the code we are going to bench
// We test it once outside the bench to check the result matches with Starknet RS
let mut projective_point = initial_projective_point.clone();
for _i in 0..10000 {
projective_point =
black_box(projective_point.operate_with_affine(black_box(&second_projective_point)));
}
projective_point
}

iai_callgrind::main!(
callgrind_args = "toggle-collect=util::*";
functions = add_for_bench,
);
23 changes: 16 additions & 7 deletions math/src/elliptic_curve/point.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::elliptic_curve::traits::IsEllipticCurve;
use crate::field::element::FieldElement;
use core::fmt::Debug;
/// Represents an elliptic curve point using the projective short Weierstrass form:

/// Represents an elliptic curve point using the projective jacobian
/// y^2 * z = x^3 + a * x * z^2 + b * z^3,
/// where `x`, `y` and `z` variables are field elements.
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -36,13 +37,21 @@ impl<E: IsEllipticCurve> ProjectivePoint<E> {
}

/// Creates the same point in affine coordinates. That is,
/// returns [x / z: y / z: 1] where `self` is [x: y: z].
/// returns [x / z^2: y / z^3: 1] where `self` is [x: y: z].
/// Panics if `self` is the point at infinity.
pub fn to_affine(&self) -> Self {
let [x, y, z] = self.coordinates();
assert_ne!(z, &FieldElement::zero());
if z == &FieldElement::zero() {
return ProjectivePoint::new([
FieldElement::zero(),
FieldElement::zero(),
FieldElement::zero(),
]);
}
let inv_z = z.inv().unwrap();
ProjectivePoint::new([x * &inv_z, y * inv_z, FieldElement::one()])
let inv_z_square = inv_z.square();
let inv_z_cube = &inv_z * &inv_z_square;
ProjectivePoint::new([x * &inv_z_square, y * inv_z_cube, FieldElement::one()])
}
}

Expand Down Expand Up @@ -99,8 +108,8 @@ mod tests {
fn operate_with_self_works_1() {
let g = TestCurve1::generator();
assert_eq!(
g.operate_with(&g).operate_with(&g),
g.operate_with_self(3_u16)
g.operate_with(&g).operate_with(&g).to_affine(),
g.operate_with_self(3_u16).to_affine()
);
}

Expand Down Expand Up @@ -144,7 +153,7 @@ mod tests {
)
.unwrap();

assert_eq!(point_1, expected_result);
assert_eq!(point_1.to_affine(), expected_result.to_affine());
}

#[test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ mod tests {
fn adding_five_times_point_1_works() {
let point_1 = point_1();
let point_1_times_5 = point_1_times_5();
assert_eq!(point_1.operate_with_self(5_u16), point_1_times_5);
assert_eq!(
point_1.operate_with_self(5_u16).to_affine(),
point_1_times_5
);
}

#[test]
Expand Down Expand Up @@ -92,8 +95,8 @@ mod tests {
fn operate_with_self_works_1() {
let g = BLS12377Curve::generator();
assert_eq!(
g.operate_with(&g).operate_with(&g),
g.operate_with_self(3_u16)
g.operate_with(&g).operate_with(&g).to_affine(),
g.operate_with_self(3_u16).to_affine()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,9 @@ mod tests {
fn test_compress_decompress_2g() {
let g = BLS12381Curve::generator();
// calculate g point operate with itself
let g_2 = g.operate_with_self(UnsignedInteger::<4>::from("2"));
let g_2 = g
.operate_with_self(UnsignedInteger::<4>::from("2"))
.to_affine();

let compressed_g2 = compress_g1_point(&g_2);
let mut compressed_g2_slice: [u8; 48] = compressed_g2.try_into().unwrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ mod tests {
fn adding_five_times_point_1_works() {
let point_1 = point_1();
let point_1_times_5 = point_1_times_5();
assert_eq!(point_1.operate_with_self(5_u16), point_1_times_5);
assert_eq!(
point_1.operate_with_self(5_u16).to_affine(),
point_1_times_5
);
}

#[test]
Expand Down Expand Up @@ -113,8 +116,8 @@ mod tests {
fn operate_with_self_works_1() {
let g = BLS12381Curve::generator();
assert_eq!(
g.operate_with(&g).operate_with(&g),
g.operate_with_self(3_u16)
g.operate_with(&g).operate_with(&g).to_affine(),
g.operate_with_self(3_u16).to_affine()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ mod tests {
let mut r = g2.clone();
let mut f = FieldElement::one();
double_accumulate_line(&mut r, &g1, &mut f);
assert_eq!(r, g2.operate_with(&g2));
assert_eq!(r, g2.operate_with(&g2).to_affine());
}

#[test]
Expand All @@ -236,7 +236,7 @@ mod tests {
let mut r = g2;
let mut f = FieldElement::one();
add_accumulate_line(&mut r, &g3, &g1, &mut f);
assert_eq!(r, expected);
assert_eq!(r, expected.to_affine());
}

#[test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,6 @@ mod tests {
let p = BLS12381TwistCurve::create_point_from_affine(px, py).unwrap();
let q = BLS12381TwistCurve::create_point_from_affine(qx, qy).unwrap();
let expected = BLS12381TwistCurve::create_point_from_affine(expectedx, expectedy).unwrap();
assert_eq!(p.operate_with(&q), expected);
assert_eq!(p.operate_with(&q).to_affine(), expected);
}
}
Loading
Loading