group: Add mixed-addition scalar multiplication bounds to CurveAffine

Replaces the explicit CurveAffine::mul trait method.
This commit is contained in:
Jack Grigg 2020-05-15 17:49:45 +12:00
parent 0941dddc13
commit b0a3713d7e
9 changed files with 48 additions and 38 deletions

View File

@ -463,12 +463,12 @@ where
let g2 = g2.into_affine();
let vk = VerifyingKey::<E> {
alpha_g1: g1.mul(alpha).into_affine(),
beta_g1: g1.mul(beta).into_affine(),
beta_g2: g2.mul(beta).into_affine(),
gamma_g2: g2.mul(gamma).into_affine(),
delta_g1: g1.mul(delta).into_affine(),
delta_g2: g2.mul(delta).into_affine(),
alpha_g1: (g1 * &alpha).into_affine(),
beta_g1: (g1 * &beta).into_affine(),
beta_g2: (g2 * &beta).into_affine(),
gamma_g2: (g2 * &gamma).into_affine(),
delta_g1: (g1 * &delta).into_affine(),
delta_g2: (g2 * &delta).into_affine(),
ic,
};

View File

@ -301,18 +301,18 @@ where
return Err(SynthesisError::UnexpectedIdentity);
}
let mut g_a = vk.delta_g1.mul(r);
let mut g_a = vk.delta_g1 * &r;
AddAssign::<&E::G1Affine>::add_assign(&mut g_a, &vk.alpha_g1);
let mut g_b = vk.delta_g2.mul(s);
let mut g_b = vk.delta_g2 * &s;
AddAssign::<&E::G2Affine>::add_assign(&mut g_b, &vk.beta_g2);
let mut g_c;
{
let mut rs = r;
rs.mul_assign(&s);
g_c = vk.delta_g1.mul(rs);
AddAssign::<&E::G1>::add_assign(&mut g_c, &vk.alpha_g1.mul(s));
AddAssign::<&E::G1>::add_assign(&mut g_c, &vk.beta_g1.mul(r));
g_c = vk.delta_g1 * &rs;
AddAssign::<&E::G1>::add_assign(&mut g_c, &(vk.alpha_g1 * &s));
AddAssign::<&E::G1>::add_assign(&mut g_c, &(vk.beta_g1 * &r));
}
let mut a_answer = a_inputs.wait()?;
AddAssign::<&E::G1>::add_assign(&mut a_answer, &a_aux.wait()?);

View File

@ -475,15 +475,6 @@ impl CurveAffine for Fr {
Choice::from(if <Fr as Field>::is_zero(self) { 1 } else { 0 })
}
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective {
let mut res = *self;
let tmp = Fr::from_repr(other.into()).unwrap();
MulAssign::mul_assign(&mut res, &tmp);
res
}
fn into_projective(&self) -> Self::Projective {
*self
}

View File

@ -1,4 +1,3 @@
use ff::PrimeField;
use group::{CurveAffine, CurveProjective};
use pairing::{Engine, PairingCurveAffine};
use std::ops::{AddAssign, Neg};
@ -31,7 +30,7 @@ pub fn verify_proof<'a, E: Engine>(
let mut acc = pvk.ic[0].into_projective();
for (i, b) in public_inputs.iter().zip(pvk.ic.iter().skip(1)) {
AddAssign::<&E::G1>::add_assign(&mut acc, &b.mul(i.to_repr()));
AddAssign::<&E::G1>::add_assign(&mut acc, &(*b * i));
}
// The original verification equation is:

View File

