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

Adding wNAF multiplication functionality #230

Merged
merged 24 commits into from
Mar 25, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The main features of this release are:
- Big speedups to radix-2 FFTs
- Fix in the assembly arithmetic backend
- Adding new traits for basic curve cycles and pairing based curve cycles
- Providing wNAF scalar multiplcation functionality

### Breaking changes
- #20 (ark-poly) Move univariate DensePolynomial and SparsePolynomial into a
Expand Down
2 changes: 2 additions & 0 deletions ec/src/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use ark_ff::{
UniformRand,
};

pub mod wnaf;

pub trait Group:
ToBytes
+ 'static
Expand Down
39 changes: 39 additions & 0 deletions ec/src/group/wnaf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
extern crate alloc;
use crate::Group;
use alloc::vec::Vec;

pub fn wnaf_mul<G: Group>(table: &[G], scalar_wnaf: &[i64]) -> G {
ValarDragon marked this conversation as resolved.
Show resolved Hide resolved
let mut result = G::zero();

let mut found_one = false;

for n in scalar_wnaf.iter().rev() {
if found_one {
result = result.double();
}

if *n != 0 {
found_one = true;

if *n > 0 {
result += &table[(n / 2) as usize];
} else {
result -= &table[((-n) / 2) as usize];
}
}
}

result
}

pub fn wnaf_table<G: Group>(table: &mut Vec<G>, mut base: G, window: usize) {
ValarDragon marked this conversation as resolved.
Show resolved Hide resolved
table.truncate(0);
table.reserve(1 << (window - 1));

let dbl = base.double();

for _ in 0..(1 << (window - 1)) {
Pratyush marked this conversation as resolved.
Show resolved Hide resolved
table.push(base);
base.add_assign(&dbl);
}
}
14 changes: 14 additions & 0 deletions test-templates/src/groups.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#![allow(unused)]
use ark_ec::group::wnaf::{wnaf_mul, wnaf_table};
use ark_ec::group::Group;
use ark_ff::fields::PrimeField;
use ark_ff::BigInteger;
use ark_ff::{One, UniformRand, Zero};

pub fn group_test<G: Group>(a: G, mut b: G) {
Expand All @@ -8,6 +11,7 @@ pub fn group_test<G: Group>(a: G, mut b: G) {
let fr_zero = G::ScalarField::zero();
let fr_one = G::ScalarField::one();
let fr_two = fr_one + &fr_one;

assert_eq!(zero, zero);
assert_eq!(zero.is_zero(), true);
assert_eq!(a.mul(&fr_one), a);
Expand Down Expand Up @@ -70,4 +74,14 @@ pub fn group_test<G: Group>(a: G, mut b: G) {
a.mul(&(fr_rand1 * &fr_rand2)),
"(a * r1) * r2 != a * (r1 * r2)"
);

// Check that mul and wnaf_mul give the same results for several window values
for w in 2..=22 {
ValarDragon marked this conversation as resolved.
Show resolved Hide resolved
let scalar = G::ScalarField::rand(&mut rng);
let scalar_bigint: <G::ScalarField as PrimeField>::BigInt = scalar.into();
let scalar_wnaf = scalar_bigint.find_wnaf();
let mut wnaf_lut: Vec<G> = vec![];
wnaf_table(&mut wnaf_lut, a, w);
assert_eq!(a.mul(&scalar), wnaf_mul(&wnaf_lut, &scalar_wnaf));
}
}