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

feat: add ec benchmark #147

Merged
merged 17 commits into from
Jul 6, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## [Unreleased]
### Added
- [\#144](https://github.com/Manta-Network/manta-rs/pull/144) Add new release PR template for future releases
- [\#147](https://github.com/Manta-Network/manta-rs/pull/147) Add benchmarks for Arkworks elliptic curve operations

### Changed

Expand Down
7 changes: 7 additions & 0 deletions manta-benchmark/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ maintenance = { status = "actively-developed" }
[lib]
crate-type = ["cdylib", "lib"]

[[bench]]
name = "ec"
harness = false

[[bench]]
name = "mint"
harness = false
Expand All @@ -40,6 +44,9 @@ name = "reclaim"
harness = false

[dependencies]
ark-bls12-381 = { version = "0.3.0", default-features = false }
ark-ec = { version = "0.3.0", default-features = false }
ark-ff = { version = "0.3.0", default-features = false }
getrandom = { version = "0.2.6", features = ["js"] }
instant = { version = "0.1.12", features = [ "wasm-bindgen" ] }
manta-accounting = { path = "../manta-accounting", default-features = false, features = ["test"] }
Expand Down
130 changes: 130 additions & 0 deletions manta-benchmark/benches/ec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Copyright 2019-2022 Manta Network.
// This file is part of manta-rs.
//
// manta-rs is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// manta-rs is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with manta-rs. If not, see <http://www.gnu.org/licenses/>.

use ark_bls12_381::{g1::Parameters, G1Affine, G1Projective};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use manta_benchmark::ec;
use manta_crypto::rand::OsRng;

fn affine_affine_addition(c: &mut Criterion) {
let mut group = c.benchmark_group("bench");
let mut rng = OsRng;
let mut lhs = black_box(ec::sample_affine_point::<G1Affine, _>(&mut rng));
let rhs = black_box(ec::sample_affine_point(&mut rng));
group.bench_function("affine-affine addition", |b| {
b.iter(|| {
ec::affine_affine_add_assign(&mut lhs, &rhs);
})
});
}

fn projective_affine_addition(c: &mut Criterion) {
let mut group = c.benchmark_group("bench");
let mut rng = OsRng;
let mut lhs = black_box(ec::sample_projective_point::<G1Projective, _>(&mut rng));
let rhs = black_box(ec::sample_affine_point(&mut rng));
group.bench_function("projective-affine addition", |b| {
b.iter(|| {
ec::projective_affine_add_assign(&mut lhs, &rhs);
})
});
}

fn projective_projective_addition(c: &mut Criterion) {
let mut group = c.benchmark_group("bench");
let mut rng = OsRng;
let mut lhs = black_box(ec::sample_projective_point::<G1Projective, _>(&mut rng));
let rhs = black_box(ec::sample_projective_point::<G1Projective, _>(&mut rng));
group.bench_function("projective-projective addition", |b| {
b.iter(|| {
ec::projective_projective_add_assign(&mut lhs, &rhs);
})
});
}

fn affine_scalar_multiplication(c: &mut Criterion) {
let mut group = c.benchmark_group("bench");
let mut rng = OsRng;
let point = black_box(ec::sample_affine_point::<G1Affine, _>(&mut rng));
let scalar = black_box(ec::sample_scalar::<Parameters, _>(&mut rng));
group.bench_function("affine-scalar multiplication", |b| {
b.iter(|| {
let _ = ec::affine_scalar_mul(&point, scalar);
BoyuanFeng marked this conversation as resolved.
Show resolved Hide resolved
})
});
}

fn projective_scalar_multiplication(c: &mut Criterion) {
let mut group = c.benchmark_group("bench");
let mut rng = OsRng;
let mut point = black_box(ec::sample_projective_point::<G1Projective, _>(&mut rng));
let scalar = black_box(ec::sample_scalar::<Parameters, _>(&mut rng));
group.bench_function("projective-scalar multiplication", |b| {
b.iter(|| {
ec::projective_scalar_mul_assign(&mut point, scalar);
})
});
}

fn projective_to_affine_normalization(c: &mut Criterion) {
let mut group = c.benchmark_group("bench");
let mut rng = OsRng;
let point = black_box(ec::sample_projective_point::<G1Projective, _>(&mut rng));
group.bench_function("projective to affine normalization", |b| {
b.iter(|| {
let _ = ec::projective_to_affine_normalization(&point);
BoyuanFeng marked this conversation as resolved.
Show resolved Hide resolved
})
});
}

fn batch_vector_projective_to_affine_normalization(c: &mut Criterion) {
let mut group = c.benchmark_group("bench");
let mut rng = OsRng;
let point_vec = (0..(1 << 16))
.map(|_| ec::sample_projective_point::<G1Projective, _>(&mut rng))
.collect::<Vec<_>>();
group.bench_function("batch vector of projective to affine normalization", |b| {
b.iter(|| {
let _ = ec::batch_vector_projective_to_affine_normalization(point_vec.as_slice());
BoyuanFeng marked this conversation as resolved.
Show resolved Hide resolved
})
});
}

fn naive_vector_projective_to_affine_normalization(c: &mut Criterion) {
let mut group = c.benchmark_group("bench");
let mut rng = OsRng;
let point_vec = (0..(1 << 16))
.map(|_| ec::sample_projective_point::<G1Projective, _>(&mut rng))
.collect::<Vec<_>>();
group.bench_function("naive vector of projective to affine normalization", |b| {
b.iter(|| {
let _ = ec::naive_vector_projective_to_affine_normalization(point_vec.as_slice());
})
});
}

criterion_group!(
ec,
affine_affine_addition,
projective_affine_addition,
projective_projective_addition,
affine_scalar_multiplication,
projective_scalar_multiplication,
projective_to_affine_normalization,
batch_vector_projective_to_affine_normalization,
naive_vector_projective_to_affine_normalization,
);
criterion_main!(ec);
156 changes: 156 additions & 0 deletions manta-benchmark/src/ec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// Copyright 2019-2022 Manta Network.
// This file is part of manta-rs.
//
// manta-rs is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// manta-rs is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with manta-rs. If not, see <http://www.gnu.org/licenses/>.

use ark_ec::{
short_weierstrass_jacobian::{GroupAffine, GroupProjective},
AffineCurve, ProjectiveCurve, SWModelParameters,
};
use ark_ff::UniformRand;
use core::ops::{AddAssign, MulAssign};
use manta_crypto::rand::RngCore;

#[inline]
pub fn sample_affine_point<A, R>(rng: &mut R) -> A
where
A: AffineCurve,
R: RngCore + ?Sized,
{
A::Projective::rand(rng).into_affine()
}

#[inline]
pub fn sample_projective_point<P, R>(rng: &mut R) -> P
where
P: ProjectiveCurve,
R: RngCore + ?Sized,
{
P::rand(rng)
}

#[inline]
pub fn sample_scalar<P, R>(rng: &mut R) -> P::ScalarField
where
P: SWModelParameters,
R: RngCore + ?Sized,
{
P::ScalarField::rand(rng)
}

#[inline]
pub fn affine_affine_add_assign<P>(lhs: &mut GroupAffine<P>, rhs: &GroupAffine<P>)
where
P: SWModelParameters,
{
lhs.add_assign(rhs);
}

#[inline]
pub fn projective_affine_add_assign<P>(lhs: &mut GroupProjective<P>, rhs: &GroupAffine<P>)
where
P: SWModelParameters,
{
lhs.add_assign_mixed(rhs);
}

#[inline]
pub fn projective_projective_add_assign<P>(lhs: &mut GroupProjective<P>, rhs: &GroupProjective<P>)
where
P: SWModelParameters,
{
lhs.add_assign(rhs);
}

#[inline]
pub fn affine_scalar_mul<P>(point: &GroupAffine<P>, scalar: P::ScalarField) -> GroupProjective<P>
where
P: SWModelParameters,
{
point.mul(scalar)
}

#[inline]
pub fn projective_scalar_mul_assign<P>(point: &mut GroupProjective<P>, scalar: P::ScalarField)
where
P: SWModelParameters,
{
point.mul_assign(scalar);
}

#[inline]
pub fn projective_to_affine_normalization<P>(point: &P) -> P::Affine
where
P: ProjectiveCurve,
{
point.into_affine()
}

#[inline]
pub fn batch_vector_projective_to_affine_normalization<P>(point_vec: &[P]) -> Vec<P::Affine>
where
P: ProjectiveCurve,
{
P::batch_normalization_into_affine(point_vec)
}

#[inline]
pub fn naive_vector_projective_to_affine_normalization<P>(point_vec: &[P]) -> Vec<P::Affine>
where
P: ProjectiveCurve,
{
point_vec.iter().map(P::into_affine).collect()
}

#[cfg(test)]
mod test {
use super::*;
use ark_bls12_381::{g1::Parameters, G1Affine};
use manta_crypto::rand::OsRng;

#[test]
fn addition_is_consistent_for_projective_and_affine_curve() {
let mut rng = OsRng;
let mut lhs_affine = sample_affine_point::<G1Affine, _>(&mut rng);
let mut lhs_projective = lhs_affine.into_projective();
let mut lhs_projective_clone = lhs_projective;
let rhs_affine = sample_affine_point::<G1Affine, _>(&mut rng);
let rhs_projective = rhs_affine.into_projective();
affine_affine_add_assign(&mut lhs_affine, &rhs_affine);
projective_affine_add_assign(&mut lhs_projective, &rhs_affine);
projective_projective_add_assign(&mut lhs_projective_clone, &rhs_projective);
assert!(
BoyuanFeng marked this conversation as resolved.
Show resolved Hide resolved
lhs_affine == lhs_projective,
"add_assign is not equivalent to add_assign_mixed and into_affine"
);
assert!(
lhs_affine == lhs_projective_clone,
"add_assign is not equivalent to add_assign_mixed and into_affine"
);
}

#[test]
fn multiplication_is_consistent_for_projective_and_affine_curve() {
let mut rng = OsRng;
let lhs_affine = sample_affine_point::<G1Affine, _>(&mut rng);
let mut lhs_projective = lhs_affine.into_projective();
let scalar = sample_scalar::<Parameters, _>(&mut rng);
let out_projective = affine_scalar_mul(&lhs_affine, scalar);
projective_scalar_mul_assign(&mut lhs_projective, scalar);
assert!(
out_projective == lhs_projective,
"Multiplication is not consistent between projective curve and affine curve."
);
}
}
2 changes: 2 additions & 0 deletions manta-benchmark/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ use manta_pay::{
};
use wasm_bindgen::prelude::wasm_bindgen;

pub mod ec;

#[wasm_bindgen]
#[derive(Clone, Debug)]
pub struct Context {
Expand Down