Skip to content

Commit

Permalink
Merge pull request #37 from zkcrypto/wnaf-memuse
Browse files Browse the repository at this point in the history
Add `memuse::DynamicUsage` impls for w-NAF structs
  • Loading branch information
str4d authored Sep 26, 2022
2 parents a7f3ceb + f61e3e4 commit 36141c3
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ and this library adheres to Rust's notion of
- `group::{WnafBase, WnafScalar}` structs for caching precomputations of both
bases and scalars, for improved many-base many-scalar multiplication
performance.
- `impl memuse::DynamicUsage for group::{Wnaf WnafBase, WnafScalar}`, behind the
new `wnaf-memuse` feature flag, to enable the heap usage of these types to be
measured at runtime.

## [0.12.0] - 2022-05-04
### Changed
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ rand_core = { version = "0.6", default-features = false }
rand_xorshift = { version = "0.3", optional = true }
subtle = { version = "2.2.1", default-features = false }

# Crate for exposing the dynamic memory usage of the w-NAF structs.
memuse = { version = "0.2", optional = true }

[features]
default = ["alloc"]
alloc = []
tests = ["alloc", "rand", "rand_xorshift"]
wnaf-memuse = ["alloc", "memuse"]

[badges]
maintenance = { status = "actively-developed" }
65 changes: 65 additions & 0 deletions src/wnaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,23 @@ impl<G: Group> Wnaf<(), Vec<G>, Vec<i64>> {
}
}

#[cfg(feature = "wnaf-memuse")]
impl<G: Group + memuse::DynamicUsage> memuse::DynamicUsage for Wnaf<(), Vec<G>, Vec<i64>> {
fn dynamic_usage(&self) -> usize {
self.base.dynamic_usage() + self.scalar.dynamic_usage()
}

fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
let (base_lower, base_upper) = self.base.dynamic_usage_bounds();
let (scalar_lower, scalar_upper) = self.scalar.dynamic_usage_bounds();

(
base_lower + scalar_lower,
base_upper.zip(scalar_upper).map(|(a, b)| a + b),
)
}
}

impl<G: WnafGroup> Wnaf<(), Vec<G>, Vec<i64>> {
/// Given a base and a number of scalars, compute a window table and return a `Wnaf` object that
/// can perform exponentiations with `.scalar(..)`.
Expand Down Expand Up @@ -316,6 +333,18 @@ impl<'a, G: Group> Wnaf<usize, &'a [G], &'a mut Vec<i64>> {
}
}

#[cfg(feature = "wnaf-memuse")]
impl<'a, G: Group> memuse::DynamicUsage for Wnaf<usize, &'a [G], Vec<i64>> {
fn dynamic_usage(&self) -> usize {
// The heap memory for the window table is counted in the parent `Wnaf`.
self.scalar.dynamic_usage()
}

fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
self.scalar.dynamic_usage_bounds()
}
}

impl<'a, G: Group> Wnaf<usize, &'a mut Vec<G>, &'a [i64]> {
/// Constructs new space for the window table while borrowing
/// the computed scalar representation, for sending the scalar representation
Expand All @@ -329,6 +358,18 @@ impl<'a, G: Group> Wnaf<usize, &'a mut Vec<G>, &'a [i64]> {
}
}

#[cfg(feature = "wnaf-memuse")]
impl<'a, G: Group + memuse::DynamicUsage> memuse::DynamicUsage for Wnaf<usize, Vec<G>, &'a [i64]> {
fn dynamic_usage(&self) -> usize {
// The heap memory for the scalar representation is counted in the parent `Wnaf`.
self.base.dynamic_usage()
}

fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
self.base.dynamic_usage_bounds()
}
}

impl<B, S: AsRef<[i64]>> Wnaf<usize, B, S> {
/// Performs exponentiation given a base.
pub fn base<G: Group>(&mut self, base: G) -> G
Expand Down Expand Up @@ -363,6 +404,17 @@ pub struct WnafScalar<F: PrimeField, const WINDOW_SIZE: usize> {
field: PhantomData<F>,
}

#[cfg(feature = "wnaf-memuse")]
impl<F: PrimeField, const WINDOW_SIZE: usize> memuse::DynamicUsage for WnafScalar<F, WINDOW_SIZE> {
fn dynamic_usage(&self) -> usize {
self.wnaf.dynamic_usage()
}

fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
self.wnaf.dynamic_usage_bounds()
}
}

impl<F: PrimeField, const WINDOW_SIZE: usize> WnafScalar<F, WINDOW_SIZE> {
/// Computes the w-NAF representation of the given scalar with the specified
/// `WINDOW_SIZE`.
Expand Down Expand Up @@ -418,6 +470,19 @@ pub struct WnafBase<G: Group, const WINDOW_SIZE: usize> {
table: Vec<G>,
}

#[cfg(feature = "wnaf-memuse")]
impl<G: Group + memuse::DynamicUsage, const WINDOW_SIZE: usize> memuse::DynamicUsage
for WnafBase<G, WINDOW_SIZE>
{
fn dynamic_usage(&self) -> usize {
self.table.dynamic_usage()
}

fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
self.table.dynamic_usage_bounds()
}
}

impl<G: Group, const WINDOW_SIZE: usize> WnafBase<G, WINDOW_SIZE> {
/// Computes a window table for the given base with the specified `WINDOW_SIZE`.
pub fn new(base: G) -> Self {
Expand Down

0 comments on commit 36141c3

Please sign in to comment.