diff --git a/bellman/src/domain.rs b/bellman/src/domain.rs index ddba4f4..a1e4a4c 100644 --- a/bellman/src/domain.rs +++ b/bellman/src/domain.rs @@ -13,6 +13,7 @@ use ff::{Field, PrimeField, ScalarEngine}; use group::CurveProjective; +use std::ops::{AddAssign, MulAssign, SubAssign}; use super::SynthesisError; diff --git a/bellman/src/gadgets/lookup.rs b/bellman/src/gadgets/lookup.rs index b83844d..3be3ed9 100644 --- a/bellman/src/gadgets/lookup.rs +++ b/bellman/src/gadgets/lookup.rs @@ -1,6 +1,7 @@ //! Window table lookup gadgets. use ff::{Field, ScalarEngine}; +use std::ops::AddAssign; use super::boolean::Boolean; use super::num::{AllocatedNum, Num}; diff --git a/bellman/src/gadgets/multipack.rs b/bellman/src/gadgets/multipack.rs index c0dc50e..445a360 100644 --- a/bellman/src/gadgets/multipack.rs +++ b/bellman/src/gadgets/multipack.rs @@ -5,6 +5,7 @@ use super::num::Num; use super::Assignment; use crate::{ConstraintSystem, SynthesisError}; use ff::{Field, PrimeField, ScalarEngine}; +use std::ops::AddAssign; /// Takes a sequence of booleans and exposes them as compact /// public inputs diff --git a/bellman/src/gadgets/num.rs b/bellman/src/gadgets/num.rs index 8be5448..da3e4a0 100644 --- a/bellman/src/gadgets/num.rs +++ b/bellman/src/gadgets/num.rs @@ -1,6 +1,7 @@ //! Gadgets representing numbers in the scalar field of the underlying curve. use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, ScalarEngine}; +use std::ops::{AddAssign, MulAssign}; use crate::{ConstraintSystem, LinearCombination, SynthesisError, Variable}; @@ -416,6 +417,7 @@ mod test { use pairing::bls12_381::{Bls12, Fr}; use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; + use std::ops::SubAssign; use super::{AllocatedNum, Boolean}; use crate::gadgets::test::*; diff --git a/bellman/src/gadgets/test/mod.rs b/bellman/src/gadgets/test/mod.rs index 47392f1..f0668b4 100644 --- a/bellman/src/gadgets/test/mod.rs +++ b/bellman/src/gadgets/test/mod.rs @@ -6,6 +6,7 @@ use crate::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable use std::collections::HashMap; use std::fmt::Write; +use std::ops::{AddAssign, MulAssign}; use byteorder::{BigEndian, ByteOrder}; use std::cmp::Ordering; diff --git a/bellman/src/groth16/generator.rs b/bellman/src/groth16/generator.rs index 767eddd..11844d7 100644 --- a/bellman/src/groth16/generator.rs +++ b/bellman/src/groth16/generator.rs @@ -1,5 +1,5 @@ use rand_core::RngCore; - +use std::ops::{AddAssign, MulAssign}; use std::sync::Arc; use ff::{Field, PrimeField}; diff --git a/bellman/src/groth16/mod.rs b/bellman/src/groth16/mod.rs index 1ff152d..6f5af85 100644 --- a/bellman/src/groth16/mod.rs +++ b/bellman/src/groth16/mod.rs @@ -474,6 +474,7 @@ mod test_with_bls12_381 { use ff::Field; use pairing::bls12_381::{Bls12, Fr}; use rand::thread_rng; + use std::ops::MulAssign; #[test] fn serialization() { diff --git a/bellman/src/groth16/prover.rs b/bellman/src/groth16/prover.rs index 7fe282f..3c5b90f 100644 --- a/bellman/src/groth16/prover.rs +++ b/bellman/src/groth16/prover.rs @@ -1,5 +1,5 @@ use rand_core::RngCore; - +use std::ops::{AddAssign, MulAssign}; use std::sync::Arc; use futures::Future; diff --git a/bellman/src/groth16/tests/dummy_engine.rs b/bellman/src/groth16/tests/dummy_engine.rs index 4692078..325c198 100644 --- a/bellman/src/groth16/tests/dummy_engine.rs +++ b/bellman/src/groth16/tests/dummy_engine.rs @@ -9,6 +9,7 @@ use rand_core::RngCore; use std::cmp::Ordering; use std::fmt; use std::num::Wrapping; +use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; const MODULUS_R: Wrapping = Wrapping(64513); @@ -21,6 +22,96 @@ impl fmt::Display for Fr { } } +impl<'r> Add<&'r Fr> for Fr { + type Output = Self; + + fn add(self, other: &Self) -> Self { + let mut ret = self; + AddAssign::add_assign(&mut ret, other); + ret + } +} + +impl Add for Fr { + type Output = Self; + + fn add(self, other: Self) -> Self { + self + &other + } +} + +impl<'r> AddAssign<&'r Fr> for Fr { + fn add_assign(&mut self, other: &Self) { + self.0 = (self.0 + other.0) % MODULUS_R; + } +} + +impl AddAssign for Fr { + fn add_assign(&mut self, other: Self) { + AddAssign::add_assign(self, &other); + } +} + +impl<'r> Sub<&'r Fr> for Fr { + type Output = Self; + + fn sub(self, other: &Self) -> Self { + let mut ret = self; + SubAssign::sub_assign(&mut ret, other); + ret + } +} + +impl Sub for Fr { + type Output = Self; + + fn sub(self, other: Self) -> Self { + self - &other + } +} + +impl<'r> SubAssign<&'r Fr> for Fr { + fn sub_assign(&mut self, other: &Self) { + self.0 = ((MODULUS_R + self.0) - other.0) % MODULUS_R; + } +} + +impl SubAssign for Fr { + fn sub_assign(&mut self, other: Self) { + SubAssign::sub_assign(self, &other); + } +} + +impl<'r> Mul<&'r Fr> for Fr { + type Output = Self; + + fn mul(self, other: &Self) -> Self { + let mut ret = self; + MulAssign::mul_assign(&mut ret, other); + ret + } +} + +impl Mul for Fr { + type Output = Self; + + fn mul(self, other: Self) -> Self { + self * &other + } +} + +impl<'r> MulAssign<&'r Fr> for Fr { + fn mul_assign(&mut self, other: &Self) { + self.0 = (self.0 * other.0) % MODULUS_R; + } +} + +impl MulAssign for Fr { + fn mul_assign(&mut self, other: Self) { + MulAssign::mul_assign(self, &other); + } +} + impl Field for Fr { fn random(rng: &mut R) -> Self { Fr(Wrapping(rng.next_u32()) % MODULUS_R) @@ -52,18 +143,6 @@ impl Field for Fr { } } - fn add_assign(&mut self, other: &Self) { - self.0 = (self.0 + other.0) % MODULUS_R; - } - - fn sub_assign(&mut self, other: &Self) { - self.0 = ((MODULUS_R + self.0) - other.0) % MODULUS_R; - } - - fn mul_assign(&mut self, other: &Self) { - self.0 = (self.0 * other.0) % MODULUS_R; - } - fn inverse(&self) -> Option { if ::is_zero(self) { None @@ -121,9 +200,9 @@ impl SqrtField for Fr { for _ in 0..(m - i - 1) { c.square(); } - ::mul_assign(&mut r, &c); + MulAssign::mul_assign(&mut r, &c); c.square(); - ::mul_assign(&mut t, &c); + MulAssign::mul_assign(&mut t, &c); m = i; } @@ -280,8 +359,8 @@ impl Engine for DummyEngine { for &(a, b) in i { let mut tmp = *a; - ::mul_assign(&mut tmp, b); - ::add_assign(&mut acc, &tmp); + MulAssign::mul_assign(&mut tmp, b); + AddAssign::add_assign(&mut acc, &tmp); } acc @@ -326,11 +405,11 @@ impl CurveProjective for Fr { } fn add_assign(&mut self, other: &Self) { - ::add_assign(self, other); + AddAssign::add_assign(self, other); } fn add_assign_mixed(&mut self, other: &Self) { - ::add_assign(self, other); + AddAssign::add_assign(self, other); } fn negate(&mut self) { @@ -340,7 +419,7 @@ impl CurveProjective for Fr { fn mul_assign::Repr>>(&mut self, other: S) { let tmp = Fr::from_repr(other.into()).unwrap(); - ::mul_assign(self, &tmp); + MulAssign::mul_assign(self, &tmp); } fn into_affine(&self) -> Fr { @@ -423,7 +502,7 @@ impl CurveAffine for Fr { let mut res = *self; let tmp = Fr::from_repr(other.into()).unwrap(); - ::mul_assign(&mut res, &tmp); + MulAssign::mul_assign(&mut res, &tmp); res } diff --git a/bellman/src/groth16/tests/mod.rs b/bellman/src/groth16/tests/mod.rs index d8be98e..aaefb5f 100644 --- a/bellman/src/groth16/tests/mod.rs +++ b/bellman/src/groth16/tests/mod.rs @@ -5,6 +5,7 @@ mod dummy_engine; use self::dummy_engine::*; use std::marker::PhantomData; +use std::ops::{AddAssign, MulAssign, SubAssign}; use crate::{Circuit, ConstraintSystem, SynthesisError}; diff --git a/bellman/src/lib.rs b/bellman/src/lib.rs index ef13a83..3877c3f 100644 --- a/bellman/src/lib.rs +++ b/bellman/src/lib.rs @@ -148,7 +148,7 @@ use std::error::Error; use std::fmt; use std::io; use std::marker::PhantomData; -use std::ops::{Add, Sub}; +use std::ops::{Add, MulAssign, Sub}; /// Computations are expressed in terms of arithmetic circuits, in particular /// rank-1 quadratic constraint systems. The `Circuit` trait represents a diff --git a/bellman/tests/mimc.rs b/bellman/tests/mimc.rs index e9a4c7c..0792af5 100644 --- a/bellman/tests/mimc.rs +++ b/bellman/tests/mimc.rs @@ -7,6 +7,7 @@ use std::time::{Duration, Instant}; // Bring in some tools for using pairing-friendly curves use ff::{Field, ScalarEngine}; use pairing::Engine; +use std::ops::{AddAssign, MulAssign}; // We're going to use the BLS12-381 pairing-friendly elliptic curve. use pairing::bls12_381::Bls12; diff --git a/ff/ff_derive/src/lib.rs b/ff/ff_derive/src/lib.rs index d47ec12..b230e7f 100644 --- a/ff/ff_derive/src/lib.rs +++ b/ff/ff_derive/src/lib.rs @@ -833,6 +833,119 @@ fn prime_field_impl( } } + impl<'r> ::std::ops::Add<&'r #name> for #name { + type Output = #name; + + #[inline] + fn add(self, other: &#name) -> #name { + let mut ret = self; + ret.add_assign(other); + ret + } + } + + impl ::std::ops::Add for #name { + type Output = #name; + + #[inline] + fn add(self, other: #name) -> Self { + self + &other + } + } + + impl<'r> ::std::ops::AddAssign<&'r #name> for #name { + #[inline] + fn add_assign(&mut self, other: &#name) { + // This cannot exceed the backing capacity. + self.0.add_nocarry(&other.0); + + // However, it may need to be reduced. + self.reduce(); + } + } + + impl ::std::ops::AddAssign for #name { + #[inline] + fn add_assign(&mut self, other: #name) { + self.add_assign(&other); + } + } + + impl<'r> ::std::ops::Sub<&'r #name> for #name { + type Output = #name; + + #[inline] + fn sub(self, other: &#name) -> Self { + let mut ret = self; + ret.sub_assign(other); + ret + } + } + + impl ::std::ops::Sub for #name { + type Output = #name; + + #[inline] + fn sub(self, other: #name) -> Self { + self - &other + } + } + + impl<'r> ::std::ops::SubAssign<&'r #name> for #name { + #[inline] + fn sub_assign(&mut self, other: &#name) { + // If `other` is larger than `self`, we'll need to add the modulus to self first. + if other.0 > self.0 { + self.0.add_nocarry(&MODULUS); + } + + self.0.sub_noborrow(&other.0); + } + } + + impl ::std::ops::SubAssign for #name { + #[inline] + fn sub_assign(&mut self, other: #name) { + self.sub_assign(&other); + } + } + + impl<'r> ::std::ops::Mul<&'r #name> for #name { + type Output = #name; + + #[inline] + fn mul(self, other: &#name) -> Self { + let mut ret = self; + ret.mul_assign(other); + ret + } + } + + impl ::std::ops::Mul for #name { + type Output = #name; + + #[inline] + fn mul(self, other: #name) -> Self { + self * &other + } + } + + impl<'r> ::std::ops::MulAssign<&'r #name> for #name { + #[inline] + fn mul_assign(&mut self, other: &#name) + { + #multiply_impl + } + } + + impl ::std::ops::MulAssign for #name { + #[inline] + fn mul_assign(&mut self, other: #name) + { + self.mul_assign(&other); + } + } + impl ::ff::PrimeField for #name { type Repr = #repr; @@ -911,15 +1024,6 @@ fn prime_field_impl( self.0.is_zero() } - #[inline] - fn add_assign(&mut self, other: &#name) { - // This cannot exceed the backing capacity. - self.0.add_nocarry(&other.0); - - // However, it may need to be reduced. - self.reduce(); - } - #[inline] fn double(&mut self) { // This cannot exceed the backing capacity. @@ -929,16 +1033,6 @@ fn prime_field_impl( self.reduce(); } - #[inline] - fn sub_assign(&mut self, other: &#name) { - // If `other` is larger than `self`, we'll need to add the modulus to self first. - if other.0 > self.0 { - self.0.add_nocarry(&MODULUS); - } - - self.0.sub_noborrow(&other.0); - } - #[inline] fn negate(&mut self) { if !self.is_zero() { @@ -1008,12 +1102,6 @@ fn prime_field_impl( // This has no effect in a prime field. } - #[inline] - fn mul_assign(&mut self, other: &#name) - { - #multiply_impl - } - #[inline] fn square(&mut self) { diff --git a/ff/src/lib.rs b/ff/src/lib.rs index b50cbd5..71a5870 100644 --- a/ff/src/lib.rs +++ b/ff/src/lib.rs @@ -11,10 +11,31 @@ use rand_core::RngCore; use std::error::Error; use std::fmt; use std::io::{self, Read, Write}; +use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; /// This trait represents an element of a field. pub trait Field: - Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static + Sized + + Eq + + Copy + + Clone + + Send + + Sync + + fmt::Debug + + fmt::Display + + 'static + + Add + + Sub + + Mul + + for<'a> Add<&'a Self, Output = Self> + + for<'a> Mul<&'a Self, Output = Self> + + for<'a> Sub<&'a Self, Output = Self> + + MulAssign + + AddAssign + + SubAssign + + for<'a> MulAssign<&'a Self> + + for<'a> AddAssign<&'a Self> + + for<'a> SubAssign<&'a Self> { /// Returns an element chosen uniformly at random using a user-provided RNG. fn random(rng: &mut R) -> Self; @@ -37,15 +58,6 @@ pub trait Field: /// Negates this element. fn negate(&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); - - /// Multiplies another element by this element. - fn mul_assign(&mut self, other: &Self); - /// Computes the multiplicative inverse of this element, if nonzero. fn inverse(&self) -> Option; diff --git a/pairing/benches/bls12_381/fq.rs b/pairing/benches/bls12_381/fq.rs index b663322..3ed810a 100644 --- a/pairing/benches/bls12_381/fq.rs +++ b/pairing/benches/bls12_381/fq.rs @@ -1,5 +1,6 @@ use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; +use std::ops::{AddAssign, MulAssign, SubAssign}; use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; use pairing::bls12_381::*; diff --git a/pairing/benches/bls12_381/fq12.rs b/pairing/benches/bls12_381/fq12.rs index 8bf0392..0eab387 100644 --- a/pairing/benches/bls12_381/fq12.rs +++ b/pairing/benches/bls12_381/fq12.rs @@ -1,5 +1,6 @@ use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; +use std::ops::{AddAssign, MulAssign, SubAssign}; use ff::Field; use pairing::bls12_381::*; diff --git a/pairing/benches/bls12_381/fq2.rs b/pairing/benches/bls12_381/fq2.rs index 028c42e..7862ea3 100644 --- a/pairing/benches/bls12_381/fq2.rs +++ b/pairing/benches/bls12_381/fq2.rs @@ -1,5 +1,6 @@ use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; +use std::ops::{AddAssign, MulAssign, SubAssign}; use ff::{Field, SqrtField}; use pairing::bls12_381::*; diff --git a/pairing/benches/bls12_381/fr.rs b/pairing/benches/bls12_381/fr.rs index 9e767d8..5905431 100644 --- a/pairing/benches/bls12_381/fr.rs +++ b/pairing/benches/bls12_381/fr.rs @@ -1,5 +1,6 @@ use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; +use std::ops::{AddAssign, MulAssign, SubAssign}; use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; use pairing::bls12_381::*; diff --git a/pairing/src/bls12_381/ec.rs b/pairing/src/bls12_381/ec.rs index 6bebc24..1d740b3 100644 --- a/pairing/src/bls12_381/ec.rs +++ b/pairing/src/bls12_381/ec.rs @@ -627,6 +627,7 @@ pub mod g1 { use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; use rand_core::RngCore; use std::fmt; + use std::ops::{AddAssign, MulAssign, SubAssign}; curve_impl!( "G1", @@ -1296,6 +1297,7 @@ pub mod g2 { use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; use rand_core::RngCore; use std::fmt; + use std::ops::{AddAssign, MulAssign, SubAssign}; curve_impl!( "G2", diff --git a/pairing/src/bls12_381/fq.rs b/pairing/src/bls12_381/fq.rs index 08135e3..ce76b54 100644 --- a/pairing/src/bls12_381/fq.rs +++ b/pairing/src/bls12_381/fq.rs @@ -1,5 +1,6 @@ use super::fq2::Fq2; use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; +use std::ops::{AddAssign, MulAssign, SubAssign}; // B coefficient of BLS12-381 curve, 4. pub const B_COEFF: Fq = Fq(FqRepr([ diff --git a/pairing/src/bls12_381/fq12.rs b/pairing/src/bls12_381/fq12.rs index 0d6e066..96b452d 100644 --- a/pairing/src/bls12_381/fq12.rs +++ b/pairing/src/bls12_381/fq12.rs @@ -3,6 +3,7 @@ use super::fq2::Fq2; use super::fq6::Fq6; use ff::Field; use rand_core::RngCore; +use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; /// An element of Fq12, represented by c0 + c1 * w. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -39,6 +40,112 @@ impl Fq12 { } } +impl<'r> Add<&'r Fq12> for Fq12 { + type Output = Self; + + fn add(self, other: &Self) -> Self { + Fq12 { + c0: self.c0 + other.c0, + c1: self.c1 + other.c1, + } + } +} + +impl Add for Fq12 { + type Output = Self; + + fn add(self, other: Self) -> Self { + self + &other + } +} + +impl<'r> AddAssign<&'r Fq12> for Fq12 { + fn add_assign(&mut self, other: &'r Self) { + self.c0.add_assign(&other.c0); + self.c1.add_assign(&other.c1); + } +} + +impl AddAssign for Fq12 { + fn add_assign(&mut self, other: Self) { + self.add_assign(&other); + } +} + +impl<'r> Sub<&'r Fq12> for Fq12 { + type Output = Self; + + fn sub(self, other: &Self) -> Self { + Fq12 { + c0: self.c0 - other.c0, + c1: self.c1 - other.c1, + } + } +} + +impl Sub for Fq12 { + type Output = Self; + + fn sub(self, other: Self) -> Self { + self - &other + } +} + +impl<'r> SubAssign<&'r Fq12> for Fq12 { + fn sub_assign(&mut self, other: &'r Self) { + self.c0.sub_assign(&other.c0); + self.c1.sub_assign(&other.c1); + } +} + +impl SubAssign for Fq12 { + fn sub_assign(&mut self, other: Self) { + self.sub_assign(&other); + } +} + +impl<'r> Mul<&'r Fq12> for Fq12 { + type Output = Self; + + fn mul(self, other: &Self) -> Self { + let mut ret = self; + ret.mul_assign(other); + ret + } +} + +impl Mul for Fq12 { + type Output = Self; + + fn mul(self, other: Self) -> Self { + self * &other + } +} + +impl<'r> MulAssign<&'r Fq12> for Fq12 { + fn mul_assign(&mut self, other: &Self) { + let mut aa = self.c0; + aa.mul_assign(&other.c0); + let mut bb = self.c1; + bb.mul_assign(&other.c1); + let mut o = other.c0; + o.add_assign(&other.c1); + self.c1.add_assign(&self.c0); + self.c1.mul_assign(&o); + self.c1.sub_assign(&aa); + self.c1.sub_assign(&bb); + self.c0 = bb; + self.c0.mul_by_nonresidue(); + self.c0.add_assign(&aa); + } +} + +impl MulAssign for Fq12 { + fn mul_assign(&mut self, other: Self) { + self.mul_assign(&other); + } +} + impl Field for Fq12 { fn random(rng: &mut R) -> Self { Fq12 { @@ -75,16 +182,6 @@ impl Field for Fq12 { self.c1.negate(); } - fn add_assign(&mut self, other: &Self) { - self.c0.add_assign(&other.c0); - self.c1.add_assign(&other.c1); - } - - fn sub_assign(&mut self, other: &Self) { - self.c0.sub_assign(&other.c0); - self.c1.sub_assign(&other.c1); - } - fn frobenius_map(&mut self, power: usize) { self.c0.frobenius_map(power); self.c1.frobenius_map(power); @@ -111,22 +208,6 @@ impl Field for Fq12 { self.c0 = c0; } - fn mul_assign(&mut self, other: &Self) { - let mut aa = self.c0; - aa.mul_assign(&other.c0); - let mut bb = self.c1; - bb.mul_assign(&other.c1); - let mut o = other.c0; - o.add_assign(&other.c1); - self.c1.add_assign(&self.c0); - self.c1.mul_assign(&o); - self.c1.sub_assign(&aa); - self.c1.sub_assign(&bb); - self.c0 = bb; - self.c0.mul_by_nonresidue(); - self.c0.add_assign(&aa); - } - fn inverse(&self) -> Option { let mut c0s = self.c0; c0s.square(); diff --git a/pairing/src/bls12_381/fq2.rs b/pairing/src/bls12_381/fq2.rs index c115dd2..6997072 100644 --- a/pairing/src/bls12_381/fq2.rs +++ b/pairing/src/bls12_381/fq2.rs @@ -1,8 +1,8 @@ use super::fq::{Fq, FROBENIUS_COEFF_FQ2_C1, NEGATIVE_ONE}; use ff::{Field, SqrtField}; use rand_core::RngCore; - use std::cmp::Ordering; +use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; /// An element of Fq2, represented by c0 + c1 * u. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -56,6 +56,111 @@ impl Fq2 { } } +impl<'r> Add<&'r Fq2> for Fq2 { + type Output = Self; + + fn add(self, other: &Self) -> Self { + Fq2 { + c0: self.c0 + other.c0, + c1: self.c1 + other.c1, + } + } +} + +impl Add for Fq2 { + type Output = Self; + + fn add(self, other: Self) -> Self { + self + &other + } +} + +impl<'r> AddAssign<&'r Fq2> for Fq2 { + fn add_assign(&mut self, other: &'r Self) { + self.c0.add_assign(&other.c0); + self.c1.add_assign(&other.c1); + } +} + +impl AddAssign for Fq2 { + fn add_assign(&mut self, other: Self) { + self.add_assign(&other); + } +} + +impl<'r> Sub<&'r Fq2> for Fq2 { + type Output = Self; + + fn sub(self, other: &Self) -> Self { + Fq2 { + c0: self.c0 - other.c0, + c1: self.c1 - other.c1, + } + } +} + +impl Sub for Fq2 { + type Output = Self; + + fn sub(self, other: Self) -> Self { + self - &other + } +} + +impl<'r> SubAssign<&'r Fq2> for Fq2 { + fn sub_assign(&mut self, other: &'r Self) { + self.c0.sub_assign(&other.c0); + self.c1.sub_assign(&other.c1); + } +} + +impl SubAssign for Fq2 { + fn sub_assign(&mut self, other: Self) { + self.sub_assign(&other); + } +} + +impl<'r> Mul<&'r Fq2> for Fq2 { + type Output = Self; + + fn mul(self, other: &Self) -> Self { + let mut ret = self; + ret.mul_assign(other); + ret + } +} + +impl Mul for Fq2 { + type Output = Self; + + fn mul(self, other: Self) -> Self { + self * &other + } +} + +impl<'r> MulAssign<&'r Fq2> for Fq2 { + fn mul_assign(&mut self, other: &Self) { + let mut aa = self.c0; + aa.mul_assign(&other.c0); + let mut bb = self.c1; + bb.mul_assign(&other.c1); + let mut o = other.c0; + o.add_assign(&other.c1); + self.c1.add_assign(&self.c0); + self.c1.mul_assign(&o); + self.c1.sub_assign(&aa); + self.c1.sub_assign(&bb); + self.c0 = aa; + self.c0.sub_assign(&bb); + } +} + +impl MulAssign for Fq2 { + fn mul_assign(&mut self, other: Self) { + self.mul_assign(&other); + } +} + impl Field for Fq2 { fn random(rng: &mut R) -> Self { Fq2 { @@ -108,31 +213,6 @@ impl Field for Fq2 { self.c1.negate(); } - fn add_assign(&mut self, other: &Self) { - self.c0.add_assign(&other.c0); - self.c1.add_assign(&other.c1); - } - - fn sub_assign(&mut self, other: &Self) { - self.c0.sub_assign(&other.c0); - self.c1.sub_assign(&other.c1); - } - - fn mul_assign(&mut self, other: &Self) { - let mut aa = self.c0; - aa.mul_assign(&other.c0); - let mut bb = self.c1; - bb.mul_assign(&other.c1); - let mut o = other.c0; - o.add_assign(&other.c1); - self.c1.add_assign(&self.c0); - self.c1.mul_assign(&o); - self.c1.sub_assign(&aa); - self.c1.sub_assign(&bb); - self.c0 = aa; - self.c0.sub_assign(&bb); - } - fn inverse(&self) -> Option { let mut t1 = self.c1; t1.square(); diff --git a/pairing/src/bls12_381/fq6.rs b/pairing/src/bls12_381/fq6.rs index e2b49c9..444119a 100644 --- a/pairing/src/bls12_381/fq6.rs +++ b/pairing/src/bls12_381/fq6.rs @@ -2,6 +2,7 @@ use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2}; use super::fq2::Fq2; use ff::Field; use rand_core::RngCore; +use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; /// An element of Fq6, represented by c0 + c1 * v + c2 * v^(2). #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -99,101 +100,93 @@ impl Fq6 { } } -impl Field for Fq6 { - fn random(rng: &mut R) -> Self { +impl<'r> Add<&'r Fq6> for Fq6 { + type Output = Self; + + fn add(self, other: &Self) -> Self { Fq6 { - c0: Fq2::random(rng), - c1: Fq2::random(rng), - c2: Fq2::random(rng), + c0: self.c0 + other.c0, + c1: self.c1 + other.c1, + c2: self.c2 + other.c2, } } +} - fn zero() -> Self { - Fq6 { - c0: Fq2::zero(), - c1: Fq2::zero(), - c2: Fq2::zero(), - } +impl Add for Fq6 { + type Output = Self; + + fn add(self, other: Self) -> Self { + self + &other } +} - fn one() -> Self { - Fq6 { - c0: Fq2::one(), - c1: Fq2::zero(), - c2: Fq2::zero(), - } - } - - fn is_zero(&self) -> bool { - self.c0.is_zero() && self.c1.is_zero() && self.c2.is_zero() - } - - fn double(&mut self) { - self.c0.double(); - self.c1.double(); - self.c2.double(); - } - - fn negate(&mut self) { - self.c0.negate(); - self.c1.negate(); - self.c2.negate(); - } - - fn add_assign(&mut self, other: &Self) { +impl<'r> AddAssign<&'r Fq6> for Fq6 { + fn add_assign(&mut self, other: &'r Self) { self.c0.add_assign(&other.c0); self.c1.add_assign(&other.c1); self.c2.add_assign(&other.c2); } +} - fn sub_assign(&mut self, other: &Self) { +impl AddAssign for Fq6 { + fn add_assign(&mut self, other: Self) { + self.add_assign(&other); + } +} + +impl<'r> Sub<&'r Fq6> for Fq6 { + type Output = Self; + + fn sub(self, other: &Self) -> Self { + Fq6 { + c0: self.c0 - other.c0, + c1: self.c1 - other.c1, + c2: self.c2 - other.c2, + } + } +} + +impl Sub for Fq6 { + type Output = Self; + + fn sub(self, other: Self) -> Self { + self - &other + } +} + +impl<'r> SubAssign<&'r Fq6> for Fq6 { + fn sub_assign(&mut self, other: &'r Self) { self.c0.sub_assign(&other.c0); self.c1.sub_assign(&other.c1); self.c2.sub_assign(&other.c2); } +} - fn frobenius_map(&mut self, power: usize) { - self.c0.frobenius_map(power); - self.c1.frobenius_map(power); - self.c2.frobenius_map(power); - - self.c1.mul_assign(&FROBENIUS_COEFF_FQ6_C1[power % 6]); - self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]); +impl SubAssign for Fq6 { + fn sub_assign(&mut self, other: Self) { + self.sub_assign(&other); } +} - fn square(&mut self) { - let mut s0 = self.c0; - s0.square(); - let mut ab = self.c0; - ab.mul_assign(&self.c1); - let mut s1 = ab; - s1.double(); - let mut s2 = self.c0; - s2.sub_assign(&self.c1); - s2.add_assign(&self.c2); - s2.square(); - let mut bc = self.c1; - bc.mul_assign(&self.c2); - let mut s3 = bc; - s3.double(); - let mut s4 = self.c2; - s4.square(); +impl<'r> Mul<&'r Fq6> for Fq6 { + type Output = Self; - self.c0 = s3; - self.c0.mul_by_nonresidue(); - self.c0.add_assign(&s0); - - self.c1 = s4; - self.c1.mul_by_nonresidue(); - self.c1.add_assign(&s1); - - self.c2 = s1; - self.c2.add_assign(&s2); - self.c2.add_assign(&s3); - self.c2.sub_assign(&s0); - self.c2.sub_assign(&s4); + fn mul(self, other: &Self) -> Self { + let mut ret = self; + ret.mul_assign(other); + ret } +} +impl Mul for Fq6 { + type Output = Self; + + fn mul(self, other: Self) -> Self { + self * &other + } +} + +impl<'r> MulAssign<&'r Fq6> for Fq6 { fn mul_assign(&mut self, other: &Self) { let mut a_a = self.c0; let mut b_b = self.c1; @@ -244,6 +237,96 @@ impl Field for Fq6 { self.c1 = t2; self.c2 = t3; } +} + +impl MulAssign for Fq6 { + fn mul_assign(&mut self, other: Self) { + self.mul_assign(&other); + } +} + +impl Field for Fq6 { + fn random(rng: &mut R) -> Self { + Fq6 { + c0: Fq2::random(rng), + c1: Fq2::random(rng), + c2: Fq2::random(rng), + } + } + + fn zero() -> Self { + Fq6 { + c0: Fq2::zero(), + c1: Fq2::zero(), + c2: Fq2::zero(), + } + } + + fn one() -> Self { + Fq6 { + c0: Fq2::one(), + c1: Fq2::zero(), + c2: Fq2::zero(), + } + } + + fn is_zero(&self) -> bool { + self.c0.is_zero() && self.c1.is_zero() && self.c2.is_zero() + } + + fn double(&mut self) { + self.c0.double(); + self.c1.double(); + self.c2.double(); + } + + fn negate(&mut self) { + self.c0.negate(); + self.c1.negate(); + self.c2.negate(); + } + + fn frobenius_map(&mut self, power: usize) { + self.c0.frobenius_map(power); + self.c1.frobenius_map(power); + self.c2.frobenius_map(power); + + self.c1.mul_assign(&FROBENIUS_COEFF_FQ6_C1[power % 6]); + self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]); + } + + fn square(&mut self) { + let mut s0 = self.c0; + s0.square(); + let mut ab = self.c0; + ab.mul_assign(&self.c1); + let mut s1 = ab; + s1.double(); + let mut s2 = self.c0; + s2.sub_assign(&self.c1); + s2.add_assign(&self.c2); + s2.square(); + let mut bc = self.c1; + bc.mul_assign(&self.c2); + let mut s3 = bc; + s3.double(); + let mut s4 = self.c2; + s4.square(); + + self.c0 = s3; + self.c0.mul_by_nonresidue(); + self.c0.add_assign(&s0); + + self.c1 = s4; + self.c1.mul_by_nonresidue(); + self.c1.add_assign(&s1); + + self.c2 = s1; + self.c2.add_assign(&s2); + self.c2.add_assign(&s3); + self.c2.sub_assign(&s0); + self.c2.sub_assign(&s4); + } fn inverse(&self) -> Option { let mut c0 = self.c2; diff --git a/pairing/src/bls12_381/fr.rs b/pairing/src/bls12_381/fr.rs index 76f3ffe..ca9cd57 100644 --- a/pairing/src/bls12_381/fr.rs +++ b/pairing/src/bls12_381/fr.rs @@ -1,4 +1,5 @@ use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; +use std::ops::{AddAssign, MulAssign, SubAssign}; #[derive(PrimeField)] #[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"] diff --git a/pairing/src/bls12_381/mod.rs b/pairing/src/bls12_381/mod.rs index e6e88dd..04fd5ee 100644 --- a/pairing/src/bls12_381/mod.rs +++ b/pairing/src/bls12_381/mod.rs @@ -25,6 +25,7 @@ use super::{Engine, PairingCurveAffine}; use ff::{BitIterator, Field, ScalarEngine}; use group::CurveAffine; +use std::ops::{AddAssign, MulAssign, SubAssign}; // The BLS parameter x for BLS12-381 is -0xd201000000010000 const BLS_X: u64 = 0xd201000000010000; diff --git a/pairing/src/tests/engine.rs b/pairing/src/tests/engine.rs index b6ae50e..6b6a430 100644 --- a/pairing/src/tests/engine.rs +++ b/pairing/src/tests/engine.rs @@ -1,6 +1,7 @@ use group::{CurveAffine, CurveProjective}; use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; +use std::ops::MulAssign; use crate::{Engine, Field, PairingCurveAffine, PrimeField}; diff --git a/zcash_primitives/src/jubjub/edwards.rs b/zcash_primitives/src/jubjub/edwards.rs index 9902d80..2865ce3 100644 --- a/zcash_primitives/src/jubjub/edwards.rs +++ b/zcash_primitives/src/jubjub/edwards.rs @@ -1,4 +1,5 @@ use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; +use std::ops::{AddAssign, MulAssign, SubAssign}; use super::{montgomery, JubjubEngine, JubjubParams, PrimeOrder, Unknown}; diff --git a/zcash_primitives/src/jubjub/fs.rs b/zcash_primitives/src/jubjub/fs.rs index 7cf4d79..ddd2bce 100644 --- a/zcash_primitives/src/jubjub/fs.rs +++ b/zcash_primitives/src/jubjub/fs.rs @@ -5,6 +5,7 @@ use ff::{ PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField, }; use rand_core::RngCore; +use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; use super::ToUniform; @@ -268,6 +269,141 @@ impl From for FsRepr { } } +impl<'r> Add<&'r Fs> for Fs { + type Output = Self; + + #[inline] + fn add(self, other: &Self) -> Self { + let mut ret = self; + ret.add_assign(other); + ret + } +} + +impl Add for Fs { + type Output = Self; + + #[inline] + fn add(self, other: Self) -> Self { + self + &other + } +} + +impl<'r> AddAssign<&'r Fs> for Fs { + #[inline] + fn add_assign(&mut self, other: &Self) { + // This cannot exceed the backing capacity. + self.0.add_nocarry(&other.0); + + // However, it may need to be reduced. + self.reduce(); + } +} + +impl AddAssign for Fs { + #[inline] + fn add_assign(&mut self, other: Self) { + self.add_assign(&other); + } +} + +impl<'r> Sub<&'r Fs> for Fs { + type Output = Self; + + #[inline] + fn sub(self, other: &Self) -> Self { + let mut ret = self; + ret.sub_assign(other); + ret + } +} + +impl Sub for Fs { + type Output = Self; + + #[inline] + fn sub(self, other: Self) -> Self { + self - &other + } +} + +impl<'r> SubAssign<&'r Fs> for Fs { + #[inline] + fn sub_assign(&mut self, other: &Self) { + // If `other` is larger than `self`, we'll need to add the modulus to self first. + if other.0 > self.0 { + self.0.add_nocarry(&MODULUS); + } + + self.0.sub_noborrow(&other.0); + } +} + +impl SubAssign for Fs { + #[inline] + fn sub_assign(&mut self, other: Self) { + self.sub_assign(&other); + } +} + +impl<'r> Mul<&'r Fs> for Fs { + type Output = Self; + + #[inline] + fn mul(self, other: &Self) -> Self { + let mut ret = self; + ret.mul_assign(other); + ret + } +} + +impl Mul for Fs { + type Output = Self; + + #[inline] + fn mul(self, other: Self) -> Self { + self * &other + } +} + +impl<'r> MulAssign<&'r Fs> for Fs { + #[inline] + fn mul_assign(&mut self, other: &Self) { + let mut carry = 0; + let r0 = mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); + let r1 = mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); + let r2 = mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); + let r3 = mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); + let r4 = carry; + let mut carry = 0; + let r1 = mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); + let r2 = mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); + let r3 = mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); + let r4 = mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); + let r5 = carry; + let mut carry = 0; + let r2 = mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); + let r3 = mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); + let r4 = mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); + let r5 = mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); + let r6 = carry; + let mut carry = 0; + let r3 = mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); + let r4 = mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); + let r5 = mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); + let r6 = mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry); + let r7 = carry; + self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7); + } +} + +impl MulAssign for Fs { + #[inline] + fn mul_assign(&mut self, other: Self) { + self.mul_assign(&other); + } +} + impl PrimeField for Fs { type Repr = FsRepr; @@ -351,15 +487,6 @@ impl Field for Fs { self.0.is_zero() } - #[inline] - fn add_assign(&mut self, other: &Fs) { - // This cannot exceed the backing capacity. - self.0.add_nocarry(&other.0); - - // However, it may need to be reduced. - self.reduce(); - } - #[inline] fn double(&mut self) { // This cannot exceed the backing capacity. @@ -369,16 +496,6 @@ impl Field for Fs { self.reduce(); } - #[inline] - fn sub_assign(&mut self, other: &Fs) { - // If `other` is larger than `self`, we'll need to add the modulus to self first. - if other.0 > self.0 { - self.0.add_nocarry(&MODULUS); - } - - self.0.sub_noborrow(&other.0); - } - #[inline] fn negate(&mut self) { if !self.is_zero() { @@ -448,35 +565,6 @@ impl Field for Fs { // This has no effect in a prime field. } - #[inline] - fn mul_assign(&mut self, other: &Fs) { - let mut carry = 0; - let r0 = mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); - let r1 = mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); - let r2 = mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); - let r3 = mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); - let r4 = carry; - let mut carry = 0; - let r1 = mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); - let r2 = mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); - let r3 = mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); - let r4 = mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); - let r5 = carry; - let mut carry = 0; - let r2 = mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); - let r3 = mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); - let r4 = mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); - let r5 = mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); - let r6 = carry; - let mut carry = 0; - let r3 = mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); - let r4 = mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); - let r5 = mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); - let r6 = mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry); - let r7 = carry; - self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7); - } - #[inline] fn square(&mut self) { let mut carry = 0; diff --git a/zcash_primitives/src/jubjub/montgomery.rs b/zcash_primitives/src/jubjub/montgomery.rs index 4e6c5e1..fc41274 100644 --- a/zcash_primitives/src/jubjub/montgomery.rs +++ b/zcash_primitives/src/jubjub/montgomery.rs @@ -1,4 +1,5 @@ use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; +use std::ops::{AddAssign, MulAssign, SubAssign}; use super::{edwards, JubjubEngine, JubjubParams, PrimeOrder, Unknown}; diff --git a/zcash_primitives/src/jubjub/tests.rs b/zcash_primitives/src/jubjub/tests.rs index b2c12ae..56fad56 100644 --- a/zcash_primitives/src/jubjub/tests.rs +++ b/zcash_primitives/src/jubjub/tests.rs @@ -1,6 +1,7 @@ use super::{edwards, montgomery, JubjubEngine, JubjubParams, PrimeOrder}; use ff::{Field, LegendreSymbol, PrimeField, PrimeFieldRepr, SqrtField}; +use std::ops::{AddAssign, MulAssign, SubAssign}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; diff --git a/zcash_primitives/src/pedersen_hash.rs b/zcash_primitives/src/pedersen_hash.rs index 000d76b..5fb7333 100644 --- a/zcash_primitives/src/pedersen_hash.rs +++ b/zcash_primitives/src/pedersen_hash.rs @@ -2,6 +2,7 @@ use crate::jubjub::*; use ff::{Field, PrimeField, PrimeFieldRepr}; +use std::ops::AddAssign; #[derive(Copy, Clone)] pub enum Personalization { diff --git a/zcash_primitives/src/redjubjub.rs b/zcash_primitives/src/redjubjub.rs index 187ebd3..6158685 100644 --- a/zcash_primitives/src/redjubjub.rs +++ b/zcash_primitives/src/redjubjub.rs @@ -7,6 +7,7 @@ use crate::jubjub::{edwards::Point, FixedGenerators, JubjubEngine, JubjubParams, use ff::{Field, PrimeField, PrimeFieldRepr}; use rand_core::RngCore; use std::io::{self, Read, Write}; +use std::ops::{AddAssign, MulAssign}; use crate::util::hash_to_scalar; diff --git a/zcash_primitives/src/zip32.rs b/zcash_primitives/src/zip32.rs index f346625..e34767b 100644 --- a/zcash_primitives/src/zip32.rs +++ b/zcash_primitives/src/zip32.rs @@ -5,9 +5,9 @@ use aes::Aes256; use blake2b_simd::Params as Blake2bParams; use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt}; -use ff::Field; use fpe::ff1::{BinaryNumeralString, FF1}; use pairing::bls12_381::Bls12; +use std::ops::AddAssign; use crate::{ jubjub::{fs::Fs, FixedGenerators, JubjubEngine, JubjubParams, ToUniform}, diff --git a/zcash_proofs/src/circuit/ecc.rs b/zcash_proofs/src/circuit/ecc.rs index 851f0e5..a35dfd7 100644 --- a/zcash_proofs/src/circuit/ecc.rs +++ b/zcash_proofs/src/circuit/ecc.rs @@ -2,6 +2,7 @@ use ff::Field; use pairing::Engine; +use std::ops::{AddAssign, MulAssign, SubAssign}; use bellman::{ConstraintSystem, SynthesisError}; @@ -668,6 +669,7 @@ mod test { use pairing::bls12_381::{Bls12, Fr}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; + use std::ops::SubAssign; use bellman::gadgets::test::*; use zcash_primitives::jubjub::fs::Fs; diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index 8067069..e695ba1 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -5,6 +5,7 @@ use bellman::{ use ff::Field; use pairing::bls12_381::{Bls12, Fr}; use rand_core::OsRng; +use std::ops::AddAssign; use zcash_primitives::{ jubjub::{edwards, fs::Fs, FixedGenerators, JubjubBls12, Unknown}, primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment},