mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-01-30 07:22:15 +00:00
group: Rewrite wNAF to remove dependency on ff::PrimeFieldRepr
Adapted from Scalar::non_adjacent_form in curve25519-dalek.
This commit is contained in:
parent
6e53cf3c4c
commit
69c60530d4
@ -2,7 +2,7 @@ use rand_core::RngCore;
|
||||
use std::ops::{AddAssign, MulAssign};
|
||||
use std::sync::Arc;
|
||||
|
||||
use ff::{Field, PrimeField};
|
||||
use ff::Field;
|
||||
use group::{CurveAffine, CurveProjective, Wnaf};
|
||||
use pairing::Engine;
|
||||
|
||||
@ -273,7 +273,7 @@ where
|
||||
exp.mul_assign(&coeff);
|
||||
|
||||
// Exponentiate
|
||||
*h = g1_wnaf.scalar(exp.into_repr());
|
||||
*h = g1_wnaf.scalar(&exp);
|
||||
}
|
||||
|
||||
// Batch normalize
|
||||
@ -376,14 +376,14 @@ where
|
||||
|
||||
// Compute A query (in G1)
|
||||
if !at.is_zero() {
|
||||
*a = g1_wnaf.scalar(at.into_repr());
|
||||
*a = g1_wnaf.scalar(&at);
|
||||
}
|
||||
|
||||
// Compute B query (in G1/G2)
|
||||
if !bt.is_zero() {
|
||||
let bt_repr = bt.into_repr();
|
||||
*b_g1 = g1_wnaf.scalar(bt_repr);
|
||||
*b_g2 = g2_wnaf.scalar(bt_repr);
|
||||
();
|
||||
*b_g1 = g1_wnaf.scalar(&bt);
|
||||
*b_g2 = g2_wnaf.scalar(&bt);
|
||||
}
|
||||
|
||||
at.mul_assign(&beta);
|
||||
@ -394,7 +394,7 @@ where
|
||||
e.add_assign(&ct);
|
||||
e.mul_assign(inv);
|
||||
|
||||
*ext = g1_wnaf.scalar(e.into_repr());
|
||||
*ext = g1_wnaf.scalar(&e);
|
||||
}
|
||||
|
||||
// Batch normalize
|
||||
|
@ -15,6 +15,7 @@ repository = "https://github.com/ebfull/group"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
byteorder = { version = "1", default-features = false }
|
||||
ff = { version = "0.6", path = "../ff" }
|
||||
rand = "0.7"
|
||||
rand_xorshift = "0.2"
|
||||
|
@ -85,12 +85,12 @@ fn random_wnaf_tests<G: CurveProjective>() {
|
||||
for w in 2..14 {
|
||||
for _ in 0..100 {
|
||||
let g = G::random(&mut rng);
|
||||
let s = G::Scalar::random(&mut rng).into_repr();
|
||||
let s = G::Scalar::random(&mut rng);
|
||||
let mut g1 = g;
|
||||
g1.mul_assign(s);
|
||||
|
||||
wnaf_table(&mut table, g, w);
|
||||
wnaf_form(&mut wnaf, s, w);
|
||||
wnaf_form(&mut wnaf, s.into_repr(), w);
|
||||
let g2 = wnaf_exp(&table, &wnaf);
|
||||
|
||||
assert_eq!(g1, g2);
|
||||
@ -103,17 +103,17 @@ fn random_wnaf_tests<G: CurveProjective>() {
|
||||
|
||||
for _ in 0..100 {
|
||||
let g = G::random(&mut rng);
|
||||
let s = G::Scalar::random(&mut rng).into_repr();
|
||||
let s = G::Scalar::random(&mut rng);
|
||||
let mut g1 = g;
|
||||
g1.mul_assign(s);
|
||||
|
||||
let g2 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
wnaf.base(g, 1).scalar(s)
|
||||
wnaf.base(g, 1).scalar(&s)
|
||||
};
|
||||
let g3 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
wnaf.scalar(s).base(g)
|
||||
wnaf.scalar(&s).base(g)
|
||||
};
|
||||
let g4 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
@ -121,11 +121,11 @@ fn random_wnaf_tests<G: CurveProjective>() {
|
||||
|
||||
only_compiles_if_send(&shared);
|
||||
|
||||
shared.scalar(s)
|
||||
shared.scalar(&s)
|
||||
};
|
||||
let g5 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
let mut shared = wnaf.scalar(s).shared();
|
||||
let mut shared = wnaf.scalar(&s).shared();
|
||||
|
||||
only_compiles_if_send(&shared);
|
||||
|
||||
@ -137,40 +137,40 @@ fn random_wnaf_tests<G: CurveProjective>() {
|
||||
{
|
||||
// Populate the vectors.
|
||||
wnaf.base(G::random(&mut rng), 1)
|
||||
.scalar(G::Scalar::random(&mut rng).into_repr());
|
||||
.scalar(&G::Scalar::random(&mut rng));
|
||||
}
|
||||
wnaf.base(g, 1).scalar(s)
|
||||
wnaf.base(g, 1).scalar(&s)
|
||||
};
|
||||
let g7 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
{
|
||||
// Populate the vectors.
|
||||
wnaf.base(G::random(&mut rng), 1)
|
||||
.scalar(G::Scalar::random(&mut rng).into_repr());
|
||||
.scalar(&G::Scalar::random(&mut rng));
|
||||
}
|
||||
wnaf.scalar(s).base(g)
|
||||
wnaf.scalar(&s).base(g)
|
||||
};
|
||||
let g8 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
{
|
||||
// Populate the vectors.
|
||||
wnaf.base(G::random(&mut rng), 1)
|
||||
.scalar(G::Scalar::random(&mut rng).into_repr());
|
||||
.scalar(&G::Scalar::random(&mut rng));
|
||||
}
|
||||
let mut shared = wnaf.base(g, 1).shared();
|
||||
|
||||
only_compiles_if_send(&shared);
|
||||
|
||||
shared.scalar(s)
|
||||
shared.scalar(&s)
|
||||
};
|
||||
let g9 = {
|
||||
let mut wnaf = Wnaf::new();
|
||||
{
|
||||
// Populate the vectors.
|
||||
wnaf.base(G::random(&mut rng), 1)
|
||||
.scalar(G::Scalar::random(&mut rng).into_repr());
|
||||
.scalar(&G::Scalar::random(&mut rng));
|
||||
}
|
||||
let mut shared = wnaf.scalar(s).shared();
|
||||
let mut shared = wnaf.scalar(&s).shared();
|
||||
|
||||
only_compiles_if_send(&shared);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use ff::{PrimeField, PrimeFieldRepr};
|
||||
use ff::PrimeField;
|
||||
use std::iter;
|
||||
|
||||
use super::CurveProjective;
|
||||
|
||||
@ -16,31 +17,60 @@ pub(crate) fn wnaf_table<G: CurveProjective>(table: &mut Vec<G>, mut base: G, wi
|
||||
}
|
||||
}
|
||||
|
||||
/// Replaces the contents of `wnaf` with the w-NAF representation of a scalar.
|
||||
pub(crate) fn wnaf_form<S: PrimeFieldRepr>(wnaf: &mut Vec<i64>, mut c: S, window: usize) {
|
||||
/// Replaces the contents of `wnaf` with the w-NAF representation of a little-endian
|
||||
/// scalar.
|
||||
pub(crate) fn wnaf_form<S: AsRef<[u64]>>(wnaf: &mut Vec<i64>, c: S, window: usize) {
|
||||
// Required by the NAF definition
|
||||
debug_assert!(window >= 2);
|
||||
// Required so that the NAF digits fit in i64
|
||||
debug_assert!(window <= 64);
|
||||
|
||||
wnaf.truncate(0);
|
||||
|
||||
while !c.is_zero() {
|
||||
let mut u;
|
||||
if c.is_odd() {
|
||||
u = (c.as_ref()[0] % (1 << (window + 1))) as i64;
|
||||
let u64_len = c.as_ref().len();
|
||||
let bit_len = u64_len * 64;
|
||||
|
||||
if u > (1 << window) {
|
||||
u -= 1 << (window + 1);
|
||||
}
|
||||
let mut c_u64 = vec![0u64; u64_len + 1];
|
||||
c_u64[0..u64_len].copy_from_slice(c.as_ref());
|
||||
|
||||
if u > 0 {
|
||||
c.sub_noborrow(&S::from(u as u64));
|
||||
} else {
|
||||
c.add_nocarry(&S::from((-u) as u64));
|
||||
}
|
||||
let width = 1u64 << window;
|
||||
let window_mask = width - 1;
|
||||
|
||||
let mut pos = 0;
|
||||
let mut carry = 0;
|
||||
while pos < bit_len {
|
||||
// Construct a buffer of bits of the scalar, starting at bit `pos`
|
||||
let u64_idx = pos / 64;
|
||||
let bit_idx = pos % 64;
|
||||
let bit_buf = if bit_idx + window < 64 {
|
||||
// This window's bits are contained in a single u64
|
||||
c_u64[u64_idx] >> bit_idx
|
||||
} else {
|
||||
u = 0;
|
||||
// Combine the current u64's bits with the bits from the next u64
|
||||
(c_u64[u64_idx] >> bit_idx) | (c_u64[u64_idx + 1] << (64 - bit_idx))
|
||||
};
|
||||
|
||||
// Add the carry into the current window
|
||||
let window_val = carry + (bit_buf & window_mask);
|
||||
|
||||
if window_val & 1 == 0 {
|
||||
// If the window value is even, preserve the carry and emit 0.
|
||||
// Why is the carry preserved?
|
||||
// If carry == 0 and window_val & 1 == 0, then the next carry should be 0
|
||||
// If carry == 1 and window_val & 1 == 0, then bit_buf & 1 == 1 so the next carry should be 1
|
||||
wnaf.push(0);
|
||||
pos += 1;
|
||||
} else {
|
||||
wnaf.push(if window_val < width / 2 {
|
||||
carry = 0;
|
||||
window_val as i64
|
||||
} else {
|
||||
carry = 1;
|
||||
(window_val as i64).wrapping_sub(width as i64)
|
||||
});
|
||||
wnaf.extend(iter::repeat(0).take(window - 1));
|
||||
pos += window;
|
||||
}
|
||||
|
||||
wnaf.push(u);
|
||||
|
||||
c.div2();
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,8 +142,10 @@ impl<G: CurveProjective> Wnaf<(), Vec<G>, Vec<i64>> {
|
||||
/// exponentiations with `.base(..)`.
|
||||
pub fn scalar(
|
||||
&mut self,
|
||||
scalar: <<G as CurveProjective>::Scalar as PrimeField>::Repr,
|
||||
scalar: &<G as CurveProjective>::Scalar,
|
||||
) -> Wnaf<usize, &mut Vec<G>, &[i64]> {
|
||||
let scalar = scalar.into_repr();
|
||||
|
||||
// Compute the appropriate window size for the scalar.
|
||||
let window_size = G::recommended_wnaf_for_scalar(&scalar);
|
||||
|
||||
@ -168,14 +200,11 @@ impl<B, S: AsRef<[i64]>> Wnaf<usize, B, S> {
|
||||
|
||||
impl<B, S: AsMut<Vec<i64>>> Wnaf<usize, B, S> {
|
||||
/// Performs exponentiation given a scalar.
|
||||
pub fn scalar<G: CurveProjective>(
|
||||
&mut self,
|
||||
scalar: <<G as CurveProjective>::Scalar as PrimeField>::Repr,
|
||||
) -> G
|
||||
pub fn scalar<G: CurveProjective>(&mut self, scalar: &<G as CurveProjective>::Scalar) -> G
|
||||
where
|
||||
B: AsRef<[G]>,
|
||||
{
|
||||
wnaf_form(self.scalar.as_mut(), scalar, self.window_size);
|
||||
wnaf_form(self.scalar.as_mut(), scalar.into_repr(), self.window_size);
|
||||
wnaf_exp(self.base.as_ref(), self.scalar.as_mut())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user