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

FixedBase refactor: rename msm -> mul, declutter the interface and hide aux methods #746

Merged
merged 13 commits into from
Jan 14, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- [\#577](https://github.com/arkworks-rs/algebra/pull/577) (`ark-ff`, `ark-ec`) Add `AdditiveGroup`, a trait for additive groups (equipped with scalar field).
- [\#593](https://github.com/arkworks-rs/algebra/pull/593) (`ark-ec`) Change `AffineRepr::xy()` to return owned values.
- [\#633](https://github.com/arkworks-rs/algebra/pull/633) (`ark-ec`) Generic pairing implementation for the curves from the BW6 family.
- [\#746](https://github.com/arkworks-rs/algebra/pull/746) (`ark-ec`) Refactor `FixedBase`: rename method `msm` → `mul`, remove its arguments `scalar_size`, `window` and change `table: &[Vec<T::MulBase>]` → `g: T`; make methods `windowed_mul` and `get_mul_window_size` private.

### Features

Expand Down
56 changes: 38 additions & 18 deletions ec/src/scalar_mul/fixed_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,16 @@ use super::ScalarMul;
pub struct FixedBase;

impl FixedBase {
pub fn get_mul_window_size(num_scalars: usize) -> usize {
fn get_mul_window_size(num_scalars: usize) -> usize {
if num_scalars < 32 {
3
} else {
super::ln_without_floats(num_scalars)
}
}

pub fn get_window_table<T: ScalarMul>(
scalar_size: usize,
window: usize,
g: T,
) -> Vec<Vec<T::MulBase>> {
pub fn get_window_table<T: ScalarMul>(window: usize, g: T) -> Vec<Vec<T::MulBase>> {
Pratyush marked this conversation as resolved.
Show resolved Hide resolved
let scalar_size = T::ScalarField::MODULUS_BIT_SIZE as usize;
let in_window = 1 << window;
let outerc = (scalar_size + window - 1) / window;
let last_in_window = 1 << (scalar_size - (outerc - 1) * window);
Expand Down Expand Up @@ -58,10 +55,10 @@ impl FixedBase {
.collect()
}

pub fn windowed_mul<T: ScalarMul>(
fn windowed_mul<T: ScalarMul>(
outerc: usize,
window: usize,
multiples_of_g: &[Vec<<T as ScalarMul>::MulBase>],
multiples_of_g: &[Vec<T::MulBase>],
scalar: &T::ScalarField,
) -> T {
let modulus_size = T::ScalarField::MODULUS_BIT_SIZE as usize;
Expand All @@ -80,19 +77,42 @@ impl FixedBase {
res
}

// TODO use const-generics for the scalar size and window
// TODO use iterators of iterators of T::Affine instead of taking owned Vec
pub fn msm<T: ScalarMul>(
scalar_size: usize,
window: usize,
table: &[Vec<<T as ScalarMul>::MulBase>],
v: &[T::ScalarField],
) -> Vec<T> {
let outerc = (scalar_size + window - 1) / window;
/// Compute the vector v[0].G, v[1].G, ..., v[n-1].G, given:
/// - an element `g`
/// - a list `v` of n scalars
///
/// # Example
/// ```
/// use ark_std::{One, UniformRand};
/// use ark_ec::pairing::Pairing;
/// use ark_test_curves::bls12_381::G1Projective as G;
/// use ark_test_curves::bls12_381::Fr;
/// use ark_ec::scalar_mul::fixed_base::FixedBase;
///
/// // Compute G, s.G, s^2.G, ..., s^9.G
/// let mut rng = ark_std::test_rng();
/// let max_degree = 10;
/// let s = Fr::rand(&mut rng);
/// let g = G::rand(&mut rng);
/// let mut powers_of_s = vec![Fr::one()];
/// let mut cur = s;
/// for _ in 0..max_degree {
/// powers_of_s.push(cur);
/// cur *= &s;
/// }
/// let powers_of_g: Vec<G> = FixedBase::mul(g, &powers_of_s);
/// let naive_powers_of_g: Vec<G> = powers_of_s.iter().map(|e| g * e).collect();
/// assert_eq!(powers_of_g, naive_powers_of_g);
/// ```
pub fn mul<T: ScalarMul>(g: T, v: &[T::ScalarField]) -> Vec<T> {
let window_size = Self::get_mul_window_size(v.len());
let table = Self::get_window_table::<T>(window_size, g.clone());
let scalar_size = T::ScalarField::MODULUS_BIT_SIZE as usize;
let outerc = (scalar_size + window_size - 1) / window_size;
assert!(outerc <= table.len());

cfg_iter!(v)
.map(|e| Self::windowed_mul::<T>(outerc, window, table, e))
.map(|e| Self::windowed_mul::<T>(outerc, window_size, &table, e))
.collect::<Vec<_>>()
}
}
Loading