mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-02-14 10:45:47 +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);
|
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);
|
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 g_c;
|
||||||
{
|
{
|
||||||
let mut rs = r;
|
let mut rs = r;
|
||||||
rs.mul_assign(&s);
|
rs.mul_assign(&s);
|
||||||
|
|
||||||
g_c = vk.delta_g1.mul(rs);
|
g_c = vk.delta_g1.mul(rs);
|
||||||
g_c.add_assign(&vk.alpha_g1.mul(s));
|
AddAssign::<&E::G1>::add_assign(&mut g_c, &vk.alpha_g1.mul(s));
|
||||||
g_c.add_assign(&vk.beta_g1.mul(r));
|
AddAssign::<&E::G1>::add_assign(&mut g_c, &vk.beta_g1.mul(r));
|
||||||
}
|
}
|
||||||
let mut a_answer = a_inputs.wait()?;
|
let mut a_answer = a_inputs.wait()?;
|
||||||
a_answer.add_assign(&a_aux.wait()?);
|
AddAssign::<&E::G1>::add_assign(&mut a_answer, &a_aux.wait()?);
|
||||||
g_a.add_assign(&a_answer);
|
AddAssign::<&E::G1>::add_assign(&mut g_a, &a_answer);
|
||||||
a_answer.mul_assign(s);
|
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()?;
|
let mut b1_answer: E::G1 = b_g1_inputs.wait()?;
|
||||||
b1_answer.add_assign(&b_g1_aux.wait()?);
|
AddAssign::<&E::G1>::add_assign(&mut b1_answer, &b_g1_aux.wait()?);
|
||||||
let mut b2_answer = b_g2_inputs.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);
|
b1_answer.mul_assign(r);
|
||||||
g_c.add_assign(&b1_answer);
|
AddAssign::<&E::G1>::add_assign(&mut g_c, &b1_answer);
|
||||||
g_c.add_assign(&h.wait()?);
|
AddAssign::<&E::G1>::add_assign(&mut g_c, &h.wait()?);
|
||||||
g_c.add_assign(&l.wait()?);
|
AddAssign::<&E::G1>::add_assign(&mut g_c, &l.wait()?);
|
||||||
|
|
||||||
Ok(Proof {
|
Ok(Proof {
|
||||||
a: g_a.into_affine(),
|
a: g_a.into_affine(),
|
||||||
|
@ -413,18 +413,6 @@ impl CurveProjective for Fr {
|
|||||||
self.0 = <Fr as Field>::double(self).0;
|
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) {
|
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S) {
|
||||||
let tmp = Fr::from_repr(other.into()).unwrap();
|
let tmp = Fr::from_repr(other.into()).unwrap();
|
||||||
|
|
||||||
@ -503,10 +491,6 @@ impl CurveAffine for Fr {
|
|||||||
<Fr as Field>::is_zero(self)
|
<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 {
|
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective {
|
||||||
let mut res = *self;
|
let mut res = *self;
|
||||||
let tmp = Fr::from_repr(other.into()).unwrap();
|
let tmp = Fr::from_repr(other.into()).unwrap();
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
use group::{CurveAffine, CurveProjective};
|
use group::{CurveAffine, CurveProjective};
|
||||||
use pairing::{Engine, PairingCurveAffine};
|
use pairing::{Engine, PairingCurveAffine};
|
||||||
|
use std::ops::{AddAssign, Neg};
|
||||||
|
|
||||||
use super::{PreparedVerifyingKey, Proof, VerifyingKey};
|
use super::{PreparedVerifyingKey, Proof, VerifyingKey};
|
||||||
|
|
||||||
use crate::SynthesisError;
|
use crate::SynthesisError;
|
||||||
|
|
||||||
pub fn prepare_verifying_key<E: Engine>(vk: &VerifyingKey<E>) -> PreparedVerifyingKey<E> {
|
pub fn prepare_verifying_key<E: Engine>(vk: &VerifyingKey<E>) -> PreparedVerifyingKey<E> {
|
||||||
let mut gamma = vk.gamma_g2;
|
let gamma = vk.gamma_g2.neg();
|
||||||
gamma.negate();
|
let delta = vk.delta_g2.neg();
|
||||||
let mut delta = vk.delta_g2;
|
|
||||||
delta.negate();
|
|
||||||
|
|
||||||
PreparedVerifyingKey {
|
PreparedVerifyingKey {
|
||||||
alpha_g1_beta_g2: E::pairing(vk.alpha_g1, vk.beta_g2),
|
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();
|
let mut acc = pvk.ic[0].into_projective();
|
||||||
|
|
||||||
for (i, b) in public_inputs.iter().zip(pvk.ic.iter().skip(1)) {
|
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:
|
// The original verification equation is:
|
||||||
|
@ -5,6 +5,7 @@ use futures::Future;
|
|||||||
use group::{CurveAffine, CurveProjective};
|
use group::{CurveAffine, CurveProjective};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
use std::ops::AddAssign;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::SynthesisError;
|
use super::SynthesisError;
|
||||||
@ -18,16 +19,24 @@ pub trait SourceBuilder<G: CurveAffine>: Send + Sync + 'static + Clone {
|
|||||||
|
|
||||||
/// A source of bases, like an iterator.
|
/// A source of bases, like an iterator.
|
||||||
pub trait Source<G: CurveAffine> {
|
pub trait Source<G: CurveAffine> {
|
||||||
/// Parses the element from the source. Fails if the point is at infinity.
|
fn next(&mut self) -> Result<&G, SynthesisError>;
|
||||||
fn add_assign_mixed(
|
|
||||||
&mut self,
|
|
||||||
to: &mut <G as CurveAffine>::Projective,
|
|
||||||
) -> Result<(), SynthesisError>;
|
|
||||||
|
|
||||||
/// Skips `amt` elements from the source, avoiding deserialization.
|
/// Skips `amt` elements from the source, avoiding deserialization.
|
||||||
fn skip(&mut self, amt: usize) -> Result<(), SynthesisError>;
|
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) {
|
impl<G: CurveAffine> SourceBuilder<G> for (Arc<Vec<G>>, usize) {
|
||||||
type Source = (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) {
|
impl<G: CurveAffine> Source<G> for (Arc<Vec<G>>, usize) {
|
||||||
fn add_assign_mixed(
|
fn next(&mut self) -> Result<&G, SynthesisError> {
|
||||||
&mut self,
|
|
||||||
to: &mut <G as CurveAffine>::Projective,
|
|
||||||
) -> Result<(), SynthesisError> {
|
|
||||||
if self.0.len() <= self.1 {
|
if self.0.len() <= self.1 {
|
||||||
return Err(io::Error::new(
|
return Err(io::Error::new(
|
||||||
io::ErrorKind::UnexpectedEof,
|
io::ErrorKind::UnexpectedEof,
|
||||||
@ -53,11 +59,10 @@ impl<G: CurveAffine> Source<G> for (Arc<Vec<G>>, usize) {
|
|||||||
return Err(SynthesisError::UnexpectedIdentity);
|
return Err(SynthesisError::UnexpectedIdentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
to.add_assign_mixed(&self.0[self.1]);
|
let ret = &self.0[self.1];
|
||||||
|
|
||||||
self.1 += 1;
|
self.1 += 1;
|
||||||
|
|
||||||
Ok(())
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip(&mut self, amt: usize) -> Result<(), SynthesisError> {
|
fn skip(&mut self, amt: usize) -> Result<(), SynthesisError> {
|
||||||
@ -153,12 +158,12 @@ fn multiexp_inner<Q, D, G, S>(
|
|||||||
mut skip: u32,
|
mut skip: u32,
|
||||||
c: u32,
|
c: u32,
|
||||||
handle_trivial: bool,
|
handle_trivial: bool,
|
||||||
) -> Box<dyn Future<Item = <G as CurveAffine>::Projective, Error = SynthesisError>>
|
) -> Box<dyn Future<Item = G, Error = SynthesisError>>
|
||||||
where
|
where
|
||||||
for<'a> &'a Q: QueryDensity,
|
for<'a> &'a Q: QueryDensity,
|
||||||
D: Send + Sync + 'static + Clone + AsRef<Q>,
|
D: Send + Sync + 'static + Clone + AsRef<Q>,
|
||||||
G: CurveAffine,
|
G: CurveProjective,
|
||||||
S: SourceBuilder<G>,
|
S: SourceBuilder<<G as CurveProjective>::Affine>,
|
||||||
{
|
{
|
||||||
// Perform this region of the multiexp
|
// Perform this region of the multiexp
|
||||||
let this = {
|
let this = {
|
||||||
@ -168,13 +173,13 @@ where
|
|||||||
|
|
||||||
pool.compute(move || {
|
pool.compute(move || {
|
||||||
// Accumulate the result
|
// Accumulate the result
|
||||||
let mut acc = G::Projective::zero();
|
let mut acc = G::zero();
|
||||||
|
|
||||||
// Build a source for the bases
|
// Build a source for the bases
|
||||||
let mut bases = bases.new();
|
let mut bases = bases.new();
|
||||||
|
|
||||||
// Create space for the buckets
|
// 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 zero = <G::Engine as ScalarEngine>::Fr::zero().into_repr();
|
||||||
let one = <G::Engine as ScalarEngine>::Fr::one().into_repr();
|
let one = <G::Engine as ScalarEngine>::Fr::one().into_repr();
|
||||||
@ -186,7 +191,7 @@ where
|
|||||||
bases.skip(1)?;
|
bases.skip(1)?;
|
||||||
} else if exp == one {
|
} else if exp == one {
|
||||||
if handle_trivial {
|
if handle_trivial {
|
||||||
bases.add_assign_mixed(&mut acc)?;
|
acc.add_assign_from_source(&mut bases)?;
|
||||||
} else {
|
} else {
|
||||||
bases.skip(1)?;
|
bases.skip(1)?;
|
||||||
}
|
}
|
||||||
@ -196,7 +201,8 @@ where
|
|||||||
let exp = exp.as_ref()[0] % (1 << c);
|
let exp = exp.as_ref()[0] % (1 << c);
|
||||||
|
|
||||||
if exp != 0 {
|
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 {
|
} else {
|
||||||
bases.skip(1)?;
|
bases.skip(1)?;
|
||||||
}
|
}
|
||||||
@ -208,7 +214,7 @@ where
|
|||||||
// e.g. 3a + 2b + 1c = a +
|
// e.g. 3a + 2b + 1c = a +
|
||||||
// (a) + b +
|
// (a) + b +
|
||||||
// ((a) + b) + c
|
// ((a) + b) + c
|
||||||
let mut running_sum = G::Projective::zero();
|
let mut running_sum = G::zero();
|
||||||
for exp in buckets.into_iter().rev() {
|
for exp in buckets.into_iter().rev() {
|
||||||
running_sum.add_assign(&exp);
|
running_sum.add_assign(&exp);
|
||||||
acc.add_assign(&running_sum);
|
acc.add_assign(&running_sum);
|
||||||
@ -236,7 +242,7 @@ where
|
|||||||
c,
|
c,
|
||||||
false,
|
false,
|
||||||
))
|
))
|
||||||
.map(move |(this, mut higher)| {
|
.map(move |(this, mut higher): (_, G)| {
|
||||||
for _ in 0..c {
|
for _ in 0..c {
|
||||||
higher.double();
|
higher.double();
|
||||||
}
|
}
|
||||||
@ -256,12 +262,12 @@ pub fn multiexp<Q, D, G, S>(
|
|||||||
bases: S,
|
bases: S,
|
||||||
density_map: D,
|
density_map: D,
|
||||||
exponents: Arc<Vec<<<G::Engine as ScalarEngine>::Fr as PrimeField>::Repr>>,
|
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
|
where
|
||||||
for<'a> &'a Q: QueryDensity,
|
for<'a> &'a Q: QueryDensity,
|
||||||
D: Send + Sync + 'static + Clone + AsRef<Q>,
|
D: Send + Sync + 'static + Clone + AsRef<Q>,
|
||||||
G: CurveAffine,
|
G: CurveProjective,
|
||||||
S: SourceBuilder<G>,
|
S: SourceBuilder<<G as CurveProjective>::Affine>,
|
||||||
{
|
{
|
||||||
let c = if exponents.len() < 32 {
|
let c = if exponents.len() < 32 {
|
||||||
3u32
|
3u32
|
||||||
@ -282,16 +288,16 @@ where
|
|||||||
#[cfg(feature = "pairing")]
|
#[cfg(feature = "pairing")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_with_bls12() {
|
fn test_with_bls12() {
|
||||||
fn naive_multiexp<G: CurveAffine>(
|
fn naive_multiexp<G: CurveProjective>(
|
||||||
bases: Arc<Vec<G>>,
|
bases: Arc<Vec<<G as CurveProjective>::Affine>>,
|
||||||
exponents: Arc<Vec<<G::Scalar as PrimeField>::Repr>>,
|
exponents: Arc<Vec<<G::Scalar as PrimeField>::Repr>>,
|
||||||
) -> G::Projective {
|
) -> G {
|
||||||
assert_eq!(bases.len(), exponents.len());
|
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()) {
|
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
|
acc
|
||||||
@ -314,7 +320,7 @@ fn test_with_bls12() {
|
|||||||
.collect::<Vec<_>>(),
|
.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();
|
let pool = Worker::new();
|
||||||
|
|
||||||
|
@ -5,16 +5,46 @@ use ff::{PrimeField, PrimeFieldDecodingError, ScalarEngine, SqrtField};
|
|||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
|
||||||
|
|
||||||
pub mod tests;
|
pub mod tests;
|
||||||
|
|
||||||
mod wnaf;
|
mod wnaf;
|
||||||
pub use self::wnaf::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
|
/// Projective representation of an elliptic curve point guaranteed to be
|
||||||
/// in the correct prime order subgroup.
|
/// in the correct prime order subgroup.
|
||||||
pub trait CurveProjective:
|
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 Engine: ScalarEngine<Fr = Self::Scalar>;
|
||||||
type Scalar: PrimeField + SqrtField;
|
type Scalar: PrimeField + SqrtField;
|
||||||
@ -44,22 +74,6 @@ pub trait CurveProjective:
|
|||||||
/// Doubles this element.
|
/// Doubles this element.
|
||||||
fn double(&mut self);
|
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.
|
/// Performs scalar multiplication of this element.
|
||||||
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S);
|
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
|
/// Affine representation of an elliptic curve point guaranteed to be
|
||||||
/// in the correct prime order subgroup.
|
/// in the correct prime order subgroup.
|
||||||
pub trait CurveAffine:
|
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 Engine: ScalarEngine<Fr = Self::Scalar>;
|
||||||
type Scalar: PrimeField + SqrtField;
|
type Scalar: PrimeField + SqrtField;
|
||||||
@ -97,9 +121,6 @@ pub trait CurveAffine:
|
|||||||
/// additive identity.
|
/// additive identity.
|
||||||
fn is_zero(&self) -> bool;
|
fn is_zero(&self) -> bool;
|
||||||
|
|
||||||
/// Negates this element.
|
|
||||||
fn negate(&mut self);
|
|
||||||
|
|
||||||
/// Performs scalar multiplication of this element with mixed addition.
|
/// Performs scalar multiplication of this element with mixed addition.
|
||||||
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective;
|
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.
|
// Negation edge case with zero.
|
||||||
{
|
{
|
||||||
let mut z = G::zero();
|
let z = G::zero().neg();
|
||||||
z.negate();
|
|
||||||
assert!(z.is_zero());
|
assert!(z.is_zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,19 +30,19 @@ pub fn curve_tests<G: CurveProjective>() {
|
|||||||
let rcopy = r;
|
let rcopy = r;
|
||||||
r.add_assign(&G::zero());
|
r.add_assign(&G::zero());
|
||||||
assert_eq!(r, rcopy);
|
assert_eq!(r, rcopy);
|
||||||
r.add_assign_mixed(&G::Affine::zero());
|
r.add_assign(&G::Affine::zero());
|
||||||
assert_eq!(r, rcopy);
|
assert_eq!(r, rcopy);
|
||||||
|
|
||||||
let mut z = G::zero();
|
let mut z = G::zero();
|
||||||
z.add_assign(&G::zero());
|
z.add_assign(&G::zero());
|
||||||
assert!(z.is_zero());
|
assert!(z.is_zero());
|
||||||
z.add_assign_mixed(&G::Affine::zero());
|
z.add_assign(&G::Affine::zero());
|
||||||
assert!(z.is_zero());
|
assert!(z.is_zero());
|
||||||
|
|
||||||
let mut z2 = z;
|
let mut z2 = z;
|
||||||
z2.add_assign(&r);
|
z2.add_assign(&r);
|
||||||
|
|
||||||
z.add_assign_mixed(&r.into_affine());
|
z.add_assign(&r.into_affine());
|
||||||
|
|
||||||
assert_eq!(z, z2);
|
assert_eq!(z, z2);
|
||||||
assert_eq!(z, r);
|
assert_eq!(z, r);
|
||||||
@ -68,7 +67,7 @@ pub fn curve_tests<G: CurveProjective>() {
|
|||||||
random_negation_tests::<G>();
|
random_negation_tests::<G>();
|
||||||
random_transformation_tests::<G>();
|
random_transformation_tests::<G>();
|
||||||
random_wnaf_tests::<G>();
|
random_wnaf_tests::<G>();
|
||||||
random_encoding_tests::<G::Affine>();
|
random_encoding_tests::<G>();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_wnaf_tests<G: CurveProjective>() {
|
fn random_wnaf_tests<G: CurveProjective>() {
|
||||||
@ -213,11 +212,10 @@ fn random_negation_tests<G: CurveProjective>() {
|
|||||||
assert!(t3.is_zero());
|
assert!(t3.is_zero());
|
||||||
|
|
||||||
let mut t4 = t1;
|
let mut t4 = t1;
|
||||||
t4.add_assign_mixed(&t2.into_affine());
|
t4.add_assign(&t2.into_affine());
|
||||||
assert!(t4.is_zero());
|
assert!(t4.is_zero());
|
||||||
|
|
||||||
t1.negate();
|
assert_eq!(t1.neg(), t2);
|
||||||
assert_eq!(t1, t2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +242,7 @@ fn random_doubling_tests<G: CurveProjective>() {
|
|||||||
tmp2.add_assign(&b);
|
tmp2.add_assign(&b);
|
||||||
|
|
||||||
let mut tmp3 = a;
|
let mut tmp3 = a;
|
||||||
tmp3.add_assign_mixed(&b.into_affine());
|
tmp3.add_assign(&b.into_affine());
|
||||||
|
|
||||||
assert_eq!(tmp1, tmp2);
|
assert_eq!(tmp1, tmp2);
|
||||||
assert_eq!(tmp1, tmp3);
|
assert_eq!(tmp1, tmp3);
|
||||||
@ -306,7 +304,7 @@ fn random_addition_tests<G: CurveProjective>() {
|
|||||||
aplusa.add_assign(&a);
|
aplusa.add_assign(&a);
|
||||||
|
|
||||||
let mut aplusamixed = a;
|
let mut aplusamixed = a;
|
||||||
aplusamixed.add_assign_mixed(&a.into_affine());
|
aplusamixed.add_assign(&a.into_affine());
|
||||||
|
|
||||||
let mut adouble = a;
|
let mut adouble = a;
|
||||||
adouble.double();
|
adouble.double();
|
||||||
@ -336,18 +334,18 @@ fn random_addition_tests<G: CurveProjective>() {
|
|||||||
|
|
||||||
// (a + b) + c
|
// (a + b) + c
|
||||||
tmp[3] = a_affine.into_projective();
|
tmp[3] = a_affine.into_projective();
|
||||||
tmp[3].add_assign_mixed(&b_affine);
|
tmp[3].add_assign(&b_affine);
|
||||||
tmp[3].add_assign_mixed(&c_affine);
|
tmp[3].add_assign(&c_affine);
|
||||||
|
|
||||||
// a + (b + c)
|
// a + (b + c)
|
||||||
tmp[4] = b_affine.into_projective();
|
tmp[4] = b_affine.into_projective();
|
||||||
tmp[4].add_assign_mixed(&c_affine);
|
tmp[4].add_assign(&c_affine);
|
||||||
tmp[4].add_assign_mixed(&a_affine);
|
tmp[4].add_assign(&a_affine);
|
||||||
|
|
||||||
// (a + c) + b
|
// (a + c) + b
|
||||||
tmp[5] = a_affine.into_projective();
|
tmp[5] = a_affine.into_projective();
|
||||||
tmp[5].add_assign_mixed(&c_affine);
|
tmp[5].add_assign(&c_affine);
|
||||||
tmp[5].add_assign_mixed(&b_affine);
|
tmp[5].add_assign(&b_affine);
|
||||||
|
|
||||||
// Comparisons
|
// Comparisons
|
||||||
for i in 0..6 {
|
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([
|
let mut rng = XorShiftRng::from_seed([
|
||||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||||
0xe5,
|
0xe5,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
G::zero().into_uncompressed().into_affine().unwrap(),
|
G::Affine::zero().into_uncompressed().into_affine().unwrap(),
|
||||||
G::zero()
|
G::Affine::zero()
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
G::zero().into_compressed().into_affine().unwrap(),
|
G::Affine::zero().into_compressed().into_affine().unwrap(),
|
||||||
G::zero()
|
G::Affine::zero()
|
||||||
);
|
);
|
||||||
|
|
||||||
for _ in 0..1000 {
|
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 uncompressed = r.into_uncompressed();
|
||||||
let de_uncompressed = uncompressed.into_affine().unwrap();
|
let de_uncompressed = uncompressed.into_affine().unwrap();
|
||||||
@ -440,7 +438,7 @@ fn random_encoding_tests<G: CurveAffine>() {
|
|||||||
let de_compressed = compressed.into_affine().unwrap();
|
let de_compressed = compressed.into_affine().unwrap();
|
||||||
assert_eq!(de_compressed, r);
|
assert_eq!(de_compressed, r);
|
||||||
|
|
||||||
r.negate();
|
r = r.neg();
|
||||||
|
|
||||||
let compressed = r.into_compressed();
|
let compressed = r.into_compressed();
|
||||||
let de_compressed = compressed.into_affine().unwrap();
|
let de_compressed = compressed.into_affine().unwrap();
|
||||||
|
@ -2,6 +2,7 @@ pub(crate) mod g1 {
|
|||||||
use criterion::{criterion_group, Criterion};
|
use criterion::{criterion_group, Criterion};
|
||||||
use rand_core::SeedableRng;
|
use rand_core::SeedableRng;
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
|
use std::ops::AddAssign;
|
||||||
|
|
||||||
use ff::Field;
|
use ff::Field;
|
||||||
use group::CurveProjective;
|
use group::CurveProjective;
|
||||||
@ -69,7 +70,7 @@ pub(crate) mod g1 {
|
|||||||
c.bench_function("G1::add_assign_mixed", |b| {
|
c.bench_function("G1::add_assign_mixed", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut tmp = v[count].0;
|
let mut tmp = v[count].0;
|
||||||
tmp.add_assign_mixed(&v[count].1);
|
tmp.add_assign(&v[count].1);
|
||||||
count = (count + 1) % SAMPLES;
|
count = (count + 1) % SAMPLES;
|
||||||
tmp
|
tmp
|
||||||
})
|
})
|
||||||
@ -88,6 +89,7 @@ pub(crate) mod g2 {
|
|||||||
use criterion::{criterion_group, Criterion};
|
use criterion::{criterion_group, Criterion};
|
||||||
use rand_core::SeedableRng;
|
use rand_core::SeedableRng;
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
|
use std::ops::AddAssign;
|
||||||
|
|
||||||
use ff::Field;
|
use ff::Field;
|
||||||
use group::CurveProjective;
|
use group::CurveProjective;
|
||||||
@ -155,7 +157,7 @@ pub(crate) mod g2 {
|
|||||||
c.bench_function("G2::add_assign_mixed", |b| {
|
c.bench_function("G2::add_assign_mixed", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut tmp = v[count].0;
|
let mut tmp = v[count].0;
|
||||||
tmp.add_assign_mixed(&v[count].1);
|
tmp.add_assign(&v[count].1);
|
||||||
count = (count + 1) % SAMPLES;
|
count = (count + 1) % SAMPLES;
|
||||||
tmp
|
tmp
|
||||||
})
|
})
|
||||||
|
@ -86,7 +86,7 @@ macro_rules! curve_impl {
|
|||||||
for i in bits {
|
for i in bits {
|
||||||
res.double();
|
res.double();
|
||||||
if i {
|
if i {
|
||||||
res.add_assign_mixed(self)
|
res.add_assign(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res
|
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 {
|
impl CurveAffine for $affine {
|
||||||
type Engine = Bls12;
|
type Engine = Bls12;
|
||||||
type Scalar = $scalarfield;
|
type Scalar = $scalarfield;
|
||||||
@ -163,12 +176,6 @@ macro_rules! curve_impl {
|
|||||||
self.mul_bits(bits)
|
self.mul_bits(bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn negate(&mut self) {
|
|
||||||
if !self.is_zero() {
|
|
||||||
self.y = self.y.neg();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_projective(&self) -> $projective {
|
fn into_projective(&self) -> $projective {
|
||||||
(*self).into()
|
(*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 {
|
impl CurveProjective for $projective {
|
||||||
type Engine = Bls12;
|
type Engine = Bls12;
|
||||||
type Scalar = $scalarfield;
|
type Scalar = $scalarfield;
|
||||||
@ -340,174 +650,6 @@ macro_rules! curve_impl {
|
|||||||
self.y.sub_assign(&c);
|
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) {
|
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S) {
|
||||||
let mut res = Self::zero();
|
let mut res = Self::zero();
|
||||||
|
|
||||||
@ -521,7 +663,7 @@ macro_rules! curve_impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if i {
|
if i {
|
||||||
res.add_assign(self);
|
res.add_assign(&*self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1258,7 +1400,7 @@ pub mod g1 {
|
|||||||
assert_eq!(tmp1, c.into_projective());
|
assert_eq!(tmp1, c.into_projective());
|
||||||
|
|
||||||
let mut tmp2 = a.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.into_affine(), c);
|
||||||
assert_eq!(tmp2, c.into_projective());
|
assert_eq!(tmp2, c.into_projective());
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ pub mod tests;
|
|||||||
pub mod bls12_381;
|
pub mod bls12_381;
|
||||||
|
|
||||||
use ff::{Field, PrimeField, ScalarEngine, SqrtField};
|
use ff::{Field, PrimeField, ScalarEngine, SqrtField};
|
||||||
use group::{CurveAffine, CurveProjective};
|
use group::{CurveAffine, CurveOps, CurveOpsOwned, CurveProjective};
|
||||||
use subtle::CtOption;
|
use subtle::CtOption;
|
||||||
|
|
||||||
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
|
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
|
||||||
@ -30,7 +30,9 @@ use subtle::CtOption;
|
|||||||
pub trait Engine: ScalarEngine {
|
pub trait Engine: ScalarEngine {
|
||||||
/// The projective representation of an element in G1.
|
/// The projective representation of an element in G1.
|
||||||
type G1: CurveProjective<Engine = Self, Base = Self::Fq, Scalar = Self::Fr, Affine = Self::G1Affine>
|
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.
|
/// The affine representation of an element in G1.
|
||||||
type G1Affine: PairingCurveAffine<
|
type G1Affine: PairingCurveAffine<
|
||||||
@ -44,7 +46,9 @@ pub trait Engine: ScalarEngine {
|
|||||||
|
|
||||||
/// The projective representation of an element in G2.
|
/// The projective representation of an element in G2.
|
||||||
type G2: CurveProjective<Engine = Self, Base = Self::Fqe, Scalar = Self::Fr, Affine = Self::G2Affine>
|
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.
|
/// The affine representation of an element in G2.
|
||||||
type G2Affine: PairingCurveAffine<
|
type G2Affine: PairingCurveAffine<
|
||||||
|
Loading…
x
Reference in New Issue
Block a user