@ -308,7 +308,7 @@ fn test_with_bls12() {
let mut acc = G::identity();
for (base, exp) in bases.iter().zip(exponents.iter()) {
AddAssign::<&G>::add_assign(&mut acc, &base.mul(exp.to_repr()));
AddAssign::<&G>::add_assign(&mut acc, &(*base * *exp));
}
acc

View File

@ -99,7 +99,9 @@ pub trait CurveProjective:
+ GroupOpsOwned<<Self as CurveProjective>::Affine>
{
type Base: Field;
type Affine: CurveAffine<Projective = Self, Scalar = Self::Scalar>;
type Affine: CurveAffine<Projective = Self, Scalar = Self::Scalar>
+ Mul<Self::Scalar, Output = Self>
+ for<'r> Mul<Self::Scalar, Output = Self>;
/// Converts a batch of projective elements into affine elements. This function will
/// panic if `p.len() != q.len()`.
@ -131,6 +133,8 @@ pub trait CurveAffine:
+ Eq
+ 'static
+ Neg<Output = Self>
+ Mul<<Self as CurveAffine>::Scalar, Output = <Self as CurveAffine>::Projective>
+ for<'r> Mul<<Self as CurveAffine>::Scalar, Output = <Self as CurveAffine>::Projective>
{
type Scalar: PrimeField;
type Base: Field;
@ -148,9 +152,6 @@ pub trait CurveAffine:
/// additive identity.
fn is_identity(&self) -> Choice;
/// Performs scalar multiplication of this element with mixed addition.
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective;
/// Converts this element into its affine representation.
fn into_projective(&self) -> Self::Projective;

View File

@ -1,7 +1,7 @@
use ff::{Field, PrimeField};
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::Neg;
use std::ops::{Mul, Neg};
use crate::{CurveAffine, CurveProjective, EncodedPoint};
@ -273,8 +273,8 @@ fn random_multiplication_tests<G: CurveProjective>() {
tmp2.add_assign(&b);
// Affine multiplication
let mut tmp3 = a_affine.mul(s);
tmp3.add_assign(&b_affine.mul(s));
let mut tmp3 = Mul::<G::Scalar>::mul(a_affine, s);
tmp3.add_assign(Mul::<G::Scalar>::mul(b_affine, s));
assert_eq!(tmp1, tmp2);
assert_eq!(tmp1, tmp3);

View File

@ -141,7 +141,8 @@ macro_rules! curve_impl {
}
fn is_in_correct_subgroup_assuming_on_curve(&self) -> bool {
self.mul($scalarfield::char()).is_identity().into()
let bits = BitIterator::<u8, _>::new($scalarfield::char());
self.mul_bits_u8(bits).is_identity().into()
}
}
@ -158,6 +159,24 @@ macro_rules! curve_impl {
}
}
impl ::std::ops::Mul<$scalarfield> for $affine {
type Output = $projective;
fn mul(self, by: $scalarfield) -> $projective {
let bits = BitIterator::<u8, <$scalarfield as PrimeField>::Repr>::new(by.into());
self.mul_bits_u8(bits)
}
}
impl<'r> ::std::ops::Mul<&'r $scalarfield> for $affine {
type Output = $projective;
fn mul(self, by: &'r $scalarfield) -> $projective {
let bits = BitIterator::<u8, <$scalarfield as PrimeField>::Repr>::new(by.into());
self.mul_bits_u8(bits)
}
}
impl CurveAffine for $affine {
type Scalar = $scalarfield;
type Base = $basefield;
@ -181,11 +200,6 @@ macro_rules! curve_impl {
Choice::from(if self.infinity { 1 } else { 0 })
}
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, by: S) -> $projective {
let bits = BitIterator::<u8, _>::new(by.into());
self.mul_bits_u8(bits)
}
fn into_projective(&self) -> $projective {
(*self).into()
}

View File

@ -20,6 +20,7 @@ pub mod tests;
pub mod bls12_381;
use core::ops::Mul;
use ff::{Field, PrimeField, ScalarEngine};
use group::{CurveAffine, CurveProjective, GroupOps, GroupOpsOwned, ScalarMul, ScalarMulOwned};
use subtle::CtOption;
@ -43,7 +44,9 @@ pub trait Engine: ScalarEngine {
Projective = Self::G1,
Pair = Self::G2Affine,
PairingResult = Self::Fqk,
> + From<Self::G1>;
> + From<Self::G1>
+ Mul<Self::Fr, Output = Self::G1>
+ for<'a> Mul<&'a Self::Fr, Output = Self::G1>;
/// The projective representation of an element in G2.
type G2: CurveProjective<Base = Self::Fqe, Scalar = Self::Fr, Affine = Self::G2Affine>
@ -60,7 +63,9 @@ pub trait Engine: ScalarEngine {
Projective = Self::G2,
Pair = Self::G1Affine,
PairingResult = Self::Fqk,
> + From<Self::G2>;
> + From<Self::G2>
+ Mul<Self::Fr, Output = Self::G2>
+ for<'a> Mul<&'a Self::Fr, Output = Self::G2>;
/// The base field that hosts G1.
type Fq: PrimeField;