Files
librustzcash/src/curves/wnaf.rs
2017-06-17 18:57:56 -06:00

111 lines
2.8 KiB
Rust

use std::marker::PhantomData;
use super::{Engine, Curve, PrimeField, PrimeFieldRepr};
/// 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 !c.is_zero() {
let mut u;
if c.is_odd() {
u = (c.as_ref()[0] % (1 << (self.window+1))) as i64;
if u > (1 << self.window) {
u -= 1 << (self.window+1);
}
if u > 0 {
c.sub_noborrow(&<<E::Fr as PrimeField<E>>::Repr as PrimeFieldRepr>::from_u64(u as u64));
} else {
c.add_nocarry(&<<E::Fr as PrimeField<E>>::Repr as PrimeFieldRepr>::from_u64((-u) as u64));
}
} else {
u = 0;
}
self.wnaf.push(u);
c.div2();
}
}
}
/// 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
}
}