Files
librustzcash/src/curves/wnaf.rs
2017-06-17 17:04:14 -06:00

111 lines
2.8 KiB
Rust

use std::marker::PhantomData;
use super::{Engine, Curve, PrimeField};
/// Represents the scratch space for a wNAF form scalar.
pub struct WNAFTable {
window: usize,
wnaf: Vec<i64>
}
impl WNAFTable {
pub fn new() -> WNAFTable {
WNAFTable {
window: 0,
wnaf: vec![]
}
}
/// Convert the scalar into wNAF form.
pub fn set_scalar<E: Engine, G: Curve<E>>(&mut self, table: &WindowTable<E, G>, mut c: <E::Fr as PrimeField<E>>::Repr) {
self.window = table.window;
self.wnaf.truncate(0);
while !E::Fr::repr_is_zero(&c) {
let mut u;
if E::Fr::repr_is_odd(&c) {
u = (E::Fr::repr_least_significant_limb(&c) % (1 << (self.window+1))) as i64;
if u > (1 << self.window) {
u -= 1 << (self.window+1);
}
if u > 0 {
E::Fr::repr_sub_noborrow(&mut c, &E::Fr::repr_from_u64(u as u64));
} else {
E::Fr::repr_add_nocarry(&mut c, &E::Fr::repr_from_u64((-u) as u64));
}
} else {
u = 0;
}
self.wnaf.push(u);
E::Fr::repr_div2(&mut c);
}
}
}
/// Represents a window table for a base curve point.
pub struct WindowTable<E: Engine, G: Curve<E>>{
window: usize,
table: Vec<G>,
_marker: PhantomData<E>
}
impl<E: Engine, G: Curve<E>> WindowTable<E, G> {
/// Construct a new window table for a given base.
pub fn new(e: &E, base: G, window: usize) -> Self {
let mut tmp = WindowTable {
window: 0,
table: vec![],
_marker: PhantomData
};
tmp.set_base(e, base, window);
tmp
}
/// Replace this window table with a new one generated by a different base.
pub fn set_base(&mut self, e: &E, mut base: G, window: usize) {
assert!(window < 23);
assert!(window > 1);
self.window = window;
self.table.truncate(0);
self.table.reserve(1 << (window-1));
let mut dbl = base;
dbl.double(e);
for _ in 0..(1 << (window-1)) {
self.table.push(base);
base.add_assign(e, &dbl);
}
}
pub fn exp(&self, e: &E, wnaf: &WNAFTable) -> G {
assert_eq!(wnaf.window, self.window);
let mut result = G::zero(e);
for n in wnaf.wnaf.iter().rev() {
result.double(e);
if *n != 0 {
if *n > 0 {
result.add_assign(e, &self.table[(n/2) as usize]);
} else {
result.sub_assign(e, &self.table[((-n)/2) as usize]);
}
}
}
result
}
pub fn current_window(&self) -> usize {
self.window
}
}