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 ff::{Field, PrimeField};
|
||||
use group::{cofactor::CofactorCurveAffine, Curve, Group, Wnaf};
|
||||
use group::{cofactor::CofactorCurveAffine, Curve, Group, Wnaf, WnafGroup};
|
||||
use pairing::Engine;
|
||||
|
||||
use super::{Parameters, VerifyingKey};
|
||||
|
@ -22,6 +22,8 @@ pub fn generate_random_parameters<E, C, R>(
|
|||
) -> Result<Parameters<E>, SynthesisError>
|
||||
where
|
||||
E: Engine,
|
||||
E::G1: WnafGroup,
|
||||
E::G2: WnafGroup,
|
||||
C: Circuit<E::Fr>,
|
||||
R: RngCore,
|
||||
{
|
||||
|
@ -165,6 +167,8 @@ pub fn generate_parameters<E, C>(
|
|||
) -> Result<Parameters<E>, SynthesisError>
|
||||
where
|
||||
E: Engine,
|
||||
E::G1: WnafGroup,
|
||||
E::G2: WnafGroup,
|
||||
C: Circuit<E::Fr>,
|
||||
{
|
||||
let mut assembly = KeypairAssembly {
|
||||
|
|
|
@ -2,7 +2,7 @@ use ff::{Field, PrimeField};
|
|||
use group::{
|
||||
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
|
||||
prime::PrimeGroup,
|
||||
Curve, Group, GroupEncoding, UncompressedEncoding,
|
||||
Curve, Group, GroupEncoding, UncompressedEncoding, WnafGroup,
|
||||
};
|
||||
use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
|
||||
|
||||
|
@ -414,7 +414,9 @@ impl Curve for Fr {
|
|||
fn to_affine(&self) -> Fr {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl WnafGroup for Fr {
|
||||
fn recommended_wnaf_for_scalar(_: &Self::Scalar) -> usize {
|
||||
3
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ pub mod prime;
|
|||
pub mod tests;
|
||||
|
||||
mod wnaf;
|
||||
pub use self::wnaf::Wnaf;
|
||||
pub use self::wnaf::{Wnaf, WnafGroup};
|
||||
|
||||
/// A helper trait for types with a group operation.
|
||||
pub trait GroupOps<Rhs = Self, Output = Self>:
|
||||
|
@ -98,14 +98,6 @@ pub trait Curve:
|
|||
|
||||
/// Converts this element into its affine representation.
|
||||
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 {
|
||||
|
|
|
@ -5,6 +5,7 @@ use std::ops::{Mul, Neg};
|
|||
|
||||
use crate::{
|
||||
cofactor::{CofactorCurve, CofactorCurveAffine},
|
||||
wnaf::WnafGroup,
|
||||
GroupEncoding, UncompressedEncoding,
|
||||
};
|
||||
|
||||
|
@ -64,11 +65,10 @@ pub fn curve_tests<G: CofactorCurve>() {
|
|||
random_doubling_tests::<G>();
|
||||
random_negation_tests::<G>();
|
||||
random_transformation_tests::<G>();
|
||||
random_wnaf_tests::<G>();
|
||||
random_compressed_encoding_tests::<G>();
|
||||
}
|
||||
|
||||
fn random_wnaf_tests<G: CofactorCurve>() {
|
||||
pub fn random_wnaf_tests<G: WnafGroup>() {
|
||||
use crate::wnaf::*;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
|
|
|
@ -2,10 +2,21 @@ use byteorder::{ByteOrder, LittleEndian};
|
|||
use ff::PrimeField;
|
||||
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.
|
||||
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.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
|
||||
/// 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 found_one = false;
|
||||
|
@ -110,7 +121,7 @@ pub struct Wnaf<W, B, S> {
|
|||
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.
|
||||
pub fn new() -> Self {
|
||||
Wnaf {
|
||||
|
@ -119,7 +130,9 @@ impl<G: CofactorCurve> Wnaf<(), Vec<G>, Vec<i64>> {
|
|||
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
|
||||
/// can perform exponentiations with `.scalar(..)`.
|
||||
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
|
||||
/// the computed window table, for sending the window table across threads.
|
||||
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
|
||||
/// the computed scalar representation, for sending the scalar representation
|
||||
/// 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> {
|
||||
/// 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
|
||||
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> {
|
||||
/// 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
|
||||
B: AsRef<[G]>,
|
||||
{
|
||||
|
|
|
@ -1092,7 +1092,9 @@ macro_rules! curve_impl {
|
|||
fn to_affine(&self) -> $affine {
|
||||
(*self).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl WnafGroup for $projective {
|
||||
fn recommended_wnaf_for_scalar(_: &Self::Scalar) -> usize {
|
||||
Self::empirical_recommended_wnaf_for_scalar(
|
||||
<Self::Scalar as PrimeField>::NUM_BITS as usize,
|
||||
|
@ -1210,7 +1212,7 @@ pub mod g1 {
|
|||
use group::{
|
||||
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
|
||||
prime::PrimeGroup,
|
||||
Curve, Group, GroupEncoding, UncompressedEncoding,
|
||||
Curve, Group, GroupEncoding, UncompressedEncoding, WnafGroup,
|
||||
};
|
||||
use rand_core::RngCore;
|
||||
use std::fmt;
|
||||
|
@ -1778,8 +1780,9 @@ pub mod g1 {
|
|||
|
||||
#[test]
|
||||
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>();
|
||||
random_wnaf_tests::<G1>();
|
||||
random_uncompressed_encoding_tests::<G1>();
|
||||
}
|
||||
}
|
||||
|
@ -1792,7 +1795,7 @@ pub mod g2 {
|
|||
use group::{
|
||||
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
|
||||
prime::PrimeGroup,
|
||||
Curve, Group, GroupEncoding, UncompressedEncoding,
|
||||
Curve, Group, GroupEncoding, UncompressedEncoding, WnafGroup,
|
||||
};
|
||||
use rand_core::RngCore;
|
||||
use std::fmt;
|
||||
|
@ -2484,8 +2487,9 @@ pub mod g2 {
|
|||
|
||||
#[test]
|
||||
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>();
|
||||
random_wnaf_tests::<G2>();
|
||||
random_uncompressed_encoding_tests::<G2>();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue