group: Make Wnaf generic over Group
Wnaf was originally generic over CurveProjective; in the prior refactor commit, we renamed this to CofactorCurve. But w-NAF only requires scalar multiplication, which is provided by the Group trait, so we relax the bounds on Wnaf to enable it to be used with any group. We move the generic w-NAF helper methods from the Curve trait to a new WnafGroup extension trait, to keep the w-NAF API surface self-contained, and not expose it to users who aren't using it.
This commit is contained in:
parent
a105ad675a
commit
ad96a38750
|
@ -3,7 +3,7 @@ use std::ops::{AddAssign, MulAssign};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use ff::{Field, PrimeField};
|
use ff::{Field, PrimeField};
|
||||||
use group::{cofactor::CofactorCurveAffine, Curve, Group, Wnaf};
|
use group::{cofactor::CofactorCurveAffine, Curve, Group, Wnaf, WnafGroup};
|
||||||
use pairing::Engine;
|
use pairing::Engine;
|
||||||
|
|
||||||
use super::{Parameters, VerifyingKey};
|
use super::{Parameters, VerifyingKey};
|
||||||
|
@ -22,6 +22,8 @@ pub fn generate_random_parameters<E, C, R>(
|
||||||
) -> Result<Parameters<E>, SynthesisError>
|
) -> Result<Parameters<E>, SynthesisError>
|
||||||
where
|
where
|
||||||
E: Engine,
|
E: Engine,
|
||||||
|
E::G1: WnafGroup,
|
||||||
|
E::G2: WnafGroup,
|
||||||
C: Circuit<E::Fr>,
|
C: Circuit<E::Fr>,
|
||||||
R: RngCore,
|
R: RngCore,
|
||||||
{
|
{
|
||||||
|
@ -165,6 +167,8 @@ pub fn generate_parameters<E, C>(
|
||||||
) -> Result<Parameters<E>, SynthesisError>
|
) -> Result<Parameters<E>, SynthesisError>
|
||||||
where
|
where
|
||||||
E: Engine,
|
E: Engine,
|
||||||
|
E::G1: WnafGroup,
|
||||||
|
E::G2: WnafGroup,
|
||||||
C: Circuit<E::Fr>,
|
C: Circuit<E::Fr>,
|
||||||
{
|
{
|
||||||
let mut assembly = KeypairAssembly {
|
let mut assembly = KeypairAssembly {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use ff::{Field, PrimeField};
|
||||||
use group::{
|
use group::{
|
||||||
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
|
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
|
||||||
prime::PrimeGroup,
|
prime::PrimeGroup,
|
||||||
Curve, Group, GroupEncoding, UncompressedEncoding,
|
Curve, Group, GroupEncoding, UncompressedEncoding, WnafGroup,
|
||||||
};
|
};
|
||||||
use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
|
use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
|
||||||
|
|
||||||
|
@ -414,7 +414,9 @@ impl Curve for Fr {
|
||||||
fn to_affine(&self) -> Fr {
|
fn to_affine(&self) -> Fr {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WnafGroup for Fr {
|
||||||
fn recommended_wnaf_for_scalar(_: &Self::Scalar) -> usize {
|
fn recommended_wnaf_for_scalar(_: &Self::Scalar) -> usize {
|
||||||
3
|
3
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub mod prime;
|
||||||
pub mod tests;
|
pub mod tests;
|
||||||
|
|
||||||
mod wnaf;
|
mod wnaf;
|
||||||
pub use self::wnaf::Wnaf;
|
pub use self::wnaf::{Wnaf, WnafGroup};
|
||||||
|
|
||||||
/// A helper trait for types with a group operation.
|
/// A helper trait for types with a group operation.
|
||||||
pub trait GroupOps<Rhs = Self, Output = Self>:
|
pub trait GroupOps<Rhs = Self, Output = Self>:
|
||||||
|
@ -98,14 +98,6 @@ pub trait Curve:
|
||||||
|
|
||||||
/// Converts this element into its affine representation.
|
/// Converts this element into its affine representation.
|
||||||
fn to_affine(&self) -> Self::AffineRepr;
|
fn to_affine(&self) -> Self::AffineRepr;
|
||||||
|
|
||||||
/// Recommends a wNAF window table size given a scalar. Always returns a number
|
|
||||||
/// between 2 and 22, inclusive.
|
|
||||||
fn recommended_wnaf_for_scalar(scalar: &Self::Scalar) -> usize;
|
|
||||||
|
|
||||||
/// Recommends a wNAF window size given the number of scalars you intend to multiply
|
|
||||||
/// a base by. Always returns a number between 2 and 22, inclusive.
|
|
||||||
fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GroupEncoding: Sized {
|
pub trait GroupEncoding: Sized {
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::ops::{Mul, Neg};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cofactor::{CofactorCurve, CofactorCurveAffine},
|
cofactor::{CofactorCurve, CofactorCurveAffine},
|
||||||
|
wnaf::WnafGroup,
|
||||||
GroupEncoding, UncompressedEncoding,
|
GroupEncoding, UncompressedEncoding,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -64,11 +65,10 @@ pub fn curve_tests<G: CofactorCurve>() {
|
||||||
random_doubling_tests::<G>();
|
random_doubling_tests::<G>();
|
||||||
random_negation_tests::<G>();
|
random_negation_tests::<G>();
|
||||||
random_transformation_tests::<G>();
|
random_transformation_tests::<G>();
|
||||||
random_wnaf_tests::<G>();
|
|
||||||
random_compressed_encoding_tests::<G>();
|
random_compressed_encoding_tests::<G>();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_wnaf_tests<G: CofactorCurve>() {
|
pub fn random_wnaf_tests<G: WnafGroup>() {
|
||||||
use crate::wnaf::*;
|
use crate::wnaf::*;
|
||||||
|
|
||||||
let mut rng = XorShiftRng::from_seed([
|
let mut rng = XorShiftRng::from_seed([
|
||||||
|
|
|
@ -2,10 +2,21 @@ use byteorder::{ByteOrder, LittleEndian};
|
||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use super::{cofactor::CofactorCurve, Group};
|
use super::Group;
|
||||||
|
|
||||||
|
/// Extension trait on a [`Group`] that provides helpers used by [`Wnaf`].
|
||||||
|
pub trait WnafGroup: Group {
|
||||||
|
/// Recommends a wNAF window table size given a scalar. Always returns a number
|
||||||
|
/// between 2 and 22, inclusive.
|
||||||
|
fn recommended_wnaf_for_scalar(scalar: &Self::Scalar) -> usize;
|
||||||
|
|
||||||
|
/// Recommends a wNAF window size given the number of scalars you intend to multiply
|
||||||
|
/// a base by. Always returns a number between 2 and 22, inclusive.
|
||||||
|
fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
/// Replaces the contents of `table` with a w-NAF window table for the given window size.
|
/// Replaces the contents of `table` with a w-NAF window table for the given window size.
|
||||||
pub(crate) fn wnaf_table<G: CofactorCurve>(table: &mut Vec<G>, mut base: G, window: usize) {
|
pub(crate) fn wnaf_table<G: Group>(table: &mut Vec<G>, mut base: G, window: usize) {
|
||||||
table.truncate(0);
|
table.truncate(0);
|
||||||
table.reserve(1 << (window - 1));
|
table.reserve(1 << (window - 1));
|
||||||
|
|
||||||
|
@ -78,7 +89,7 @@ pub(crate) fn wnaf_form<S: AsRef<[u8]>>(wnaf: &mut Vec<i64>, c: S, window: usize
|
||||||
///
|
///
|
||||||
/// This function must be provided a `table` and `wnaf` that were constructed with
|
/// This function must be provided a `table` and `wnaf` that were constructed with
|
||||||
/// the same window size; otherwise, it may panic or produce invalid results.
|
/// the same window size; otherwise, it may panic or produce invalid results.
|
||||||
pub(crate) fn wnaf_exp<G: CofactorCurve>(table: &[G], wnaf: &[i64]) -> G {
|
pub(crate) fn wnaf_exp<G: Group>(table: &[G], wnaf: &[i64]) -> G {
|
||||||
let mut result = G::identity();
|
let mut result = G::identity();
|
||||||
|
|
||||||
let mut found_one = false;
|
let mut found_one = false;
|
||||||
|
@ -110,7 +121,7 @@ pub struct Wnaf<W, B, S> {
|
||||||
window_size: W,
|
window_size: W,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: CofactorCurve> Wnaf<(), Vec<G>, Vec<i64>> {
|
impl<G: Group> Wnaf<(), Vec<G>, Vec<i64>> {
|
||||||
/// Construct a new wNAF context without allocating.
|
/// Construct a new wNAF context without allocating.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Wnaf {
|
Wnaf {
|
||||||
|
@ -119,7 +130,9 @@ impl<G: CofactorCurve> Wnaf<(), Vec<G>, Vec<i64>> {
|
||||||
window_size: (),
|
window_size: (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
/// Given a base and a number of scalars, compute a window table and return a `Wnaf` object that
|
||||||
/// can perform exponentiations with `.scalar(..)`.
|
/// can perform exponentiations with `.scalar(..)`.
|
||||||
pub fn base(&mut self, base: G, num_scalars: usize) -> Wnaf<usize, &[G], &mut Vec<i64>> {
|
pub fn base(&mut self, base: G, num_scalars: usize) -> Wnaf<usize, &[G], &mut Vec<i64>> {
|
||||||
|
@ -157,7 +170,7 @@ impl<G: CofactorCurve> Wnaf<(), Vec<G>, Vec<i64>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, G: CofactorCurve> Wnaf<usize, &'a [G], &'a mut Vec<i64>> {
|
impl<'a, G: Group> Wnaf<usize, &'a [G], &'a mut Vec<i64>> {
|
||||||
/// Constructs new space for the scalar representation while borrowing
|
/// Constructs new space for the scalar representation while borrowing
|
||||||
/// the computed window table, for sending the window table across threads.
|
/// the computed window table, for sending the window table across threads.
|
||||||
pub fn shared(&self) -> Wnaf<usize, &'a [G], Vec<i64>> {
|
pub fn shared(&self) -> Wnaf<usize, &'a [G], Vec<i64>> {
|
||||||
|
@ -169,7 +182,7 @@ impl<'a, G: CofactorCurve> Wnaf<usize, &'a [G], &'a mut Vec<i64>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, G: CofactorCurve> Wnaf<usize, &'a mut Vec<G>, &'a [i64]> {
|
impl<'a, G: Group> Wnaf<usize, &'a mut Vec<G>, &'a [i64]> {
|
||||||
/// Constructs new space for the window table while borrowing
|
/// Constructs new space for the window table while borrowing
|
||||||
/// the computed scalar representation, for sending the scalar representation
|
/// the computed scalar representation, for sending the scalar representation
|
||||||
/// across threads.
|
/// across threads.
|
||||||
|
@ -184,7 +197,7 @@ impl<'a, G: CofactorCurve> Wnaf<usize, &'a mut Vec<G>, &'a [i64]> {
|
||||||
|
|
||||||
impl<B, S: AsRef<[i64]>> Wnaf<usize, B, S> {
|
impl<B, S: AsRef<[i64]>> Wnaf<usize, B, S> {
|
||||||
/// Performs exponentiation given a base.
|
/// Performs exponentiation given a base.
|
||||||
pub fn base<G: CofactorCurve>(&mut self, base: G) -> G
|
pub fn base<G: Group>(&mut self, base: G) -> G
|
||||||
where
|
where
|
||||||
B: AsMut<Vec<G>>,
|
B: AsMut<Vec<G>>,
|
||||||
{
|
{
|
||||||
|
@ -195,7 +208,7 @@ impl<B, S: AsRef<[i64]>> Wnaf<usize, B, S> {
|
||||||
|
|
||||||
impl<B, S: AsMut<Vec<i64>>> Wnaf<usize, B, S> {
|
impl<B, S: AsMut<Vec<i64>>> Wnaf<usize, B, S> {
|
||||||
/// Performs exponentiation given a scalar.
|
/// Performs exponentiation given a scalar.
|
||||||
pub fn scalar<G: CofactorCurve>(&mut self, scalar: &<G as Group>::Scalar) -> G
|
pub fn scalar<G: Group>(&mut self, scalar: &<G as Group>::Scalar) -> G
|
||||||
where
|
where
|
||||||
B: AsRef<[G]>,
|
B: AsRef<[G]>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -1092,7 +1092,9 @@ macro_rules! curve_impl {
|
||||||
fn to_affine(&self) -> $affine {
|
fn to_affine(&self) -> $affine {
|
||||||
(*self).into()
|
(*self).into()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WnafGroup for $projective {
|
||||||
fn recommended_wnaf_for_scalar(_: &Self::Scalar) -> usize {
|
fn recommended_wnaf_for_scalar(_: &Self::Scalar) -> usize {
|
||||||
Self::empirical_recommended_wnaf_for_scalar(
|
Self::empirical_recommended_wnaf_for_scalar(
|
||||||
<Self::Scalar as PrimeField>::NUM_BITS as usize,
|
<Self::Scalar as PrimeField>::NUM_BITS as usize,
|
||||||
|
@ -1210,7 +1212,7 @@ pub mod g1 {
|
||||||
use group::{
|
use group::{
|
||||||
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
|
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
|
||||||
prime::PrimeGroup,
|
prime::PrimeGroup,
|
||||||
Curve, Group, GroupEncoding, UncompressedEncoding,
|
Curve, Group, GroupEncoding, UncompressedEncoding, WnafGroup,
|
||||||
};
|
};
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -1778,8 +1780,9 @@ pub mod g1 {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn g1_curve_tests() {
|
fn g1_curve_tests() {
|
||||||
use group::tests::{curve_tests, random_uncompressed_encoding_tests};
|
use group::tests::{curve_tests, random_uncompressed_encoding_tests, random_wnaf_tests};
|
||||||
curve_tests::<G1>();
|
curve_tests::<G1>();
|
||||||
|
random_wnaf_tests::<G1>();
|
||||||
random_uncompressed_encoding_tests::<G1>();
|
random_uncompressed_encoding_tests::<G1>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1792,7 +1795,7 @@ pub mod g2 {
|
||||||
use group::{
|
use group::{
|
||||||
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
|
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
|
||||||
prime::PrimeGroup,
|
prime::PrimeGroup,
|
||||||
Curve, Group, GroupEncoding, UncompressedEncoding,
|
Curve, Group, GroupEncoding, UncompressedEncoding, WnafGroup,
|
||||||
};
|
};
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -2484,8 +2487,9 @@ pub mod g2 {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn g2_curve_tests() {
|
fn g2_curve_tests() {
|
||||||
use group::tests::{curve_tests, random_uncompressed_encoding_tests};
|
use group::tests::{curve_tests, random_uncompressed_encoding_tests, random_wnaf_tests};
|
||||||
curve_tests::<G2>();
|
curve_tests::<G2>();
|
||||||
|
random_wnaf_tests::<G2>();
|
||||||
random_uncompressed_encoding_tests::<G2>();
|
random_uncompressed_encoding_tests::<G2>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue