mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-02-11 17:55:46 +00:00
Merge pull request #193 from str4d/group-std-ops
Move Group operations to operator-backed traits
This commit is contained in:
commit
702b5e5d8c
@ -314,34 +314,34 @@ where
|
||||
}
|
||||
|
||||
let mut g_a = vk.delta_g1.mul(r);
|
||||
g_a.add_assign_mixed(&vk.alpha_g1);
|
||||
AddAssign::<&E::G1Affine>::add_assign(&mut g_a, &vk.alpha_g1);
|
||||
let mut g_b = vk.delta_g2.mul(s);
|
||||
g_b.add_assign_mixed(&vk.beta_g2);
|
||||
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);
|
||||
g_c.add_assign(&vk.alpha_g1.mul(s));
|
||||
g_c.add_assign(&vk.beta_g1.mul(r));
|
||||
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));
|
||||
}
|
||||
let mut a_answer = a_inputs.wait()?;
|
||||
a_answer.add_assign(&a_aux.wait()?);
|
||||
g_a.add_assign(&a_answer);
|
||||
AddAssign::<&E::G1>::add_assign(&mut a_answer, &a_aux.wait()?);
|
||||
AddAssign::<&E::G1>::add_assign(&mut g_a, &a_answer);
|
||||
a_answer.mul_assign(s);
|
||||
g_c.add_assign(&a_answer);
|
||||
AddAssign::<&E::G1>::add_assign(&mut g_c, &a_answer);
|
||||
|
||||
let mut b1_answer = b_g1_inputs.wait()?;
|
||||
b1_answer.add_assign(&b_g1_aux.wait()?);
|
||||
let mut b1_answer: E::G1 = b_g1_inputs.wait()?;
|
||||
AddAssign::<&E::G1>::add_assign(&mut b1_answer, &b_g1_aux.wait()?);
|
||||
let mut b2_answer = b_g2_inputs.wait()?;
|
||||
b2_answer.add_assign(&b_g2_aux.wait()?);
|
||||
AddAssign::<&E::G2>::add_assign(&mut b2_answer, &b_g2_aux.wait()?);
|
||||
|
||||
g_b.add_assign(&b2_answer);
|
||||
AddAssign::<&E::G2>::add_assign(&mut g_b, &b2_answer);
|
||||
b1_answer.mul_assign(r);
|
||||
g_c.add_assign(&b1_answer);
|
||||
g_c.add_assign(&h.wait()?);
|
||||
g_c.add_assign(&l.wait()?);
|
||||
AddAssign::<&E::G1>::add_assign(&mut g_c, &b1_answer);
|
||||
AddAssign::<&E::G1>::add_assign(&mut g_c, &h.wait()?);
|
||||
AddAssign::<&E::G1>::add_assign(&mut g_c, &l.wait()?);
|
||||
|
||||
Ok(Proof {
|
||||
a: g_a.into_affine(),
|
||||
|
@ -413,18 +413,6 @@ impl CurveProjective for Fr {
|
||||
self.0 = <Fr as Field>::double(self).0;
|
||||
}
|
||||
|
||||
fn add_assign(&mut self, other: &Self) {
|
||||
AddAssign::add_assign(self, other);
|
||||
}
|
||||
|
||||
fn add_assign_mixed(&mut self, other: &Self) {
|
||||
AddAssign::add_assign(self, other);
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
self.0 = self.neg().0;
|
||||
}
|
||||
|
||||
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S) {
|
||||
let tmp = Fr::from_repr(other.into()).unwrap();
|
||||
|
||||
@ -503,10 +491,6 @@ impl CurveAffine for Fr {
|
||||
<Fr as Field>::is_zero(self)
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
self.0 = self.neg().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();
|
||||
|
@ -1,16 +1,15 @@
|
||||
use ff::PrimeField;
|
||||
use group::{CurveAffine, CurveProjective};
|
||||
use pairing::{Engine, PairingCurveAffine};
|
||||
use std::ops::{AddAssign, Neg};
|
||||
|
||||
use super::{PreparedVerifyingKey, Proof, VerifyingKey};
|
||||
|
||||
use crate::SynthesisError;
|
||||
|
||||
pub fn prepare_verifying_key<E: Engine>(vk: &VerifyingKey<E>) -> PreparedVerifyingKey<E> {
|
||||
let mut gamma = vk.gamma_g2;
|
||||
gamma.negate();
|
||||
let mut delta = vk.delta_g2;
|
||||
delta.negate();
|
||||
let gamma = vk.gamma_g2.neg();
|
||||
let delta = vk.delta_g2.neg();
|
||||
|
||||
PreparedVerifyingKey {
|
||||
alpha_g1_beta_g2: E::pairing(vk.alpha_g1, vk.beta_g2),
|
||||
@ -32,7 +31,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)) {
|
||||
acc.add_assign(&b.mul(i.into_repr()));
|
||||
AddAssign::<&E::G1>::add_assign(&mut acc, &b.mul(i.into_repr()));
|
||||
}
|
||||
|
||||
// The original verification equation is:
|
||||
|
@ -5,6 +5,7 @@ use futures::Future;
|
||||
use group::{CurveAffine, CurveProjective};
|
||||
use std::io;
|
||||
use std::iter;
|
||||
use std::ops::AddAssign;
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::SynthesisError;
|
||||
@ -18,16 +19,24 @@ pub trait SourceBuilder<G: CurveAffine>: Send + Sync + 'static + Clone {
|
||||
|
||||
/// A source of bases, like an iterator.
|
||||
pub trait Source<G: CurveAffine> {
|
||||
/// Parses the element from the source. Fails if the point is at infinity.
|
||||
fn add_assign_mixed(
|
||||
&mut self,
|
||||
to: &mut <G as CurveAffine>::Projective,
|
||||
) -> Result<(), SynthesisError>;
|
||||
fn next(&mut self) -> Result<&G, SynthesisError>;
|
||||
|
||||
/// Skips `amt` elements from the source, avoiding deserialization.
|
||||
fn skip(&mut self, amt: usize) -> Result<(), SynthesisError>;
|
||||
}
|
||||
|
||||
pub trait AddAssignFromSource: CurveProjective {
|
||||
/// Parses the element from the source. Fails if the point is at infinity.
|
||||
fn add_assign_from_source<S: Source<<Self as CurveProjective>::Affine>>(
|
||||
&mut self,
|
||||
source: &mut S,
|
||||
) -> Result<(), SynthesisError> {
|
||||
AddAssign::<&<Self as CurveProjective>::Affine>::add_assign(self, source.next()?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl<G> AddAssignFromSource for G where G: CurveProjective {}
|
||||
|
||||
impl<G: CurveAffine> SourceBuilder<G> for (Arc<Vec<G>>, usize) {
|
||||
type Source = (Arc<Vec<G>>, usize);
|
||||
|
||||
@ -37,10 +46,7 @@ impl<G: CurveAffine> SourceBuilder<G> for (Arc<Vec<G>>, usize) {
|
||||
}
|
||||
|
||||
impl<G: CurveAffine> Source<G> for (Arc<Vec<G>>, usize) {
|
||||
fn add_assign_mixed(
|
||||
&mut self,
|
||||
to: &mut <G as CurveAffine>::Projective,
|
||||
) -> Result<(), SynthesisError> {
|
||||
fn next(&mut self) -> Result<&G, SynthesisError> {
|
||||
if self.0.len() <= self.1 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::UnexpectedEof,
|
||||
@ -53,11 +59,10 @@ impl<G: CurveAffine> Source<G> for (Arc<Vec<G>>, usize) {
|
||||
return Err(SynthesisError::UnexpectedIdentity);
|
||||
}
|
||||
|
||||
to.add_assign_mixed(&self.0[self.1]);
|
||||
|
||||
let ret = &self.0[self.1];
|
||||
self.1 += 1;
|
||||
|
||||
Ok(())
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
fn skip(&mut self, amt: usize) -> Result<(), SynthesisError> {
|
||||
@ -153,12 +158,12 @@ fn multiexp_inner<Q, D, G, S>(
|
||||
mut skip: u32,
|
||||
c: u32,
|
||||
handle_trivial: bool,
|
||||
) -> Box<dyn Future<Item = <G as CurveAffine>::Projective, Error = SynthesisError>>
|
||||
) -> Box<dyn Future<Item = G, Error = SynthesisError>>
|
||||
where
|
||||
for<'a> &'a Q: QueryDensity,
|
||||
D: Send + Sync + 'static + Clone + AsRef<Q>,
|
||||
G: CurveAffine,
|
||||
S: SourceBuilder<G>,
|
||||
G: CurveProjective,
|
||||
S: SourceBuilder<<G as CurveProjective>::Affine>,
|
||||
{
|
||||
// Perform this region of the multiexp
|
||||
let this = {
|
||||
@ -168,13 +173,13 @@ where
|
||||
|
||||
pool.compute(move || {
|
||||
// Accumulate the result
|
||||
let mut acc = G::Projective::zero();
|
||||
let mut acc = G::zero();
|
||||
|
||||
// Build a source for the bases
|
||||
let mut bases = bases.new();
|
||||
|
||||
// Create space for the buckets
|
||||
let mut buckets = vec![<G as CurveAffine>::Projective::zero(); (1 << c) - 1];
|
||||
let mut buckets = vec![G::zero(); (1 << c) - 1];
|
||||
|
||||
let zero = <G::Engine as ScalarEngine>::Fr::zero().into_repr();
|
||||
let one = <G::Engine as ScalarEngine>::Fr::one().into_repr();
|
||||
@ -186,7 +191,7 @@ where
|
||||
bases.skip(1)?;
|
||||
} else if exp == one {
|
||||
if handle_trivial {
|
||||
bases.add_assign_mixed(&mut acc)?;
|
||||
acc.add_assign_from_source(&mut bases)?;
|
||||
} else {
|
||||
bases.skip(1)?;
|
||||
}
|
||||
@ -196,7 +201,8 @@ where
|
||||
let exp = exp.as_ref()[0] % (1 << c);
|
||||
|
||||
if exp != 0 {
|
||||
bases.add_assign_mixed(&mut buckets[(exp - 1) as usize])?;
|
||||
(&mut buckets[(exp - 1) as usize])
|
||||
.add_assign_from_source(&mut bases)?;
|
||||
} else {
|
||||
bases.skip(1)?;
|
||||
}
|
||||
@ -208,7 +214,7 @@ where
|
||||
// e.g. 3a + 2b + 1c = a +
|
||||
// (a) + b +
|
||||
// ((a) + b) + c
|
||||
let mut running_sum = G::Projective::zero();
|
||||
let mut running_sum = G::zero();
|
||||
for exp in buckets.into_iter().rev() {
|
||||
running_sum.add_assign(&exp);
|
||||
acc.add_assign(&running_sum);
|
||||
@ -236,7 +242,7 @@ where
|
||||
c,
|
||||
false,
|
||||
))
|
||||
.map(move |(this, mut higher)| {
|
||||
.map(move |(this, mut higher): (_, G)| {
|
||||
for _ in 0..c {
|
||||
higher.double();
|
||||
}
|
||||
@ -256,12 +262,12 @@ pub fn multiexp<Q, D, G, S>(
|
||||
bases: S,
|
||||
density_map: D,
|
||||
exponents: Arc<Vec<<<G::Engine as ScalarEngine>::Fr as PrimeField>::Repr>>,
|
||||
) -> Box<dyn Future<Item = <G as CurveAffine>::Projective, Error = SynthesisError>>
|
||||
) -> Box<dyn Future<Item = G, Error = SynthesisError>>
|
||||
where
|
||||
for<'a> &'a Q: QueryDensity,
|
||||
D: Send + Sync + 'static + Clone + AsRef<Q>,
|
||||
G: CurveAffine,
|
||||
S: SourceBuilder<G>,
|
||||
G: CurveProjective,
|
||||
S: SourceBuilder<<G as CurveProjective>::Affine>,
|
||||
{
|
||||
let c = if exponents.len() < 32 {
|
||||
3u32
|
||||
@ -282,16 +288,16 @@ where
|
||||
#[cfg(feature = "pairing")]
|
||||
#[test]
|
||||
fn test_with_bls12() {
|
||||
fn naive_multiexp<G: CurveAffine>(
|
||||
bases: Arc<Vec<G>>,
|
||||
fn naive_multiexp<G: CurveProjective>(
|
||||
bases: Arc<Vec<<G as CurveProjective>::Affine>>,
|
||||
exponents: Arc<Vec<<G::Scalar as PrimeField>::Repr>>,
|
||||
) -> G::Projective {
|
||||
) -> G {
|
||||
assert_eq!(bases.len(), exponents.len());
|
||||
|
||||
let mut acc = G::Projective::zero();
|
||||
let mut acc = G::zero();
|
||||
|
||||
for (base, exp) in bases.iter().zip(exponents.iter()) {
|
||||
acc.add_assign(&base.mul(*exp));
|
||||
AddAssign::<&G>::add_assign(&mut acc, &base.mul(*exp));
|
||||
}
|
||||
|
||||
acc
|
||||
@ -314,7 +320,7 @@ fn test_with_bls12() {
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let naive = naive_multiexp(g.clone(), v.clone());
|
||||
let naive: <Bls12 as Engine>::G1 = naive_multiexp(g.clone(), v.clone());
|
||||
|
||||
let pool = Worker::new();
|
||||
|
||||
|
@ -5,16 +5,46 @@ use ff::{PrimeField, PrimeFieldDecodingError, ScalarEngine, SqrtField};
|
||||
use rand::RngCore;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
|
||||
|
||||
pub mod tests;
|
||||
|
||||
mod wnaf;
|
||||
pub use self::wnaf::Wnaf;
|
||||
|
||||
/// A helper trait for types implementing group addition.
|
||||
pub trait CurveOps<Rhs = Self, Output = Self>:
|
||||
Add<Rhs, Output = Output> + Sub<Rhs, Output = Output> + AddAssign<Rhs> + SubAssign<Rhs>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, Rhs, Output> CurveOps<Rhs, Output> for T where
|
||||
T: Add<Rhs, Output = Output> + Sub<Rhs, Output = Output> + AddAssign<Rhs> + SubAssign<Rhs>
|
||||
{
|
||||
}
|
||||
|
||||
/// A helper trait for references implementing group addition.
|
||||
pub trait CurveOpsOwned<Rhs = Self, Output = Self>: for<'r> CurveOps<&'r Rhs, Output> {}
|
||||
impl<T, Rhs, Output> CurveOpsOwned<Rhs, Output> for T where T: for<'r> CurveOps<&'r Rhs, Output> {}
|
||||
|
||||
/// Projective representation of an elliptic curve point guaranteed to be
|
||||
/// in the correct prime order subgroup.
|
||||
pub trait CurveProjective:
|
||||
PartialEq + Eq + Sized + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static
|
||||
PartialEq
|
||||
+ Eq
|
||||
+ Sized
|
||||
+ Copy
|
||||
+ Clone
|
||||
+ Send
|
||||
+ Sync
|
||||
+ fmt::Debug
|
||||
+ fmt::Display
|
||||
+ 'static
|
||||
+ Neg<Output = Self>
|
||||
+ CurveOps
|
||||
+ CurveOpsOwned
|
||||
+ CurveOps<<Self as CurveProjective>::Affine>
|
||||
+ CurveOpsOwned<<Self as CurveProjective>::Affine>
|
||||
{
|
||||
type Engine: ScalarEngine<Fr = Self::Scalar>;
|
||||
type Scalar: PrimeField + SqrtField;
|
||||
@ -44,22 +74,6 @@ pub trait CurveProjective:
|
||||
/// Doubles this element.
|
||||
fn double(&mut self);
|
||||
|
||||
/// Adds another element to this element.
|
||||
fn add_assign(&mut self, other: &Self);
|
||||
|
||||
/// Subtracts another element from this element.
|
||||
fn sub_assign(&mut self, other: &Self) {
|
||||
let mut tmp = *other;
|
||||
tmp.negate();
|
||||
self.add_assign(&tmp);
|
||||
}
|
||||
|
||||
/// Adds an affine element to this element.
|
||||
fn add_assign_mixed(&mut self, other: &Self::Affine);
|
||||
|
||||
/// Negates this element.
|
||||
fn negate(&mut self);
|
||||
|
||||
/// Performs scalar multiplication of this element.
|
||||
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S);
|
||||
|
||||
@ -78,7 +92,17 @@ pub trait CurveProjective:
|
||||
/// Affine representation of an elliptic curve point guaranteed to be
|
||||
/// in the correct prime order subgroup.
|
||||
pub trait CurveAffine:
|
||||
Copy + Clone + Sized + Send + Sync + fmt::Debug + fmt::Display + PartialEq + Eq + 'static
|
||||
Copy
|
||||
+ Clone
|
||||
+ Sized
|
||||
+ Send
|
||||
+ Sync
|
||||
+ fmt::Debug
|
||||
+ fmt::Display
|
||||
+ PartialEq
|
||||
+ Eq
|
||||
+ 'static
|
||||
+ Neg<Output = Self>
|
||||
{
|
||||
type Engine: ScalarEngine<Fr = Self::Scalar>;
|
||||
type Scalar: PrimeField + SqrtField;
|
||||
@ -97,9 +121,6 @@ pub trait CurveAffine:
|
||||
/// additive identity.
|
||||
fn is_zero(&self) -> bool;
|
||||
|
||||
/// Negates this element.
|
||||
fn negate(&mut self);
|
||||
|
||||
/// Performs scalar multiplication of this element with mixed addition.
|
||||
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective;
|
||||
|
||||
|
@ -13,8 +13,7 @@ pub fn curve_tests<G: CurveProjective>() {
|
||||
|
||||
// Negation edge case with zero.
|
||||
{
|
||||
let mut z = G::zero();
|
||||
z.negate();
|
||||
let z = G::zero().neg();
|
||||
assert!(z.is_zero());
|
||||
}
|
||||
|
||||
@ -31,19 +30,19 @@ pub fn curve_tests<G: CurveProjective>() {
|
||||
let rcopy = r;
|
||||
r.add_assign(&G::zero());
|
||||
assert_eq!(r, rcopy);
|
||||
r.add_assign_mixed(&G::Affine::zero());
|
||||
r.add_assign(&G::Affine::zero());
|
||||
assert_eq!(r, rcopy);
|
||||
|
||||
let mut z = G::zero();
|
||||
z.add_assign(&G::zero());
|
||||
assert!(z.is_zero());
|
||||
z.add_assign_mixed(&G::Affine::zero());
|
||||
z.add_assign(&G::Affine::zero());
|
||||
assert!(z.is_zero());
|
||||
|
||||
let mut z2 = z;
|
||||
z2.add_assign(&r);
|
||||
|
||||
z.add_assign_mixed(&r.into_affine());
|
||||
z.add_assign(&r.into_affine());
|
||||
|
||||
assert_eq!(z, z2);
|
||||
assert_eq!(z, r);
|
||||
@ -68,7 +67,7 @@ pub fn curve_tests<G: CurveProjective>() {
|
||||
random_negation_tests::<G>();
|
||||
random_transformation_tests::<G>();
|
||||
random_wnaf_tests::<G>();
|
||||
random_encoding_tests::<G::Affine>();
|
||||
random_encoding_tests::<G>();
|
||||
}
|
||||
|
||||
fn random_wnaf_tests<G: CurveProjective>() {
|
||||
@ -213,11 +212,10 @@ fn random_negation_tests<G: CurveProjective>() {
|
||||
assert!(t3.is_zero());
|
||||
|
||||
let mut t4 = t1;
|
||||
t4.add_assign_mixed(&t2.into_affine());
|
||||
t4.add_assign(&t2.into_affine());
|
||||
assert!(t4.is_zero());
|
||||
|
||||
t1.negate();
|
||||
assert_eq!(t1, t2);
|
||||
assert_eq!(t1.neg(), t2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,7 +242,7 @@ fn random_doubling_tests<G: CurveProjective>() {
|
||||
tmp2.add_assign(&b);
|
||||
|
||||
let mut tmp3 = a;
|
||||
tmp3.add_assign_mixed(&b.into_affine());
|
||||
tmp3.add_assign(&b.into_affine());
|
||||
|
||||
assert_eq!(tmp1, tmp2);
|
||||
assert_eq!(tmp1, tmp3);
|
||||
@ -306,7 +304,7 @@ fn random_addition_tests<G: CurveProjective>() {
|
||||
aplusa.add_assign(&a);
|
||||
|
||||
let mut aplusamixed = a;
|
||||
aplusamixed.add_assign_mixed(&a.into_affine());
|
||||
aplusamixed.add_assign(&a.into_affine());
|
||||
|
||||
let mut adouble = a;
|
||||
adouble.double();
|
||||
@ -336,18 +334,18 @@ fn random_addition_tests<G: CurveProjective>() {
|
||||
|
||||
// (a + b) + c
|
||||
tmp[3] = a_affine.into_projective();
|
||||
tmp[3].add_assign_mixed(&b_affine);
|
||||
tmp[3].add_assign_mixed(&c_affine);
|
||||
tmp[3].add_assign(&b_affine);
|
||||
tmp[3].add_assign(&c_affine);
|
||||
|
||||
// a + (b + c)
|
||||
tmp[4] = b_affine.into_projective();
|
||||
tmp[4].add_assign_mixed(&c_affine);
|
||||
tmp[4].add_assign_mixed(&a_affine);
|
||||
tmp[4].add_assign(&c_affine);
|
||||
tmp[4].add_assign(&a_affine);
|
||||
|
||||
// (a + c) + b
|
||||
tmp[5] = a_affine.into_projective();
|
||||
tmp[5].add_assign_mixed(&c_affine);
|
||||
tmp[5].add_assign_mixed(&b_affine);
|
||||
tmp[5].add_assign(&c_affine);
|
||||
tmp[5].add_assign(&b_affine);
|
||||
|
||||
// Comparisons
|
||||
for i in 0..6 {
|
||||
@ -413,24 +411,24 @@ fn random_transformation_tests<G: CurveProjective>() {
|
||||
}
|
||||
}
|
||||
|
||||
fn random_encoding_tests<G: CurveAffine>() {
|
||||
fn random_encoding_tests<G: CurveProjective>() {
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
0xe5,
|
||||
]);
|
||||
|
||||
assert_eq!(
|
||||
G::zero().into_uncompressed().into_affine().unwrap(),
|
||||
G::zero()
|
||||
G::Affine::zero().into_uncompressed().into_affine().unwrap(),
|
||||
G::Affine::zero()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
G::zero().into_compressed().into_affine().unwrap(),
|
||||
G::zero()
|
||||
G::Affine::zero().into_compressed().into_affine().unwrap(),
|
||||
G::Affine::zero()
|
||||
);
|
||||
|
||||
for _ in 0..1000 {
|
||||
let mut r = G::Projective::random(&mut rng).into_affine();
|
||||
let mut r = G::random(&mut rng).into_affine();
|
||||
|
||||
let uncompressed = r.into_uncompressed();
|
||||
let de_uncompressed = uncompressed.into_affine().unwrap();
|
||||
@ -440,7 +438,7 @@ fn random_encoding_tests<G: CurveAffine>() {
|
||||
let de_compressed = compressed.into_affine().unwrap();
|
||||
assert_eq!(de_compressed, r);
|
||||
|
||||
r.negate();
|
||||
r = r.neg();
|
||||
|
||||
let compressed = r.into_compressed();
|
||||
let de_compressed = compressed.into_affine().unwrap();
|
||||
|
@ -2,6 +2,7 @@ pub(crate) mod g1 {
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::AddAssign;
|
||||
|
||||
use ff::Field;
|
||||
use group::CurveProjective;
|
||||
@ -69,7 +70,7 @@ pub(crate) mod g1 {
|
||||
c.bench_function("G1::add_assign_mixed", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign_mixed(&v[count].1);
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
@ -88,6 +89,7 @@ pub(crate) mod g2 {
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::AddAssign;
|
||||
|
||||
use ff::Field;
|
||||
use group::CurveProjective;
|
||||
@ -155,7 +157,7 @@ pub(crate) mod g2 {
|
||||
c.bench_function("G2::add_assign_mixed", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign_mixed(&v[count].1);
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
|
@ -86,7 +86,7 @@ macro_rules! curve_impl {
|
||||
for i in bits {
|
||||
res.double();
|
||||
if i {
|
||||
res.add_assign_mixed(self)
|
||||
res.add_assign(self)
|
||||
}
|
||||
}
|
||||
res
|
||||
@ -134,6 +134,19 @@ macro_rules! curve_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Neg for $affine {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Self {
|
||||
let mut ret = self;
|
||||
if !ret.is_zero() {
|
||||
ret.y = ret.y.neg();
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl CurveAffine for $affine {
|
||||
type Engine = Bls12;
|
||||
type Scalar = $scalarfield;
|
||||
@ -163,12 +176,6 @@ macro_rules! curve_impl {
|
||||
self.mul_bits(bits)
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
if !self.is_zero() {
|
||||
self.y = self.y.neg();
|
||||
}
|
||||
}
|
||||
|
||||
fn into_projective(&self) -> $projective {
|
||||
(*self).into()
|
||||
}
|
||||
@ -188,6 +195,309 @@ macro_rules! curve_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Neg for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Self {
|
||||
let mut ret = self;
|
||||
if !ret.is_zero() {
|
||||
ret.y = ret.y.neg();
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::Add<&'r $projective> for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
ret.add_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Add for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: Self) -> Self {
|
||||
self + &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::AddAssign<&'r $projective> for $projective {
|
||||
fn add_assign(&mut self, other: &Self) {
|
||||
if self.is_zero() {
|
||||
*self = *other;
|
||||
return;
|
||||
}
|
||||
|
||||
if other.is_zero() {
|
||||
return;
|
||||
}
|
||||
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
||||
|
||||
// Z1Z1 = Z1^2
|
||||
let z1z1 = self.z.square();
|
||||
|
||||
// Z2Z2 = Z2^2
|
||||
let z2z2 = other.z.square();
|
||||
|
||||
// U1 = X1*Z2Z2
|
||||
let mut u1 = self.x;
|
||||
u1.mul_assign(&z2z2);
|
||||
|
||||
// U2 = X2*Z1Z1
|
||||
let mut u2 = other.x;
|
||||
u2.mul_assign(&z1z1);
|
||||
|
||||
// S1 = Y1*Z2*Z2Z2
|
||||
let mut s1 = self.y;
|
||||
s1.mul_assign(&other.z);
|
||||
s1.mul_assign(&z2z2);
|
||||
|
||||
// S2 = Y2*Z1*Z1Z1
|
||||
let mut s2 = other.y;
|
||||
s2.mul_assign(&self.z);
|
||||
s2.mul_assign(&z1z1);
|
||||
|
||||
if u1 == u2 && s1 == s2 {
|
||||
// The two points are equal, so we double.
|
||||
self.double();
|
||||
} else {
|
||||
// If we're adding -a and a together, self.z becomes zero as H becomes zero.
|
||||
|
||||
// H = U2-U1
|
||||
let mut h = u2;
|
||||
h.sub_assign(&u1);
|
||||
|
||||
// I = (2*H)^2
|
||||
let i = h.double().square();
|
||||
|
||||
// J = H*I
|
||||
let mut j = h;
|
||||
j.mul_assign(&i);
|
||||
|
||||
// r = 2*(S2-S1)
|
||||
let mut r = s2;
|
||||
r.sub_assign(&s1);
|
||||
r = r.double();
|
||||
|
||||
// V = U1*I
|
||||
let mut v = u1;
|
||||
v.mul_assign(&i);
|
||||
|
||||
// X3 = r^2 - J - 2*V
|
||||
self.x = r.square();
|
||||
self.x.sub_assign(&j);
|
||||
self.x.sub_assign(&v);
|
||||
self.x.sub_assign(&v);
|
||||
|
||||
// Y3 = r*(V - X3) - 2*S1*J
|
||||
self.y = v;
|
||||
self.y.sub_assign(&self.x);
|
||||
self.y.mul_assign(&r);
|
||||
s1.mul_assign(&j); // S1 = S1 * J * 2
|
||||
s1 = s1.double();
|
||||
self.y.sub_assign(&s1);
|
||||
|
||||
// Z3 = ((Z1+Z2)^2 - Z1Z1 - Z2Z2)*H
|
||||
self.z.add_assign(&other.z);
|
||||
self.z = self.z.square();
|
||||
self.z.sub_assign(&z1z1);
|
||||
self.z.sub_assign(&z2z2);
|
||||
self.z.mul_assign(&h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::AddAssign for $projective {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
self.add_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::Sub<&'r $projective> for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
ret.sub_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Sub for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self - &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::SubAssign<&'r $projective> for $projective {
|
||||
fn sub_assign(&mut self, other: &Self) {
|
||||
self.add_assign(&other.neg());
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::SubAssign for $projective {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
self.sub_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::Add<&'r <$projective as CurveProjective>::Affine> for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: &<$projective as CurveProjective>::Affine) -> Self {
|
||||
let mut ret = self;
|
||||
ret.add_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Add<<$projective as CurveProjective>::Affine> for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: <$projective as CurveProjective>::Affine) -> Self {
|
||||
self + &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::AddAssign<&'r <$projective as CurveProjective>::Affine>
|
||||
for $projective
|
||||
{
|
||||
fn add_assign(&mut self, other: &<$projective as CurveProjective>::Affine) {
|
||||
if other.is_zero() {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.is_zero() {
|
||||
self.x = other.x;
|
||||
self.y = other.y;
|
||||
self.z = $basefield::one();
|
||||
return;
|
||||
}
|
||||
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
|
||||
|
||||
// Z1Z1 = Z1^2
|
||||
let z1z1 = self.z.square();
|
||||
|
||||
// U2 = X2*Z1Z1
|
||||
let mut u2 = other.x;
|
||||
u2.mul_assign(&z1z1);
|
||||
|
||||
// S2 = Y2*Z1*Z1Z1
|
||||
let mut s2 = other.y;
|
||||
s2.mul_assign(&self.z);
|
||||
s2.mul_assign(&z1z1);
|
||||
|
||||
if self.x == u2 && self.y == s2 {
|
||||
// The two points are equal, so we double.
|
||||
self.double();
|
||||
} else {
|
||||
// If we're adding -a and a together, self.z becomes zero as H becomes zero.
|
||||
|
||||
// H = U2-X1
|
||||
let mut h = u2;
|
||||
h.sub_assign(&self.x);
|
||||
|
||||
// HH = H^2
|
||||
let hh = h.square();
|
||||
|
||||
// I = 4*HH
|
||||
let i = hh.double().double();
|
||||
|
||||
// J = H*I
|
||||
let mut j = h;
|
||||
j.mul_assign(&i);
|
||||
|
||||
// r = 2*(S2-Y1)
|
||||
let mut r = s2;
|
||||
r.sub_assign(&self.y);
|
||||
r = r.double();
|
||||
|
||||
// V = X1*I
|
||||
let mut v = self.x;
|
||||
v.mul_assign(&i);
|
||||
|
||||
// X3 = r^2 - J - 2*V
|
||||
self.x = r.square();
|
||||
self.x.sub_assign(&j);
|
||||
self.x.sub_assign(&v);
|
||||
self.x.sub_assign(&v);
|
||||
|
||||
// Y3 = r*(V-X3)-2*Y1*J
|
||||
j.mul_assign(&self.y); // J = 2*Y1*J
|
||||
j = j.double();
|
||||
self.y = v;
|
||||
self.y.sub_assign(&self.x);
|
||||
self.y.mul_assign(&r);
|
||||
self.y.sub_assign(&j);
|
||||
|
||||
// Z3 = (Z1+H)^2-Z1Z1-HH
|
||||
self.z.add_assign(&h);
|
||||
self.z = self.z.square();
|
||||
self.z.sub_assign(&z1z1);
|
||||
self.z.sub_assign(&hh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::AddAssign<<$projective as CurveProjective>::Affine> for $projective {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: <$projective as CurveProjective>::Affine) {
|
||||
self.add_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::Sub<&'r <$projective as CurveProjective>::Affine> for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, other: &<$projective as CurveProjective>::Affine) -> Self {
|
||||
let mut ret = self;
|
||||
ret.sub_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Sub<<$projective as CurveProjective>::Affine> for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, other: <$projective as CurveProjective>::Affine) -> Self {
|
||||
self - &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::SubAssign<&'r <$projective as CurveProjective>::Affine>
|
||||
for $projective
|
||||
{
|
||||
fn sub_assign(&mut self, other: &<$projective as CurveProjective>::Affine) {
|
||||
self.add_assign(&other.neg());
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::SubAssign<<$projective as CurveProjective>::Affine> for $projective {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, other: <$projective as CurveProjective>::Affine) {
|
||||
self.sub_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl CurveProjective for $projective {
|
||||
type Engine = Bls12;
|
||||
type Scalar = $scalarfield;
|
||||
@ -340,174 +650,6 @@ macro_rules! curve_impl {
|
||||
self.y.sub_assign(&c);
|
||||
}
|
||||
|
||||
fn add_assign(&mut self, other: &Self) {
|
||||
if self.is_zero() {
|
||||
*self = *other;
|
||||
return;
|
||||
}
|
||||
|
||||
if other.is_zero() {
|
||||
return;
|
||||
}
|
||||
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
||||
|
||||
// Z1Z1 = Z1^2
|
||||
let z1z1 = self.z.square();
|
||||
|
||||
// Z2Z2 = Z2^2
|
||||
let z2z2 = other.z.square();
|
||||
|
||||
// U1 = X1*Z2Z2
|
||||
let mut u1 = self.x;
|
||||
u1.mul_assign(&z2z2);
|
||||
|
||||
// U2 = X2*Z1Z1
|
||||
let mut u2 = other.x;
|
||||
u2.mul_assign(&z1z1);
|
||||
|
||||
// S1 = Y1*Z2*Z2Z2
|
||||
let mut s1 = self.y;
|
||||
s1.mul_assign(&other.z);
|
||||
s1.mul_assign(&z2z2);
|
||||
|
||||
// S2 = Y2*Z1*Z1Z1
|
||||
let mut s2 = other.y;
|
||||
s2.mul_assign(&self.z);
|
||||
s2.mul_assign(&z1z1);
|
||||
|
||||
if u1 == u2 && s1 == s2 {
|
||||
// The two points are equal, so we double.
|
||||
self.double();
|
||||
} else {
|
||||
// If we're adding -a and a together, self.z becomes zero as H becomes zero.
|
||||
|
||||
// H = U2-U1
|
||||
let mut h = u2;
|
||||
h.sub_assign(&u1);
|
||||
|
||||
// I = (2*H)^2
|
||||
let i = h.double().square();
|
||||
|
||||
// J = H*I
|
||||
let mut j = h;
|
||||
j.mul_assign(&i);
|
||||
|
||||
// r = 2*(S2-S1)
|
||||
let mut r = s2;
|
||||
r.sub_assign(&s1);
|
||||
r = r.double();
|
||||
|
||||
// V = U1*I
|
||||
let mut v = u1;
|
||||
v.mul_assign(&i);
|
||||
|
||||
// X3 = r^2 - J - 2*V
|
||||
self.x = r.square();
|
||||
self.x.sub_assign(&j);
|
||||
self.x.sub_assign(&v);
|
||||
self.x.sub_assign(&v);
|
||||
|
||||
// Y3 = r*(V - X3) - 2*S1*J
|
||||
self.y = v;
|
||||
self.y.sub_assign(&self.x);
|
||||
self.y.mul_assign(&r);
|
||||
s1.mul_assign(&j); // S1 = S1 * J * 2
|
||||
s1 = s1.double();
|
||||
self.y.sub_assign(&s1);
|
||||
|
||||
// Z3 = ((Z1+Z2)^2 - Z1Z1 - Z2Z2)*H
|
||||
self.z.add_assign(&other.z);
|
||||
self.z = self.z.square();
|
||||
self.z.sub_assign(&z1z1);
|
||||
self.z.sub_assign(&z2z2);
|
||||
self.z.mul_assign(&h);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_assign_mixed(&mut self, other: &Self::Affine) {
|
||||
if other.is_zero() {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.is_zero() {
|
||||
self.x = other.x;
|
||||
self.y = other.y;
|
||||
self.z = $basefield::one();
|
||||
return;
|
||||
}
|
||||
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
|
||||
|
||||
// Z1Z1 = Z1^2
|
||||
let z1z1 = self.z.square();
|
||||
|
||||
// U2 = X2*Z1Z1
|
||||
let mut u2 = other.x;
|
||||
u2.mul_assign(&z1z1);
|
||||
|
||||
// S2 = Y2*Z1*Z1Z1
|
||||
let mut s2 = other.y;
|
||||
s2.mul_assign(&self.z);
|
||||
s2.mul_assign(&z1z1);
|
||||
|
||||
if self.x == u2 && self.y == s2 {
|
||||
// The two points are equal, so we double.
|
||||
self.double();
|
||||
} else {
|
||||
// If we're adding -a and a together, self.z becomes zero as H becomes zero.
|
||||
|
||||
// H = U2-X1
|
||||
let mut h = u2;
|
||||
h.sub_assign(&self.x);
|
||||
|
||||
// HH = H^2
|
||||
let hh = h.square();
|
||||
|
||||
// I = 4*HH
|
||||
let i = hh.double().double();
|
||||
|
||||
// J = H*I
|
||||
let mut j = h;
|
||||
j.mul_assign(&i);
|
||||
|
||||
// r = 2*(S2-Y1)
|
||||
let mut r = s2;
|
||||
r.sub_assign(&self.y);
|
||||
r = r.double();
|
||||
|
||||
// V = X1*I
|
||||
let mut v = self.x;
|
||||
v.mul_assign(&i);
|
||||
|
||||
// X3 = r^2 - J - 2*V
|
||||
self.x = r.square();
|
||||
self.x.sub_assign(&j);
|
||||
self.x.sub_assign(&v);
|
||||
self.x.sub_assign(&v);
|
||||
|
||||
// Y3 = r*(V-X3)-2*Y1*J
|
||||
j.mul_assign(&self.y); // J = 2*Y1*J
|
||||
j = j.double();
|
||||
self.y = v;
|
||||
self.y.sub_assign(&self.x);
|
||||
self.y.mul_assign(&r);
|
||||
self.y.sub_assign(&j);
|
||||
|
||||
// Z3 = (Z1+H)^2-Z1Z1-HH
|
||||
self.z.add_assign(&h);
|
||||
self.z = self.z.square();
|
||||
self.z.sub_assign(&z1z1);
|
||||
self.z.sub_assign(&hh);
|
||||
}
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
if !self.is_zero() {
|
||||
self.y = self.y.neg();
|
||||
}
|
||||
}
|
||||
|
||||
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S) {
|
||||
let mut res = Self::zero();
|
||||
|
||||
@ -521,7 +663,7 @@ macro_rules! curve_impl {
|
||||
}
|
||||
|
||||
if i {
|
||||
res.add_assign(self);
|
||||
res.add_assign(&*self);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1258,7 +1400,7 @@ pub mod g1 {
|
||||
assert_eq!(tmp1, c.into_projective());
|
||||
|
||||
let mut tmp2 = a.into_projective();
|
||||
tmp2.add_assign_mixed(&b);
|
||||
tmp2.add_assign(&b);
|
||||
assert_eq!(tmp2.into_affine(), c);
|
||||
assert_eq!(tmp2, c.into_projective());
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ pub mod tests;
|
||||
pub mod bls12_381;
|
||||
|
||||
use ff::{Field, PrimeField, ScalarEngine, SqrtField};
|
||||
use group::{CurveAffine, CurveProjective};
|
||||
use group::{CurveAffine, CurveOps, CurveOpsOwned, CurveProjective};
|
||||
use subtle::CtOption;
|
||||
|
||||
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
|
||||
@ -30,7 +30,9 @@ use subtle::CtOption;
|
||||
pub trait Engine: ScalarEngine {
|
||||
/// The projective representation of an element in G1.
|
||||
type G1: CurveProjective<Engine = Self, Base = Self::Fq, Scalar = Self::Fr, Affine = Self::G1Affine>
|
||||
+ From<Self::G1Affine>;
|
||||
+ From<Self::G1Affine>
|
||||
+ CurveOps<Self::G1Affine>
|
||||
+ CurveOpsOwned<Self::G1Affine>;
|
||||
|
||||
/// The affine representation of an element in G1.
|
||||
type G1Affine: PairingCurveAffine<
|
||||
@ -44,7 +46,9 @@ pub trait Engine: ScalarEngine {
|
||||
|
||||
/// The projective representation of an element in G2.
|
||||
type G2: CurveProjective<Engine = Self, Base = Self::Fqe, Scalar = Self::Fr, Affine = Self::G2Affine>
|
||||
+ From<Self::G2Affine>;
|
||||
+ From<Self::G2Affine>
|
||||
+ CurveOps<Self::G2Affine>
|
||||
+ CurveOpsOwned<Self::G2Affine>;
|
||||
|
||||
/// The affine representation of an element in G2.
|
||||
type G2Affine: PairingCurveAffine<
|
||||
|
Loading…
x
Reference in New Issue
Block a user