From 91c32f1c7c5ff0690ef899d3979f56e69a3a613e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 12 Dec 2019 22:52:17 +0000 Subject: [PATCH 1/4] Move from Field::negate to Neg operator --- bellman/src/gadgets/lookup.rs | 9 ++--- bellman/src/gadgets/num.rs | 5 +-- bellman/src/gadgets/test/mod.rs | 8 +--- bellman/src/groth16/tests/dummy_engine.rs | 23 ++++++----- bellman/src/lib.rs | 8 ++-- ff/ff_derive/src/lib.rs | 24 +++++++----- ff/src/lib.rs | 6 +-- group/src/tests/mod.rs | 4 +- pairing/benches/bls12_381/fq.rs | 7 ++-- pairing/benches/bls12_381/fr.rs | 7 ++-- pairing/src/bls12_381/ec.rs | 23 +++++------ pairing/src/bls12_381/fq.rs | 20 +++++----- pairing/src/bls12_381/fq12.rs | 30 ++++++++------- pairing/src/bls12_381/fq2.rs | 47 ++++++++++------------- pairing/src/bls12_381/fq6.rs | 22 +++++++---- pairing/src/bls12_381/fr.rs | 13 +++---- pairing/src/bls12_381/mod.rs | 6 +-- pairing/src/tests/field.rs | 11 ++---- zcash_primitives/src/jubjub/edwards.rs | 16 +++----- zcash_primitives/src/jubjub/fs.rs | 39 ++++++++++--------- zcash_primitives/src/jubjub/montgomery.rs | 10 ++--- zcash_primitives/src/jubjub/tests.rs | 7 ++-- zcash_primitives/src/pedersen_hash.rs | 4 +- zcash_primitives/src/redjubjub.rs | 4 +- zcash_proofs/src/circuit/ecc.rs | 6 +-- zcash_proofs/src/sapling/prover.rs | 5 +-- 26 files changed, 175 insertions(+), 189 deletions(-) diff --git a/bellman/src/gadgets/lookup.rs b/bellman/src/gadgets/lookup.rs index 3be3ed9..bde86e2 100644 --- a/bellman/src/gadgets/lookup.rs +++ b/bellman/src/gadgets/lookup.rs @@ -1,7 +1,7 @@ //! Window table lookup gadgets. use ff::{Field, ScalarEngine}; -use std::ops::AddAssign; +use std::ops::{AddAssign, Neg}; use super::boolean::Boolean; use super::num::{AllocatedNum, Num}; @@ -16,8 +16,7 @@ where assert_eq!(assignment.len(), 1 << window_size); for (i, constant) in constants.into_iter().enumerate() { - let mut cur = assignment[i]; - cur.negate(); + let mut cur = assignment[i].neg(); cur.add_assign(constant); assignment[i] = cur; for (j, eval) in assignment.iter_mut().enumerate().skip(i + 1) { @@ -151,7 +150,7 @@ where let y = AllocatedNum::alloc(cs.namespace(|| "y"), || { let mut tmp = coords[*i.get()?].1; if *bits[2].get_value().get()? { - tmp.negate(); + tmp = tmp.neg(); } Ok(tmp) })?; @@ -281,7 +280,7 @@ mod test { assert_eq!(res.0.get_value().unwrap(), points[index].0); let mut tmp = points[index].1; if c_val { - tmp.negate() + tmp = tmp.neg() } assert_eq!(res.1.get_value().unwrap(), tmp); } diff --git a/bellman/src/gadgets/num.rs b/bellman/src/gadgets/num.rs index da3e4a0..bce55ce 100644 --- a/bellman/src/gadgets/num.rs +++ b/bellman/src/gadgets/num.rs @@ -417,7 +417,7 @@ mod test { use pairing::bls12_381::{Bls12, Fr}; use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; - use std::ops::SubAssign; + use std::ops::{Neg, SubAssign}; use super::{AllocatedNum, Boolean}; use crate::gadgets::test::*; @@ -519,8 +519,7 @@ mod test { #[test] fn test_into_bits_strict() { - let mut negone = Fr::one(); - negone.negate(); + let negone = Fr::one().neg(); let mut cs = TestConstraintSystem::::new(); diff --git a/bellman/src/gadgets/test/mod.rs b/bellman/src/gadgets/test/mod.rs index f0668b4..f4cc927 100644 --- a/bellman/src/gadgets/test/mod.rs +++ b/bellman/src/gadgets/test/mod.rs @@ -6,7 +6,7 @@ use crate::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable use std::collections::HashMap; use std::fmt::Write; -use std::ops::{AddAssign, MulAssign}; +use std::ops::{AddAssign, MulAssign, Neg}; use byteorder::{BigEndian, ByteOrder}; use std::cmp::Ordering; @@ -152,11 +152,7 @@ impl TestConstraintSystem { pub fn pretty_print(&self) -> String { let mut s = String::new(); - let negone = { - let mut tmp = E::Fr::one(); - tmp.negate(); - tmp - }; + let negone = E::Fr::one().neg(); let powers_of_two = (0..E::Fr::NUM_BITS) .map(|i| E::Fr::from_str("2").unwrap().pow(&[u64::from(i)])) diff --git a/bellman/src/groth16/tests/dummy_engine.rs b/bellman/src/groth16/tests/dummy_engine.rs index 325c198..46641b3 100644 --- a/bellman/src/groth16/tests/dummy_engine.rs +++ b/bellman/src/groth16/tests/dummy_engine.rs @@ -9,7 +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}; +use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; const MODULUS_R: Wrapping = Wrapping(64513); @@ -22,6 +22,17 @@ impl fmt::Display for Fr { } } +impl Neg for Fr { + type Output = Self; + + fn neg(mut self) -> Self { + if !::is_zero(&self) { + self.0 = MODULUS_R - self.0; + } + self + } +} + impl<'r> Add<&'r Fr> for Fr { type Output = Self; @@ -137,12 +148,6 @@ impl Field for Fr { self.0 = (self.0 << 1) % MODULUS_R; } - fn negate(&mut self) { - if !::is_zero(self) { - self.0 = MODULUS_R - self.0; - } - } - fn inverse(&self) -> Option { if ::is_zero(self) { None @@ -413,7 +418,7 @@ impl CurveProjective for Fr { } fn negate(&mut self) { - ::negate(self); + self.0 = self.neg().0; } fn mul_assign::Repr>>(&mut self, other: S) { @@ -495,7 +500,7 @@ impl CurveAffine for Fr { } fn negate(&mut self) { - ::negate(self); + self.0 = self.neg().0; } fn mul::Repr>>(&self, other: S) -> Self::Projective { diff --git a/bellman/src/lib.rs b/bellman/src/lib.rs index 3877c3f..1e48b0c 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, MulAssign, Sub}; +use std::ops::{Add, MulAssign, Neg, Sub}; /// Computations are expressed in terms of arithmetic circuits, in particular /// rank-1 quadratic constraint systems. The `Circuit` trait represents a @@ -216,10 +216,8 @@ impl Sub<(E::Fr, Variable)> for LinearCombination { type Output = LinearCombination; #[allow(clippy::suspicious_arithmetic_impl)] - fn sub(self, (mut coeff, var): (E::Fr, Variable)) -> LinearCombination { - coeff.negate(); - - self + (coeff, var) + fn sub(self, (coeff, var): (E::Fr, Variable)) -> LinearCombination { + self + (coeff.neg(), var) } } diff --git a/ff/ff_derive/src/lib.rs b/ff/ff_derive/src/lib.rs index b230e7f..0e804c7 100644 --- a/ff/ff_derive/src/lib.rs +++ b/ff/ff_derive/src/lib.rs @@ -833,6 +833,21 @@ fn prime_field_impl( } } + impl ::std::ops::Neg for #name { + type Output = #name; + + #[inline] + fn neg(self) -> #name { + let mut ret = self; + if !ret.is_zero() { + let mut tmp = MODULUS; + tmp.sub_noborrow(&ret.0); + ret.0 = tmp; + } + ret + } + } + impl<'r> ::std::ops::Add<&'r #name> for #name { type Output = #name; @@ -1033,15 +1048,6 @@ fn prime_field_impl( self.reduce(); } - #[inline] - fn negate(&mut self) { - if !self.is_zero() { - let mut tmp = MODULUS; - tmp.sub_noborrow(&self.0); - self.0 = tmp; - } - } - fn inverse(&self) -> Option { if self.is_zero() { None diff --git a/ff/src/lib.rs b/ff/src/lib.rs index 71a5870..c605f64 100644 --- a/ff/src/lib.rs +++ b/ff/src/lib.rs @@ -11,7 +11,7 @@ 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}; +use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// This trait represents an element of a field. pub trait Field: @@ -27,6 +27,7 @@ pub trait Field: + Add + Sub + Mul + + Neg + for<'a> Add<&'a Self, Output = Self> + for<'a> Mul<&'a Self, Output = Self> + for<'a> Sub<&'a Self, Output = Self> @@ -55,9 +56,6 @@ pub trait Field: /// Doubles this element. fn double(&mut self); - /// Negates this element. - fn negate(&mut self); - /// Computes the multiplicative inverse of this element, if nonzero. fn inverse(&self) -> Option; diff --git a/group/src/tests/mod.rs b/group/src/tests/mod.rs index 1970667..949d934 100644 --- a/group/src/tests/mod.rs +++ b/group/src/tests/mod.rs @@ -1,6 +1,7 @@ use ff::{Field, PrimeField}; use rand::SeedableRng; use rand_xorshift::XorShiftRng; +use std::ops::Neg; use crate::{CurveAffine, CurveProjective, EncodedPoint}; @@ -199,8 +200,7 @@ fn random_negation_tests() { let r = G::random(&mut rng); let s = G::Scalar::random(&mut rng); - let mut sneg = s; - sneg.negate(); + let sneg = s.neg(); let mut t1 = r; t1.mul_assign(s); diff --git a/pairing/benches/bls12_381/fq.rs b/pairing/benches/bls12_381/fq.rs index 3ed810a..046491e 100644 --- a/pairing/benches/bls12_381/fq.rs +++ b/pairing/benches/bls12_381/fq.rs @@ -1,6 +1,6 @@ use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; -use std::ops::{AddAssign, MulAssign, SubAssign}; +use std::ops::{AddAssign, MulAssign, Neg, SubAssign}; use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; use pairing::bls12_381::*; @@ -236,7 +236,7 @@ fn bench_fq_inverse(b: &mut ::test::Bencher) { } #[bench] -fn bench_fq_negate(b: &mut ::test::Bencher) { +fn bench_fq_neg(b: &mut ::test::Bencher) { const SAMPLES: usize = 1000; let mut rng = XorShiftRng::from_seed([ @@ -248,8 +248,7 @@ fn bench_fq_negate(b: &mut ::test::Bencher) { let mut count = 0; b.iter(|| { - let mut tmp = v[count]; - tmp.negate(); + let tmp = v[count].neg(); count = (count + 1) % SAMPLES; tmp }); diff --git a/pairing/benches/bls12_381/fr.rs b/pairing/benches/bls12_381/fr.rs index 5905431..16a5c08 100644 --- a/pairing/benches/bls12_381/fr.rs +++ b/pairing/benches/bls12_381/fr.rs @@ -1,6 +1,6 @@ use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; -use std::ops::{AddAssign, MulAssign, SubAssign}; +use std::ops::{AddAssign, MulAssign, Neg, SubAssign}; use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; use pairing::bls12_381::*; @@ -236,7 +236,7 @@ fn bench_fr_inverse(b: &mut ::test::Bencher) { } #[bench] -fn bench_fr_negate(b: &mut ::test::Bencher) { +fn bench_fr_neg(b: &mut ::test::Bencher) { const SAMPLES: usize = 1000; let mut rng = XorShiftRng::from_seed([ @@ -248,8 +248,7 @@ fn bench_fr_negate(b: &mut ::test::Bencher) { let mut count = 0; b.iter(|| { - let mut tmp = v[count]; - tmp.negate(); + let tmp = v[count].neg(); count = (count + 1) % SAMPLES; tmp }); diff --git a/pairing/src/bls12_381/ec.rs b/pairing/src/bls12_381/ec.rs index 1d740b3..c1da107 100644 --- a/pairing/src/bls12_381/ec.rs +++ b/pairing/src/bls12_381/ec.rs @@ -107,8 +107,7 @@ macro_rules! curve_impl { x3b.add_assign(&$affine::get_coeff_b()); x3b.sqrt().map(|y| { - let mut negy = y; - negy.negate(); + let negy = y.neg(); $affine { x: x, @@ -171,7 +170,7 @@ macro_rules! curve_impl { fn negate(&mut self) { if !self.is_zero() { - self.y.negate(); + self.y = self.y.neg(); } } @@ -527,7 +526,7 @@ macro_rules! curve_impl { fn negate(&mut self) { if !self.is_zero() { - self.y.negate() + self.y = self.y.neg(); } } @@ -627,7 +626,7 @@ pub mod g1 { use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; use rand_core::RngCore; use std::fmt; - use std::ops::{AddAssign, MulAssign, SubAssign}; + use std::ops::{AddAssign, MulAssign, Neg, SubAssign}; curve_impl!( "G1", @@ -849,8 +848,7 @@ pub mod g1 { affine.x.into_repr().write_be(&mut writer).unwrap(); } - let mut negy = affine.y; - negy.negate(); + let negy = affine.y.neg(); // Set the third most significant bit if the correct y-coordinate // is lexicographically largest. @@ -948,8 +946,7 @@ pub mod g1 { if let Some(y) = rhs.sqrt() { let yrepr = y.into_repr(); - let mut negy = y; - negy.negate(); + let negy = y.neg(); let negyrepr = negy.into_repr(); let p = G1Affine { @@ -1297,7 +1294,7 @@ pub mod g2 { use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; use rand_core::RngCore; use std::fmt; - use std::ops::{AddAssign, MulAssign, SubAssign}; + use std::ops::{AddAssign, MulAssign, Neg, SubAssign}; curve_impl!( "G2", @@ -1544,8 +1541,7 @@ pub mod g2 { affine.x.c0.into_repr().write_be(&mut writer).unwrap(); } - let mut negy = affine.y; - negy.negate(); + let negy = affine.y.neg(); // Set the third most significant bit if the correct y-coordinate // is lexicographically largest. @@ -1654,8 +1650,7 @@ pub mod g2 { rhs.add_assign(&G2Affine::get_coeff_b()); if let Some(y) = rhs.sqrt() { - let mut negy = y; - negy.negate(); + let negy = y.neg(); let p = G2Affine { x, diff --git a/pairing/src/bls12_381/fq.rs b/pairing/src/bls12_381/fq.rs index ce76b54..f17a278 100644 --- a/pairing/src/bls12_381/fq.rs +++ b/pairing/src/bls12_381/fq.rs @@ -2,6 +2,9 @@ use super::fq2::Fq2; use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; use std::ops::{AddAssign, MulAssign, SubAssign}; +#[cfg(test)] +use std::ops::Neg; + // B coefficient of BLS12-381 curve, 4. pub const B_COEFF: Fq = Fq(FqRepr([ 0xaa270000000cfff3, @@ -456,8 +459,7 @@ fn test_b_coeff() { #[test] fn test_frob_coeffs() { - let mut nqr = Fq::one(); - nqr.negate(); + let nqr = Fq::one().neg(); assert_eq!(FROBENIUS_COEFF_FQ2_C1[0], Fq::one()); assert_eq!( @@ -1167,8 +1169,7 @@ fn test_frob_coeffs() { #[test] fn test_neg_one() { - let mut o = Fq::one(); - o.negate(); + let o = Fq::one().neg(); assert_eq!(NEGATIVE_ONE, o); } @@ -2009,10 +2010,9 @@ fn test_fq_double() { } #[test] -fn test_fq_negate() { +fn test_fq_neg() { { - let mut a = Fq::zero(); - a.negate(); + let a = Fq::zero().neg(); assert!(a.is_zero()); } @@ -2025,8 +2025,7 @@ fn test_fq_negate() { for _ in 0..1000 { // Ensure (a - (-a)) = 0. let mut a = Fq::random(&mut rng); - let mut b = a; - b.negate(); + let b = a.neg(); a.add_assign(&b); assert!(a.is_zero()); @@ -2074,8 +2073,7 @@ fn test_fq_sqrt() { for _ in 0..1000 { // Ensure sqrt(a^2) = a or -a let a = Fq::random(&mut rng); - let mut nega = a; - nega.negate(); + let nega = a.neg(); let mut b = a; b.square(); diff --git a/pairing/src/bls12_381/fq12.rs b/pairing/src/bls12_381/fq12.rs index 96b452d..6bc66a4 100644 --- a/pairing/src/bls12_381/fq12.rs +++ b/pairing/src/bls12_381/fq12.rs @@ -3,7 +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}; +use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// An element of Fq12, represented by c0 + c1 * w. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -20,7 +20,7 @@ impl ::std::fmt::Display for Fq12 { impl Fq12 { pub fn conjugate(&mut self) { - self.c1.negate(); + self.c1 = self.c1.neg(); } pub fn mul_by_014(&mut self, c0: &Fq2, c1: &Fq2, c4: &Fq2) { @@ -40,6 +40,17 @@ impl Fq12 { } } +impl Neg for Fq12 { + type Output = Self; + + fn neg(self) -> Self { + Fq12 { + c0: self.c0.neg(), + c1: self.c1.neg(), + } + } +} + impl<'r> Add<&'r Fq12> for Fq12 { type Output = Self; @@ -177,11 +188,6 @@ impl Field for Fq12 { self.c1.double(); } - fn negate(&mut self) { - self.c0.negate(); - self.c1.negate(); - } - fn frobenius_map(&mut self, power: usize) { self.c0.frobenius_map(power); self.c1.frobenius_map(power); @@ -216,13 +222,9 @@ impl Field for Fq12 { c1s.mul_by_nonresidue(); c0s.sub_assign(&c1s); - c0s.inverse().map(|t| { - let mut tmp = Fq12 { c0: t, c1: t }; - tmp.c0.mul_assign(&self.c0); - tmp.c1.mul_assign(&self.c1); - tmp.c1.negate(); - - tmp + c0s.inverse().map(|t| Fq12 { + c0: t.mul(&self.c0), + c1: t.mul(&self.c1).neg(), }) } } diff --git a/pairing/src/bls12_381/fq2.rs b/pairing/src/bls12_381/fq2.rs index 6997072..e60c374 100644 --- a/pairing/src/bls12_381/fq2.rs +++ b/pairing/src/bls12_381/fq2.rs @@ -2,7 +2,7 @@ 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}; +use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// An element of Fq2, represented by c0 + c1 * u. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -56,6 +56,17 @@ impl Fq2 { } } +impl Neg for Fq2 { + type Output = Self; + + fn neg(self) -> Self { + Fq2 { + c0: self.c0.neg(), + c1: self.c1.neg(), + } + } +} + impl<'r> Add<&'r Fq2> for Fq2 { type Output = Self; @@ -192,8 +203,7 @@ impl Field for Fq2 { ab.mul_assign(&self.c1); let mut c0c1 = self.c0; c0c1.add_assign(&self.c1); - let mut c0 = self.c1; - c0.negate(); + let mut c0 = self.c1.neg(); c0.add_assign(&self.c0); c0.mul_assign(&c0c1); c0.sub_assign(&ab); @@ -208,27 +218,15 @@ impl Field for Fq2 { self.c1.double(); } - fn negate(&mut self) { - self.c0.negate(); - self.c1.negate(); - } - fn inverse(&self) -> Option { let mut t1 = self.c1; t1.square(); let mut t0 = self.c0; t0.square(); t0.add_assign(&t1); - t0.inverse().map(|t| { - let mut tmp = Fq2 { - c0: self.c0, - c1: self.c1, - }; - tmp.c0.mul_assign(&t); - tmp.c1.mul_assign(&t); - tmp.c1.negate(); - - tmp + t0.inverse().map(|t| Fq2 { + c0: self.c0.mul(&t), + c1: self.c1.mul(&t).neg(), }) } @@ -372,10 +370,8 @@ fn test_fq2_squaring() { }; // u a.square(); assert_eq!(a, { - let mut neg1 = Fq::one(); - neg1.negate(); Fq2 { - c0: neg1, + c0: Fq::one().neg(), c1: Fq::zero(), } }); // -1 @@ -694,7 +690,7 @@ fn test_fq2_negation() { use super::fq::FqRepr; use ff::PrimeField; - let mut a = Fq2 { + let a = Fq2 { c0: Fq::from_repr(FqRepr([ 0x2d0078036923ffc7, 0x11e59ea221a3b6d2, @@ -713,8 +709,8 @@ fn test_fq2_negation() { 0x12d1137b8a6a837, ])) .unwrap(), - }; - a.negate(); + } + .neg(); assert_eq!( a, Fq2 { @@ -1000,8 +996,7 @@ fn test_fq2_legendre() { assert_eq!(Zero, Fq2::zero().legendre()); // i^2 = -1 - let mut m1 = Fq2::one(); - m1.negate(); + let mut m1 = Fq2::one().neg(); assert_eq!(QuadraticResidue, m1.legendre()); m1.mul_by_nonresidue(); assert_eq!(QuadraticNonResidue, m1.legendre()); diff --git a/pairing/src/bls12_381/fq6.rs b/pairing/src/bls12_381/fq6.rs index 444119a..a50e283 100644 --- a/pairing/src/bls12_381/fq6.rs +++ b/pairing/src/bls12_381/fq6.rs @@ -2,7 +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}; +use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// An element of Fq6, represented by c0 + c1 * v + c2 * v^(2). #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -100,6 +100,18 @@ impl Fq6 { } } +impl Neg for Fq6 { + type Output = Self; + + fn neg(self) -> Self { + Fq6 { + c0: self.c0.neg(), + c1: self.c1.neg(), + c2: self.c2.neg(), + } + } +} + impl<'r> Add<&'r Fq6> for Fq6 { type Output = Self; @@ -280,12 +292,6 @@ impl Field for Fq6 { 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); @@ -332,7 +338,7 @@ impl Field for Fq6 { let mut c0 = self.c2; c0.mul_by_nonresidue(); c0.mul_assign(&self.c1); - c0.negate(); + c0 = c0.neg(); { let mut c0s = self.c0; c0s.square(); diff --git a/pairing/src/bls12_381/fr.rs b/pairing/src/bls12_381/fr.rs index ca9cd57..d72557e 100644 --- a/pairing/src/bls12_381/fr.rs +++ b/pairing/src/bls12_381/fr.rs @@ -10,6 +10,8 @@ pub struct Fr(FrRepr); use rand_core::SeedableRng; #[cfg(test)] use rand_xorshift::XorShiftRng; +#[cfg(test)] +use std::ops::Neg; #[test] fn test_fr_repr_ordering() { @@ -767,10 +769,9 @@ fn test_fr_double() { } #[test] -fn test_fr_negate() { +fn test_fr_neg() { { - let mut a = Fr::zero(); - a.negate(); + let a = Fr::zero().neg(); assert!(a.is_zero()); } @@ -783,8 +784,7 @@ fn test_fr_negate() { for _ in 0..1000 { // Ensure (a - (-a)) = 0. let mut a = Fr::random(&mut rng); - let mut b = a; - b.negate(); + let b = a.neg(); a.add_assign(&b); assert!(a.is_zero()); @@ -832,8 +832,7 @@ fn test_fr_sqrt() { for _ in 0..1000 { // Ensure sqrt(a^2) = a or -a let a = Fr::random(&mut rng); - let mut nega = a; - nega.negate(); + let nega = a.neg(); let mut b = a; b.square(); diff --git a/pairing/src/bls12_381/mod.rs b/pairing/src/bls12_381/mod.rs index 04fd5ee..32e23e1 100644 --- a/pairing/src/bls12_381/mod.rs +++ b/pairing/src/bls12_381/mod.rs @@ -25,7 +25,7 @@ use super::{Engine, PairingCurveAffine}; use ff::{BitIterator, Field, ScalarEngine}; use group::CurveAffine; -use std::ops::{AddAssign, MulAssign, SubAssign}; +use std::ops::{AddAssign, MulAssign, Neg, SubAssign}; // The BLS parameter x for BLS12-381 is -0xd201000000010000 const BLS_X: u64 = 0xd201000000010000; @@ -236,7 +236,7 @@ impl G2Prepared { tmp3 = tmp4; tmp3.mul_assign(&zsquared); tmp3.double(); - tmp3.negate(); + tmp3 = tmp3.neg(); tmp6.square(); tmp6.sub_assign(&tmp0); @@ -334,7 +334,7 @@ impl G2Prepared { t10 = r.z; t10.double(); - t6.negate(); + t6 = t6.neg(); t1 = t6; t1.double(); diff --git a/pairing/src/tests/field.rs b/pairing/src/tests/field.rs index 8f3d8d9..89b2038 100644 --- a/pairing/src/tests/field.rs +++ b/pairing/src/tests/field.rs @@ -36,8 +36,7 @@ pub fn random_sqrt_tests() { assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue); let b = b.sqrt().unwrap(); - let mut negb = b; - negb.negate(); + let negb = b.neg(); assert!(a == b || a == negb); } @@ -51,7 +50,7 @@ pub fn random_sqrt_tests() { b = b.sqrt().unwrap(); if b != c { - b.negate(); + b = b.neg(); } assert_eq!(b, c); @@ -77,8 +76,7 @@ pub fn random_field_tests() { assert!(F::zero().is_zero()); { - let mut z = F::zero(); - z.negate(); + let z = F::zero().neg(); assert!(z.is_zero()); } @@ -204,8 +202,7 @@ fn random_subtraction_tests(rng: &mut R) { fn random_negation_tests(rng: &mut R) { for _ in 0..10000 { let a = F::random(rng); - let mut b = a; - b.negate(); + let mut b = a.neg(); b.add_assign(&a); assert!(b.is_zero()); diff --git a/zcash_primitives/src/jubjub/edwards.rs b/zcash_primitives/src/jubjub/edwards.rs index 2865ce3..8c7df4c 100644 --- a/zcash_primitives/src/jubjub/edwards.rs +++ b/zcash_primitives/src/jubjub/edwards.rs @@ -1,5 +1,5 @@ use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; -use std::ops::{AddAssign, MulAssign, SubAssign}; +use std::ops::{AddAssign, MulAssign, Neg, SubAssign}; use super::{montgomery, JubjubEngine, JubjubParams, PrimeOrder, Unknown}; @@ -126,7 +126,7 @@ impl Point { match tmp1.sqrt() { Some(mut x) => { if x.into_repr().is_odd() != sign { - x.negate(); + x = x.neg(); } let mut t = x; @@ -213,12 +213,9 @@ impl Point { // only point of order 2 that is not the neutral element. if y.is_zero() { // This must be the point (0, 0) as above. - let mut neg1 = E::Fr::one(); - neg1.negate(); - Point { x: E::Fr::zero(), - y: neg1, + y: E::Fr::one().neg(), t: E::Fr::zero(), z: E::Fr::one(), _marker: PhantomData, @@ -324,8 +321,8 @@ impl Point { pub fn negate(&self) -> Self { let mut p = self.clone(); - p.x.negate(); - p.t.negate(); + p.x = p.x.neg(); + p.t = p.t.neg(); p } @@ -352,8 +349,7 @@ impl Point { // D = a*A // = -A - let mut d = a; - d.negate(); + let d = a.neg(); // E = (X1+Y1)^2 - A - B let mut e = self.x; diff --git a/zcash_primitives/src/jubjub/fs.rs b/zcash_primitives/src/jubjub/fs.rs index ddd2bce..53d0ee3 100644 --- a/zcash_primitives/src/jubjub/fs.rs +++ b/zcash_primitives/src/jubjub/fs.rs @@ -5,7 +5,7 @@ use ff::{ PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField, }; use rand_core::RngCore; -use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}; +use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use super::ToUniform; @@ -269,6 +269,20 @@ impl From for FsRepr { } } +impl Neg for Fs { + type Output = Self; + + #[inline] + fn neg(mut self) -> Self { + if !self.is_zero() { + let mut tmp = MODULUS; + tmp.sub_noborrow(&self.0); + self.0 = tmp; + } + self + } +} + impl<'r> Add<&'r Fs> for Fs { type Output = Self; @@ -496,15 +510,6 @@ impl Field for Fs { self.reduce(); } - #[inline] - fn negate(&mut self) { - if !self.is_zero() { - let mut tmp = MODULUS; - tmp.sub_noborrow(&self.0); - self.0 = tmp; - } - } - fn inverse(&self) -> Option { if self.is_zero() { None @@ -742,8 +747,7 @@ impl SqrtField for Fs { #[test] fn test_neg_one() { - let mut o = Fs::one(); - o.negate(); + let o = Fs::one().neg(); assert_eq!(NEGATIVE_ONE, o); } @@ -1471,10 +1475,9 @@ fn test_fs_double() { } #[test] -fn test_fs_negate() { +fn test_fs_neg() { { - let mut a = Fs::zero(); - a.negate(); + let a = Fs::zero().neg(); assert!(a.is_zero()); } @@ -1487,8 +1490,7 @@ fn test_fs_negate() { for _ in 0..1000 { // Ensure (a - (-a)) = 0. let mut a = Fs::random(&mut rng); - let mut b = a; - b.negate(); + let b = a.neg(); a.add_assign(&b); assert!(a.is_zero()); @@ -1534,8 +1536,7 @@ fn test_fs_sqrt() { for _ in 0..1000 { // Ensure sqrt(a^2) = a or -a let a = Fs::random(&mut rng); - let mut nega = a; - nega.negate(); + let nega = a.neg(); let mut b = a; b.square(); diff --git a/zcash_primitives/src/jubjub/montgomery.rs b/zcash_primitives/src/jubjub/montgomery.rs index fc41274..18acc0d 100644 --- a/zcash_primitives/src/jubjub/montgomery.rs +++ b/zcash_primitives/src/jubjub/montgomery.rs @@ -1,5 +1,5 @@ use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; -use std::ops::{AddAssign, MulAssign, SubAssign}; +use std::ops::{AddAssign, MulAssign, Neg, SubAssign}; use super::{edwards, JubjubEngine, JubjubParams, PrimeOrder, Unknown}; @@ -62,7 +62,7 @@ impl Point { match rhs.sqrt() { Some(mut y) => { if y.into_repr().is_odd() != sign { - y.negate(); + y = y.neg(); } Some(Point { @@ -190,7 +190,7 @@ impl Point { pub fn negate(&self) -> Self { let mut p = self.clone(); - p.y.negate(); + p.y = p.y.neg(); p } @@ -242,7 +242,7 @@ impl Point { y3.sub_assign(&self.x); y3.mul_assign(&delta); y3.add_assign(&self.y); - y3.negate(); + y3 = y3.neg(); Point { x: x3, @@ -292,7 +292,7 @@ impl Point { y3.sub_assign(&self.x); y3.mul_assign(&delta); y3.add_assign(&self.y); - y3.negate(); + y3 = y3.neg(); Point { x: x3, diff --git a/zcash_primitives/src/jubjub/tests.rs b/zcash_primitives/src/jubjub/tests.rs index 56fad56..d152737 100644 --- a/zcash_primitives/src/jubjub/tests.rs +++ b/zcash_primitives/src/jubjub/tests.rs @@ -1,7 +1,7 @@ use super::{edwards, montgomery, JubjubEngine, JubjubParams, PrimeOrder}; use ff::{Field, LegendreSymbol, PrimeField, PrimeFieldRepr, SqrtField}; -use std::ops::{AddAssign, MulAssign, SubAssign}; +use std::ops::{AddAssign, MulAssign, Neg, SubAssign}; use rand_core::{RngCore, SeedableRng}; use rand_xorshift::XorShiftRng; @@ -310,8 +310,7 @@ fn test_back_and_forth(params: &E::Params) { fn test_jubjub_params(params: &E::Params) { // a = -1 - let mut a = E::Fr::one(); - a.negate(); + let a = E::Fr::one().neg(); { // Check that 2A is consistent with A @@ -339,7 +338,7 @@ fn test_jubjub_params(params: &E::Params) { assert!(tmp.inverse().unwrap().legendre() == LegendreSymbol::QuadraticNonResidue); // tmp = -d - tmp.negate(); + tmp = tmp.neg(); // -d is nonsquare assert!(tmp.legendre() == LegendreSymbol::QuadraticNonResidue); diff --git a/zcash_primitives/src/pedersen_hash.rs b/zcash_primitives/src/pedersen_hash.rs index 5fb7333..d12b6a4 100644 --- a/zcash_primitives/src/pedersen_hash.rs +++ b/zcash_primitives/src/pedersen_hash.rs @@ -2,7 +2,7 @@ use crate::jubjub::*; use ff::{Field, PrimeField, PrimeFieldRepr}; -use std::ops::AddAssign; +use std::ops::{AddAssign, Neg}; #[derive(Copy, Clone)] pub enum Personalization { @@ -65,7 +65,7 @@ where // conditionally negate if c { - tmp.negate(); + tmp = tmp.neg(); } acc.add_assign(&tmp); diff --git a/zcash_primitives/src/redjubjub.rs b/zcash_primitives/src/redjubjub.rs index 6158685..4633d6d 100644 --- a/zcash_primitives/src/redjubjub.rs +++ b/zcash_primitives/src/redjubjub.rs @@ -7,7 +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 std::ops::{AddAssign, MulAssign, Neg}; use crate::util::hash_to_scalar; @@ -194,7 +194,7 @@ pub fn batch_verify<'a, E: JubjubEngine, R: RngCore>( let z = E::Fs::random(rng); s.mul_assign(&z); - s.negate(); + s = s.neg(); r = r.mul(z, params); diff --git a/zcash_proofs/src/circuit/ecc.rs b/zcash_proofs/src/circuit/ecc.rs index a35dfd7..7072f01 100644 --- a/zcash_proofs/src/circuit/ecc.rs +++ b/zcash_proofs/src/circuit/ecc.rs @@ -2,7 +2,7 @@ use ff::Field; use pairing::Engine; -use std::ops::{AddAssign, MulAssign, SubAssign}; +use std::ops::{AddAssign, MulAssign, Neg, SubAssign}; use bellman::{ConstraintSystem, SynthesisError}; @@ -367,7 +367,7 @@ impl EdwardsPoint { let y3 = AllocatedNum::alloc(cs.namespace(|| "y3"), || { let mut t0 = *a.get_value().get()?; t0.double(); - t0.negate(); + t0 = t0.neg(); t0.add_assign(t.get_value().get()?); let mut t1 = E::Fr::one(); @@ -642,7 +642,7 @@ impl MontgomeryPoint { t0.sub_assign(self.x.get_value().get()?); t0.mul_assign(lambda.get_value().get()?); t0.add_assign(self.y.get_value().get()?); - t0.negate(); + t0 = t0.neg(); Ok(t0) })?; diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index e695ba1..16424cc 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -5,7 +5,7 @@ use bellman::{ use ff::Field; use pairing::bls12_381::{Bls12, Fr}; use rand_core::OsRng; -use std::ops::AddAssign; +use std::ops::{AddAssign, Neg}; use zcash_primitives::{ jubjub::{edwards, fs::Fs, FixedGenerators, JubjubBls12, Unknown}, primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment}, @@ -202,8 +202,7 @@ impl SaplingProvingContext { // Accumulate the value commitment randomness in the context { - let mut tmp = rcv; - tmp.negate(); // Outputs subtract from the total. + let mut tmp = rcv.neg(); // Outputs subtract from the total. tmp.add_assign(&self.bsk); // Update the context From 9dac74822471f5fadd732370fb4ab7b0ca5c719b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 12 Dec 2019 22:59:18 +0000 Subject: [PATCH 2/4] Make Field::double take &self and return Self --- bellman/src/gadgets/multipack.rs | 4 +-- bellman/src/gadgets/num.rs | 4 +-- bellman/src/gadgets/uint32.rs | 4 +-- bellman/src/groth16/tests/dummy_engine.rs | 6 ++--- ff/ff_derive/src/lib.rs | 10 +++++--- ff/src/lib.rs | 3 ++- pairing/src/bls12_381/ec.rs | 26 ++++++++----------- pairing/src/bls12_381/fq.rs | 7 ++--- pairing/src/bls12_381/fq12.rs | 8 +++--- pairing/src/bls12_381/fq2.rs | 13 +++++----- pairing/src/bls12_381/fq6.rs | 16 ++++++------ pairing/src/bls12_381/fr.rs | 7 ++--- pairing/src/bls12_381/mod.rs | 31 ++++++++--------------- pairing/src/tests/field.rs | 8 ++---- zcash_primitives/src/jubjub/edwards.rs | 2 +- zcash_primitives/src/jubjub/fs.rs | 19 +++++++------- zcash_primitives/src/jubjub/mod.rs | 3 +-- zcash_primitives/src/jubjub/montgomery.rs | 7 +++-- zcash_primitives/src/jubjub/tests.rs | 5 +--- zcash_primitives/src/pedersen_hash.rs | 6 ++--- zcash_proofs/src/circuit/ecc.rs | 5 ++-- zcash_proofs/src/circuit/sapling.rs | 2 +- zcash_proofs/src/circuit/sprout/mod.rs | 2 +- 23 files changed, 87 insertions(+), 111 deletions(-) diff --git a/bellman/src/gadgets/multipack.rs b/bellman/src/gadgets/multipack.rs index 445a360..8ee6a15 100644 --- a/bellman/src/gadgets/multipack.rs +++ b/bellman/src/gadgets/multipack.rs @@ -20,7 +20,7 @@ where for bit in bits { num = num.add_bool_with_coeff(CS::one(), bit, coeff); - coeff.double(); + coeff = coeff.double(); } let input = cs.alloc_input(|| format!("input {}", i), || Ok(*num.get_value().get()?))?; @@ -63,7 +63,7 @@ pub fn compute_multipacking(bits: &[bool]) -> Vec { cur.add_assign(&coeff); } - coeff.double(); + coeff = coeff.double(); } result.push(cur); diff --git a/bellman/src/gadgets/num.rs b/bellman/src/gadgets/num.rs index bce55ce..08a175b 100644 --- a/bellman/src/gadgets/num.rs +++ b/bellman/src/gadgets/num.rs @@ -177,7 +177,7 @@ impl AllocatedNum { for bit in result.iter().rev() { lc = lc + (coeff, bit.get_variable()); - coeff.double(); + coeff = coeff.double(); } lc = lc - self.variable; @@ -203,7 +203,7 @@ impl AllocatedNum { for bit in bits.iter() { lc = lc + (coeff, bit.get_variable()); - coeff.double(); + coeff = coeff.double(); } lc = lc - self.variable; diff --git a/bellman/src/gadgets/uint32.rs b/bellman/src/gadgets/uint32.rs index 8bf4558..16bb651 100644 --- a/bellman/src/gadgets/uint32.rs +++ b/bellman/src/gadgets/uint32.rs @@ -330,7 +330,7 @@ impl UInt32 { all_constants &= bit.is_constant(); - coeff.double(); + coeff = coeff.double(); } } @@ -368,7 +368,7 @@ impl UInt32 { max_value >>= 1; i += 1; - coeff.double(); + coeff = coeff.double(); } // Enforce equality between the sum and result diff --git a/bellman/src/groth16/tests/dummy_engine.rs b/bellman/src/groth16/tests/dummy_engine.rs index 46641b3..224f84e 100644 --- a/bellman/src/groth16/tests/dummy_engine.rs +++ b/bellman/src/groth16/tests/dummy_engine.rs @@ -144,8 +144,8 @@ impl Field for Fr { self.0 = (self.0 * self.0) % MODULUS_R; } - fn double(&mut self) { - self.0 = (self.0 << 1) % MODULUS_R; + fn double(&self) -> Self { + Fr((self.0 << 1) % MODULUS_R) } fn inverse(&self) -> Option { @@ -406,7 +406,7 @@ impl CurveProjective for Fr { } fn double(&mut self) { - ::double(self); + self.0 = ::double(self).0; } fn add_assign(&mut self, other: &Self) { diff --git a/ff/ff_derive/src/lib.rs b/ff/ff_derive/src/lib.rs index 0e804c7..88146b3 100644 --- a/ff/ff_derive/src/lib.rs +++ b/ff/ff_derive/src/lib.rs @@ -1040,12 +1040,16 @@ fn prime_field_impl( } #[inline] - fn double(&mut self) { + fn double(&self) -> Self { + let mut ret = *self; + // This cannot exceed the backing capacity. - self.0.mul2(); + ret.0.mul2(); // However, it may need to be reduced. - self.reduce(); + ret.reduce(); + + ret } fn inverse(&self) -> Option { diff --git a/ff/src/lib.rs b/ff/src/lib.rs index c605f64..fd8d45d 100644 --- a/ff/src/lib.rs +++ b/ff/src/lib.rs @@ -54,7 +54,8 @@ pub trait Field: fn square(&mut self); /// Doubles this element. - fn double(&mut self); + #[must_use] + fn double(&self) -> Self; /// Computes the multiplicative inverse of this element, if nonzero. fn inverse(&self) -> Option; diff --git a/pairing/src/bls12_381/ec.rs b/pairing/src/bls12_381/ec.rs index c1da107..6f45592 100644 --- a/pairing/src/bls12_381/ec.rs +++ b/pairing/src/bls12_381/ec.rs @@ -322,11 +322,10 @@ macro_rules! curve_impl { d.square(); d.sub_assign(&a); d.sub_assign(&c); - d.double(); + d = d.double(); // E = 3*A - let mut e = a; - e.double(); + let mut e = a.double(); e.add_assign(&a); // F = E^2 @@ -335,7 +334,7 @@ macro_rules! curve_impl { // Z3 = 2*Y1*Z1 self.z.mul_assign(&self.y); - self.z.double(); + self.z = self.z.double(); // X3 = F-2*D self.x = f; @@ -346,9 +345,7 @@ macro_rules! curve_impl { self.y = d; self.y.sub_assign(&self.x); self.y.mul_assign(&e); - c.double(); - c.double(); - c.double(); + c = c.double().double().double(); self.y.sub_assign(&c); } @@ -401,8 +398,7 @@ macro_rules! curve_impl { h.sub_assign(&u1); // I = (2*H)^2 - let mut i = h; - i.double(); + let mut i = h.double(); i.square(); // J = H*I @@ -412,7 +408,7 @@ macro_rules! curve_impl { // r = 2*(S2-S1) let mut r = s2; r.sub_assign(&s1); - r.double(); + r = r.double(); // V = U1*I let mut v = u1; @@ -430,7 +426,7 @@ macro_rules! curve_impl { self.y.sub_assign(&self.x); self.y.mul_assign(&r); s1.mul_assign(&j); // S1 = S1 * J * 2 - s1.double(); + s1 = s1.double(); self.y.sub_assign(&s1); // Z3 = ((Z1+Z2)^2 - Z1Z1 - Z2Z2)*H @@ -484,9 +480,7 @@ macro_rules! curve_impl { hh.square(); // I = 4*HH - let mut i = hh; - i.double(); - i.double(); + let i = hh.double().double(); // J = H*I let mut j = h; @@ -495,7 +489,7 @@ macro_rules! curve_impl { // r = 2*(S2-Y1) let mut r = s2; r.sub_assign(&self.y); - r.double(); + r = r.double(); // V = X1*I let mut v = self.x; @@ -510,7 +504,7 @@ macro_rules! curve_impl { // Y3 = r*(V-X3)-2*Y1*J j.mul_assign(&self.y); // J = 2*Y1*J - j.double(); + j = j.double(); self.y = v; self.y.sub_assign(&self.x); self.y.mul_assign(&r); diff --git a/pairing/src/bls12_381/fq.rs b/pairing/src/bls12_381/fq.rs index f17a278..77c85ea 100644 --- a/pairing/src/bls12_381/fq.rs +++ b/pairing/src/bls12_381/fq.rs @@ -2001,11 +2001,8 @@ fn test_fq_double() { for _ in 0..1000 { // Ensure doubling a is equivalent to adding a to itself. - let mut a = Fq::random(&mut rng); - let mut b = a; - b.add_assign(&a); - a.double(); - assert_eq!(a, b); + let a = Fq::random(&mut rng); + assert_eq!(a.double(), a + a); } } diff --git a/pairing/src/bls12_381/fq12.rs b/pairing/src/bls12_381/fq12.rs index 6bc66a4..d072725 100644 --- a/pairing/src/bls12_381/fq12.rs +++ b/pairing/src/bls12_381/fq12.rs @@ -183,9 +183,11 @@ impl Field for Fq12 { self.c0.is_zero() && self.c1.is_zero() } - fn double(&mut self) { - self.c0.double(); - self.c1.double(); + fn double(&self) -> Self { + Fq12 { + c0: self.c0.double(), + c1: self.c1.double(), + } } fn frobenius_map(&mut self, power: usize) { diff --git a/pairing/src/bls12_381/fq2.rs b/pairing/src/bls12_381/fq2.rs index e60c374..137c1ba 100644 --- a/pairing/src/bls12_381/fq2.rs +++ b/pairing/src/bls12_381/fq2.rs @@ -213,9 +213,11 @@ impl Field for Fq2 { self.c0 = c0; } - fn double(&mut self) { - self.c0.double(); - self.c1.double(); + fn double(&self) -> Self { + Fq2 { + c0: self.c0.double(), + c1: self.c1.double(), + } } fn inverse(&self) -> Option { @@ -741,7 +743,7 @@ fn test_fq2_doubling() { use super::fq::FqRepr; use ff::PrimeField; - let mut a = Fq2 { + let a = Fq2 { c0: Fq::from_repr(FqRepr([ 0x2d0078036923ffc7, 0x11e59ea221a3b6d2, @@ -761,9 +763,8 @@ fn test_fq2_doubling() { ])) .unwrap(), }; - a.double(); assert_eq!( - a, + a.double(), Fq2 { c0: Fq::from_repr(FqRepr([ 0x5a00f006d247ff8e, diff --git a/pairing/src/bls12_381/fq6.rs b/pairing/src/bls12_381/fq6.rs index a50e283..8e5b394 100644 --- a/pairing/src/bls12_381/fq6.rs +++ b/pairing/src/bls12_381/fq6.rs @@ -286,10 +286,12 @@ impl Field for Fq6 { 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 double(&self) -> Self { + Fq6 { + c0: self.c0.double(), + c1: self.c1.double(), + c2: self.c2.double(), + } } fn frobenius_map(&mut self, power: usize) { @@ -306,16 +308,14 @@ impl Field for Fq6 { s0.square(); let mut ab = self.c0; ab.mul_assign(&self.c1); - let mut s1 = ab; - s1.double(); + let s1 = ab.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 s3 = bc.double(); let mut s4 = self.c2; s4.square(); diff --git a/pairing/src/bls12_381/fr.rs b/pairing/src/bls12_381/fr.rs index d72557e..21832de 100644 --- a/pairing/src/bls12_381/fr.rs +++ b/pairing/src/bls12_381/fr.rs @@ -760,11 +760,8 @@ fn test_fr_double() { for _ in 0..1000 { // Ensure doubling a is equivalent to adding a to itself. - let mut a = Fr::random(&mut rng); - let mut b = a; - b.add_assign(&a); - a.double(); - assert_eq!(a, b); + let a = Fr::random(&mut rng); + assert_eq!(a.double(), a + a); } } diff --git a/pairing/src/bls12_381/mod.rs b/pairing/src/bls12_381/mod.rs index 32e23e1..0a3813d 100644 --- a/pairing/src/bls12_381/mod.rs +++ b/pairing/src/bls12_381/mod.rs @@ -199,10 +199,9 @@ impl G2Prepared { tmp3.square(); tmp3.sub_assign(&tmp0); tmp3.sub_assign(&tmp2); - tmp3.double(); + tmp3 = tmp3.double(); - let mut tmp4 = tmp0; - tmp4.double(); + let mut tmp4 = tmp0.double(); tmp4.add_assign(&tmp0); let mut tmp6 = r.x; @@ -227,29 +226,25 @@ impl G2Prepared { r.y.sub_assign(&r.x); r.y.mul_assign(&tmp4); - tmp2.double(); - tmp2.double(); - tmp2.double(); + tmp2 = tmp2.double().double().double(); r.y.sub_assign(&tmp2); tmp3 = tmp4; tmp3.mul_assign(&zsquared); - tmp3.double(); - tmp3 = tmp3.neg(); + tmp3 = tmp3.double().neg(); tmp6.square(); tmp6.sub_assign(&tmp0); tmp6.sub_assign(&tmp5); - tmp1.double(); - tmp1.double(); + tmp1 = tmp1.double().double(); tmp6.sub_assign(&tmp1); tmp0 = r.z; tmp0.mul_assign(&zsquared); - tmp0.double(); + tmp0 = tmp0.double(); (tmp0, tmp3, tmp6) } @@ -278,9 +273,7 @@ impl G2Prepared { let mut t3 = t2; t3.square(); - let mut t4 = t3; - t4.double(); - t4.double(); + let t4 = t3.double().double(); let mut t5 = t4; t5.mul_assign(&t2); @@ -315,7 +308,7 @@ impl G2Prepared { t0 = r.y; t0.mul_assign(&t5); - t0.double(); + t0 = t0.double(); r.y = t8; r.y.sub_assign(&t0); @@ -328,16 +321,14 @@ impl G2Prepared { t10.sub_assign(&ztsquared); - t9.double(); + t9 = t9.double(); t9.sub_assign(&t10); - t10 = r.z; - t10.double(); + t10 = r.z.double(); t6 = t6.neg(); - t1 = t6; - t1.double(); + t1 = t6.double(); (t10, t1, t9) } diff --git a/pairing/src/tests/field.rs b/pairing/src/tests/field.rs index 89b2038..304e142 100644 --- a/pairing/src/tests/field.rs +++ b/pairing/src/tests/field.rs @@ -211,12 +211,8 @@ fn random_negation_tests(rng: &mut R) { fn random_doubling_tests(rng: &mut R) { for _ in 0..10000 { - let mut a = F::random(rng); - let mut b = a; - a.add_assign(&b); - b.double(); - - assert_eq!(a, b); + let a = F::random(rng); + assert_eq!(a + a, a.double()); } } diff --git a/zcash_primitives/src/jubjub/edwards.rs b/zcash_primitives/src/jubjub/edwards.rs index 8c7df4c..45975cb 100644 --- a/zcash_primitives/src/jubjub/edwards.rs +++ b/zcash_primitives/src/jubjub/edwards.rs @@ -345,7 +345,7 @@ impl Point { // C = 2*Z1^2 let mut c = self.z; c.square(); - c.double(); + c = c.double(); // D = a*A // = -A diff --git a/zcash_primitives/src/jubjub/fs.rs b/zcash_primitives/src/jubjub/fs.rs index 53d0ee3..aa18590 100644 --- a/zcash_primitives/src/jubjub/fs.rs +++ b/zcash_primitives/src/jubjub/fs.rs @@ -502,12 +502,16 @@ impl Field for Fs { } #[inline] - fn double(&mut self) { + fn double(&self) -> Self { + let mut ret = *self; + // This cannot exceed the backing capacity. - self.0.mul2(); + ret.0.mul2(); // However, it may need to be reduced. - self.reduce(); + ret.reduce(); + + ret } fn inverse(&self) -> Option { @@ -680,7 +684,7 @@ impl Fs { fn mul_bits>(&self, bits: BitIterator) -> Self { let mut res = Self::zero(); for bit in bits { - res.double(); + res = res.double(); if bit { res.add_assign(self) @@ -1466,11 +1470,8 @@ fn test_fs_double() { for _ in 0..1000 { // Ensure doubling a is equivalent to adding a to itself. - let mut a = Fs::random(&mut rng); - let mut b = a; - b.add_assign(&a); - a.double(); - assert_eq!(a, b); + let a = Fs::random(&mut rng); + assert_eq!(a.double(), a + a); } } diff --git a/zcash_primitives/src/jubjub/mod.rs b/zcash_primitives/src/jubjub/mod.rs index 9428600..06a3810 100644 --- a/zcash_primitives/src/jubjub/mod.rs +++ b/zcash_primitives/src/jubjub/mod.rs @@ -195,8 +195,7 @@ impl JubjubParams for JubjubBls12 { impl JubjubBls12 { pub fn new() -> Self { let montgomery_a = Fr::from_str("40962").unwrap(); - let mut montgomery_2a = montgomery_a; - montgomery_2a.double(); + let montgomery_2a = montgomery_a.double(); let mut tmp_params = JubjubBls12 { // d = -(10240/10241) diff --git a/zcash_primitives/src/jubjub/montgomery.rs b/zcash_primitives/src/jubjub/montgomery.rs index 18acc0d..5bb052f 100644 --- a/zcash_primitives/src/jubjub/montgomery.rs +++ b/zcash_primitives/src/jubjub/montgomery.rs @@ -216,19 +216,18 @@ impl Point { { let mut tmp = *params.montgomery_a(); tmp.mul_assign(&self.x); - tmp.double(); + tmp = tmp.double(); delta.add_assign(&tmp); } { let mut tmp = self.x; tmp.square(); delta.add_assign(&tmp); - tmp.double(); + tmp = tmp.double(); delta.add_assign(&tmp); } { - let mut tmp = self.y; - tmp.double(); + let tmp = self.y.double(); delta.mul_assign(&tmp.inverse().expect("y is nonzero so this must be nonzero")); } diff --git a/zcash_primitives/src/jubjub/tests.rs b/zcash_primitives/src/jubjub/tests.rs index d152737..2469d58 100644 --- a/zcash_primitives/src/jubjub/tests.rs +++ b/zcash_primitives/src/jubjub/tests.rs @@ -314,10 +314,7 @@ fn test_jubjub_params(params: &E::Params) { { // Check that 2A is consistent with A - let mut tmp = *params.montgomery_a(); - tmp.double(); - - assert_eq!(&tmp, params.montgomery_2a()); + assert_eq!(¶ms.montgomery_a().double(), params.montgomery_2a()); } { diff --git a/zcash_primitives/src/pedersen_hash.rs b/zcash_primitives/src/pedersen_hash.rs index d12b6a4..ea182a5 100644 --- a/zcash_primitives/src/pedersen_hash.rs +++ b/zcash_primitives/src/pedersen_hash.rs @@ -58,7 +58,7 @@ where if a { tmp.add_assign(&cur); } - cur.double(); // 2^1 * cur + cur = cur.double(); // 2^1 * cur if b { tmp.add_assign(&cur); } @@ -75,9 +75,7 @@ where if chunks_remaining == 0 { break; } else { - cur.double(); // 2^2 * cur - cur.double(); // 2^3 * cur - cur.double(); // 2^4 * cur + cur = cur.double().double().double(); // 2^4 * cur } } diff --git a/zcash_proofs/src/circuit/ecc.rs b/zcash_proofs/src/circuit/ecc.rs index 7072f01..9889a50 100644 --- a/zcash_proofs/src/circuit/ecc.rs +++ b/zcash_proofs/src/circuit/ecc.rs @@ -340,7 +340,7 @@ impl EdwardsPoint { // Compute x3 = (2.A) / (1 + C) let x3 = AllocatedNum::alloc(cs.namespace(|| "x3"), || { let mut t0 = *a.get_value().get()?; - t0.double(); + t0 = t0.double(); let mut t1 = E::Fr::one(); t1.add_assign(c.get_value().get()?); @@ -366,8 +366,7 @@ impl EdwardsPoint { // Compute y3 = (U - 2.A) / (1 - C) let y3 = AllocatedNum::alloc(cs.namespace(|| "y3"), || { let mut t0 = *a.get_value().get()?; - t0.double(); - t0 = t0.neg(); + t0 = t0.double().neg(); t0.add_assign(t.get_value().get()?); let mut t1 = E::Fr::one(); diff --git a/zcash_proofs/src/circuit/sapling.rs b/zcash_proofs/src/circuit/sapling.rs index ddb0f1c..9782a4f 100644 --- a/zcash_proofs/src/circuit/sapling.rs +++ b/zcash_proofs/src/circuit/sapling.rs @@ -245,7 +245,7 @@ impl<'a, E: JubjubEngine> Circuit for Spend<'a, E> { let mut coeff = E::Fr::one(); for bit in &value_bits { value_num = value_num.add_bool_with_coeff(CS::one(), bit, coeff); - coeff.double(); + coeff = coeff.double(); } // Place the value in the note diff --git a/zcash_proofs/src/circuit/sprout/mod.rs b/zcash_proofs/src/circuit/sprout/mod.rs index 1877047..6afe677 100644 --- a/zcash_proofs/src/circuit/sprout/mod.rs +++ b/zcash_proofs/src/circuit/sprout/mod.rs @@ -268,7 +268,7 @@ impl NoteValue { let mut coeff = E::Fr::one(); for b in &self.bits { tmp = tmp + (coeff, b.get_variable()); - coeff.double(); + coeff = coeff.double(); } tmp From cded08b0c5ea4e96131b8a52d117da889d6dde9b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 12 Dec 2019 23:09:28 +0000 Subject: [PATCH 3/4] Make Field::square take &self and return Self --- bellman/src/domain.rs | 2 +- bellman/src/gadgets/num.rs | 3 +- bellman/src/groth16/tests/dummy_engine.rs | 13 +++-- bellman/tests/mimc.rs | 6 +-- ff/ff_derive/src/lib.rs | 18 +++---- ff/src/lib.rs | 5 +- pairing/benches/bls12_381/fq.rs | 9 +--- pairing/benches/bls12_381/fq12.rs | 3 +- pairing/benches/bls12_381/fq2.rs | 3 +- pairing/benches/bls12_381/fr.rs | 9 +--- pairing/src/bls12_381/ec.rs | 66 ++++++++--------------- pairing/src/bls12_381/fq.rs | 23 +++----- pairing/src/bls12_381/fq12.rs | 14 +++-- pairing/src/bls12_381/fq2.rs | 38 ++++++------- pairing/src/bls12_381/fq6.rs | 43 +++++++-------- pairing/src/bls12_381/fr.rs | 23 +++----- pairing/src/bls12_381/mod.rs | 47 +++++++--------- pairing/src/bls12_381/tests/mod.rs | 18 +++---- pairing/src/tests/field.rs | 14 ++--- zcash_primitives/src/jubjub/edwards.rs | 15 ++---- zcash_primitives/src/jubjub/fs.rs | 27 +++++----- zcash_primitives/src/jubjub/montgomery.rs | 12 ++--- zcash_primitives/src/jubjub/tests.rs | 15 ++---- zcash_proofs/src/circuit/ecc.rs | 6 +-- 24 files changed, 160 insertions(+), 272 deletions(-) diff --git a/bellman/src/domain.rs b/bellman/src/domain.rs index a1e4a4c..6e8a6a7 100644 --- a/bellman/src/domain.rs +++ b/bellman/src/domain.rs @@ -63,7 +63,7 @@ impl> EvaluationDomain { // Compute omega, the 2^exp primitive root of unity let mut omega = E::Fr::root_of_unity(); for _ in exp..E::Fr::S { - omega.square(); + omega = omega.square(); } // Extend the coeffs vector with zeroes if necessary diff --git a/bellman/src/gadgets/num.rs b/bellman/src/gadgets/num.rs index 08a175b..65bee25 100644 --- a/bellman/src/gadgets/num.rs +++ b/bellman/src/gadgets/num.rs @@ -254,8 +254,7 @@ impl AllocatedNum { let var = cs.alloc( || "squared num", || { - let mut tmp = *self.value.get()?; - tmp.square(); + let tmp = self.value.get()?.square(); value = Some(tmp); diff --git a/bellman/src/groth16/tests/dummy_engine.rs b/bellman/src/groth16/tests/dummy_engine.rs index 224f84e..0e722f2 100644 --- a/bellman/src/groth16/tests/dummy_engine.rs +++ b/bellman/src/groth16/tests/dummy_engine.rs @@ -140,8 +140,8 @@ impl Field for Fr { (self.0).0 == 0 } - fn square(&mut self) { - self.0 = (self.0 * self.0) % MODULUS_R; + fn square(&self) -> Self { + Fr((self.0 * self.0) % MODULUS_R) } fn double(&self) -> Self { @@ -191,22 +191,21 @@ impl SqrtField for Fr { while t != ::one() { let mut i = 1; { - let mut t2i = t; - t2i.square(); + let mut t2i = t.square(); loop { if t2i == ::one() { break; } - t2i.square(); + t2i = t2i.square(); i += 1; } } for _ in 0..(m - i - 1) { - c.square(); + c = c.square(); } MulAssign::mul_assign(&mut r, &c); - c.square(); + c = c.square(); MulAssign::mul_assign(&mut t, &c); m = i; } diff --git a/bellman/tests/mimc.rs b/bellman/tests/mimc.rs index 0792af5..a1de0f1 100644 --- a/bellman/tests/mimc.rs +++ b/bellman/tests/mimc.rs @@ -41,8 +41,7 @@ fn mimc(mut xl: E::Fr, mut xr: E::Fr, constants: &[E::Fr]) -> E::Fr { for i in 0..MIMC_ROUNDS { let mut tmp1 = xl; tmp1.add_assign(&constants[i]); - let mut tmp2 = tmp1; - tmp2.square(); + let mut tmp2 = tmp1.square(); tmp2.mul_assign(&tmp1); tmp2.add_assign(&xr); xr = xl; @@ -88,8 +87,7 @@ impl<'a, E: Engine> Circuit for MiMCDemo<'a, E> { // tmp = (xL + Ci)^2 let tmp_value = xl_value.map(|mut e| { e.add_assign(&self.constants[i]); - e.square(); - e + e.square() }); let tmp = cs.alloc( || "tmp", diff --git a/ff/ff_derive/src/lib.rs b/ff/ff_derive/src/lib.rs index 88146b3..73b560b 100644 --- a/ff/ff_derive/src/lib.rs +++ b/ff/ff_derive/src/lib.rs @@ -447,8 +447,7 @@ fn prime_field_constants_and_sqrt( let mut a1 = self.pow(#mod_minus_3_over_4); - let mut a0 = a1; - a0.square(); + let mut a0 = a1.square(); a0.mul_assign(self); if a0.0 == #repr(#rneg) { @@ -484,22 +483,21 @@ fn prime_field_constants_and_sqrt( while t != Self::one() { let mut i = 1; { - let mut t2i = t; - t2i.square(); + let mut t2i = t.square(); loop { if t2i == Self::one() { break; } - t2i.square(); + t2i = t2i.square(); i += 1; } } for _ in 0..(m - i - 1) { - c.square(); + c = c.square(); } r.mul_assign(&c); - c.square(); + c = c.square(); t.mul_assign(&c); m = i; } @@ -715,7 +713,9 @@ fn prime_field_impl( ); gen.extend(quote! { - self.mont_reduce(#mont_calling); + let mut ret = *self; + ret.mont_reduce(#mont_calling); + ret }); gen @@ -1113,7 +1113,7 @@ fn prime_field_impl( } #[inline] - fn square(&mut self) + fn square(&self) -> Self { #squaring_impl } diff --git a/ff/src/lib.rs b/ff/src/lib.rs index fd8d45d..10975a3 100644 --- a/ff/src/lib.rs +++ b/ff/src/lib.rs @@ -51,7 +51,8 @@ pub trait Field: fn is_zero(&self) -> bool; /// Squares this element. - fn square(&mut self); + #[must_use] + fn square(&self) -> Self; /// Doubles this element. #[must_use] @@ -73,7 +74,7 @@ pub trait Field: for i in BitIterator::new(exp) { if found_one { - res.square(); + res = res.square(); } else { found_one = i; } diff --git a/pairing/benches/bls12_381/fq.rs b/pairing/benches/bls12_381/fq.rs index 046491e..bd4ed15 100644 --- a/pairing/benches/bls12_381/fq.rs +++ b/pairing/benches/bls12_381/fq.rs @@ -210,8 +210,7 @@ fn bench_fq_square(b: &mut ::test::Bencher) { let mut count = 0; b.iter(|| { - let mut tmp = v[count]; - tmp.square(); + let tmp = v[count].square(); count = (count + 1) % SAMPLES; tmp }); @@ -264,11 +263,7 @@ fn bench_fq_sqrt(b: &mut ::test::Bencher) { ]); let v: Vec = (0..SAMPLES) - .map(|_| { - let mut tmp = Fq::random(&mut rng); - tmp.square(); - tmp - }) + .map(|_| Fq::random(&mut rng).square()) .collect(); let mut count = 0; diff --git a/pairing/benches/bls12_381/fq12.rs b/pairing/benches/bls12_381/fq12.rs index 0eab387..b79bf5c 100644 --- a/pairing/benches/bls12_381/fq12.rs +++ b/pairing/benches/bls12_381/fq12.rs @@ -84,8 +84,7 @@ fn bench_fq12_squaring(b: &mut ::test::Bencher) { let mut count = 0; b.iter(|| { - let mut tmp = v[count]; - tmp.square(); + let tmp = v[count].square(); count = (count + 1) % SAMPLES; tmp }); diff --git a/pairing/benches/bls12_381/fq2.rs b/pairing/benches/bls12_381/fq2.rs index 7862ea3..ace0171 100644 --- a/pairing/benches/bls12_381/fq2.rs +++ b/pairing/benches/bls12_381/fq2.rs @@ -84,8 +84,7 @@ fn bench_fq2_squaring(b: &mut ::test::Bencher) { let mut count = 0; b.iter(|| { - let mut tmp = v[count]; - tmp.square(); + let tmp = v[count].square(); count = (count + 1) % SAMPLES; tmp }); diff --git a/pairing/benches/bls12_381/fr.rs b/pairing/benches/bls12_381/fr.rs index 16a5c08..e4d07d2 100644 --- a/pairing/benches/bls12_381/fr.rs +++ b/pairing/benches/bls12_381/fr.rs @@ -210,8 +210,7 @@ fn bench_fr_square(b: &mut ::test::Bencher) { let mut count = 0; b.iter(|| { - let mut tmp = v[count]; - tmp.square(); + let tmp = v[count].square(); count = (count + 1) % SAMPLES; tmp }); @@ -264,11 +263,7 @@ fn bench_fr_sqrt(b: &mut ::test::Bencher) { ]); let v: Vec = (0..SAMPLES) - .map(|_| { - let mut tmp = Fr::random(&mut rng); - tmp.square(); - tmp - }) + .map(|_| Fr::random(&mut rng).square()) .collect(); let mut count = 0; diff --git a/pairing/src/bls12_381/ec.rs b/pairing/src/bls12_381/ec.rs index 6f45592..abf6873 100644 --- a/pairing/src/bls12_381/ec.rs +++ b/pairing/src/bls12_381/ec.rs @@ -54,10 +54,8 @@ macro_rules! curve_impl { // are equal when (X * Z^2) = (X' * Z'^2) // and (Y * Z^3) = (Y' * Z'^3). - let mut z1 = self.z; - z1.square(); - let mut z2 = other.z; - z2.square(); + let mut z1 = self.z.square(); + let mut z2 = other.z.square(); let mut tmp1 = self.x; tmp1.mul_assign(&z2); @@ -101,8 +99,7 @@ macro_rules! curve_impl { /// largest y-coordinate be selected. fn get_point_from_x(x: $basefield, greatest: bool) -> Option<$affine> { // Compute x^3 + b - let mut x3b = x; - x3b.square(); + let mut x3b = x.square(); x3b.mul_assign(&x); x3b.add_assign(&$affine::get_coeff_b()); @@ -122,11 +119,9 @@ macro_rules! curve_impl { true } else { // Check that the point is on the curve - let mut y2 = self.y; - y2.square(); + let y2 = self.y.square(); - let mut x3b = self.x; - x3b.square(); + let mut x3b = self.x.square(); x3b.mul_assign(&self.x); x3b.add_assign(&Self::get_coeff_b()); @@ -283,8 +278,7 @@ macro_rules! curve_impl { // Perform affine transformations for g in v.iter_mut().filter(|g| !g.is_normalized()) { - let mut z = g.z; // 1/z - z.square(); // 1/z^2 + let mut z = g.z.square(); // 1/z^2 g.x.mul_assign(&z); // x/z^2 z.mul_assign(&g.z); // 1/z^3 g.y.mul_assign(&z); // y/z^3 @@ -305,21 +299,18 @@ macro_rules! curve_impl { // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l // A = X1^2 - let mut a = self.x; - a.square(); + let a = self.x.square(); // B = Y1^2 - let mut b = self.y; - b.square(); + let b = self.y.square(); // C = B^2 - let mut c = b; - c.square(); + let mut c = b.square(); // D = 2*((X1+B)2-A-C) let mut d = self.x; d.add_assign(&b); - d.square(); + d = d.square(); d.sub_assign(&a); d.sub_assign(&c); d = d.double(); @@ -329,8 +320,7 @@ macro_rules! curve_impl { e.add_assign(&a); // F = E^2 - let mut f = e; - f.square(); + let f = e.square(); // Z3 = 2*Y1*Z1 self.z.mul_assign(&self.y); @@ -362,12 +352,10 @@ macro_rules! curve_impl { // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl // Z1Z1 = Z1^2 - let mut z1z1 = self.z; - z1z1.square(); + let z1z1 = self.z.square(); // Z2Z2 = Z2^2 - let mut z2z2 = other.z; - z2z2.square(); + let z2z2 = other.z.square(); // U1 = X1*Z2Z2 let mut u1 = self.x; @@ -398,8 +386,7 @@ macro_rules! curve_impl { h.sub_assign(&u1); // I = (2*H)^2 - let mut i = h.double(); - i.square(); + let i = h.double().square(); // J = H*I let mut j = h; @@ -415,8 +402,7 @@ macro_rules! curve_impl { v.mul_assign(&i); // X3 = r^2 - J - 2*V - self.x = r; - self.x.square(); + self.x = r.square(); self.x.sub_assign(&j); self.x.sub_assign(&v); self.x.sub_assign(&v); @@ -431,7 +417,7 @@ macro_rules! curve_impl { // Z3 = ((Z1+Z2)^2 - Z1Z1 - Z2Z2)*H self.z.add_assign(&other.z); - self.z.square(); + self.z = self.z.square(); self.z.sub_assign(&z1z1); self.z.sub_assign(&z2z2); self.z.mul_assign(&h); @@ -453,8 +439,7 @@ macro_rules! curve_impl { // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl // Z1Z1 = Z1^2 - let mut z1z1 = self.z; - z1z1.square(); + let z1z1 = self.z.square(); // U2 = X2*Z1Z1 let mut u2 = other.x; @@ -476,8 +461,7 @@ macro_rules! curve_impl { h.sub_assign(&self.x); // HH = H^2 - let mut hh = h; - hh.square(); + let hh = h.square(); // I = 4*HH let i = hh.double().double(); @@ -496,8 +480,7 @@ macro_rules! curve_impl { v.mul_assign(&i); // X3 = r^2 - J - 2*V - self.x = r; - self.x.square(); + self.x = r.square(); self.x.sub_assign(&j); self.x.sub_assign(&v); self.x.sub_assign(&v); @@ -512,7 +495,7 @@ macro_rules! curve_impl { // Z3 = (Z1+H)^2-Z1Z1-HH self.z.add_assign(&h); - self.z.square(); + self.z = self.z.square(); self.z.sub_assign(&z1z1); self.z.sub_assign(&hh); } @@ -589,8 +572,7 @@ macro_rules! curve_impl { } else { // Z is nonzero, so it must have an inverse in a field. let zinv = p.z.inverse().unwrap(); - let mut zinv_powered = zinv; - zinv_powered.square(); + let mut zinv_powered = zinv.square(); // X/Z^2 let mut x = p.x; @@ -933,8 +915,7 @@ pub mod g1 { let mut i = 0; loop { // y^2 = x^3 + b - let mut rhs = x; - rhs.square(); + let mut rhs = x.square(); rhs.mul_assign(&x); rhs.add_assign(&G1Affine::get_coeff_b()); @@ -1638,8 +1619,7 @@ pub mod g2 { let mut i = 0; loop { // y^2 = x^3 + b - let mut rhs = x; - rhs.square(); + let mut rhs = x.square(); rhs.mul_assign(&x); rhs.add_assign(&G2Affine::get_coeff_b()); diff --git a/pairing/src/bls12_381/fq.rs b/pairing/src/bls12_381/fq.rs index 77c85ea..28326f4 100644 --- a/pairing/src/bls12_381/fq.rs +++ b/pairing/src/bls12_381/fq.rs @@ -1930,7 +1930,7 @@ fn test_fq_mul_assign() { #[test] fn test_fq_squaring() { - let mut a = Fq(FqRepr([ + let a = Fq(FqRepr([ 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, @@ -1939,9 +1939,8 @@ fn test_fq_squaring() { 0x19ffffffffffffff, ])); assert!(a.is_valid()); - a.square(); assert_eq!( - a, + a.square(), Fq::from_repr(FqRepr([ 0x1cfb28fe7dfbbb86, 0x24cbe1731577a59, @@ -1961,14 +1960,7 @@ fn test_fq_squaring() { for _ in 0..1000000 { // Ensure that (a * a) = a^2 let a = Fq::random(&mut rng); - - let mut tmp = a; - tmp.square(); - - let mut tmp2 = a; - tmp2.mul_assign(&a); - - assert_eq!(tmp, tmp2); + assert_eq!(a.square(), a * a); } } @@ -2071,8 +2063,7 @@ fn test_fq_sqrt() { // Ensure sqrt(a^2) = a or -a let a = Fq::random(&mut rng); let nega = a.neg(); - let mut b = a; - b.square(); + let b = a.square(); let b = b.sqrt().unwrap(); @@ -2083,10 +2074,8 @@ fn test_fq_sqrt() { // Ensure sqrt(a)^2 = a for random a let a = Fq::random(&mut rng); - if let Some(mut tmp) = a.sqrt() { - tmp.square(); - - assert_eq!(a, tmp); + if let Some(tmp) = a.sqrt() { + assert_eq!(a, tmp.square()); } } } diff --git a/pairing/src/bls12_381/fq12.rs b/pairing/src/bls12_381/fq12.rs index d072725..77670e4 100644 --- a/pairing/src/bls12_381/fq12.rs +++ b/pairing/src/bls12_381/fq12.rs @@ -199,7 +199,7 @@ impl Field for Fq12 { self.c1.c2.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]); } - fn square(&mut self) { + fn square(&self) -> Self { let mut ab = self.c0; ab.mul_assign(&self.c1); let mut c0c1 = self.c0; @@ -209,18 +209,16 @@ impl Field for Fq12 { c0.add_assign(&self.c0); c0.mul_assign(&c0c1); c0.sub_assign(&ab); - self.c1 = ab; - self.c1.add_assign(&ab); + let mut c1 = ab; + c1.add_assign(&ab); ab.mul_by_nonresidue(); c0.sub_assign(&ab); - self.c0 = c0; + Fq12 { c0, c1 } } fn inverse(&self) -> Option { - let mut c0s = self.c0; - c0s.square(); - let mut c1s = self.c1; - c1s.square(); + let mut c0s = self.c0.square(); + let mut c1s = self.c1.square(); c1s.mul_by_nonresidue(); c0s.sub_assign(&c1s); diff --git a/pairing/src/bls12_381/fq2.rs b/pairing/src/bls12_381/fq2.rs index 137c1ba..f271913 100644 --- a/pairing/src/bls12_381/fq2.rs +++ b/pairing/src/bls12_381/fq2.rs @@ -46,10 +46,8 @@ impl Fq2 { /// Norm of Fq2 as extension field in i over Fq pub fn norm(&self) -> Fq { - let mut t0 = self.c0; - let mut t1 = self.c1; - t0.square(); - t1.square(); + let t0 = self.c0.square(); + let mut t1 = self.c1.square(); t1.add_assign(&t0); t1 @@ -198,7 +196,7 @@ impl Field for Fq2 { self.c0.is_zero() && self.c1.is_zero() } - fn square(&mut self) { + fn square(&self) -> Self { let mut ab = self.c0; ab.mul_assign(&self.c1); let mut c0c1 = self.c0; @@ -207,10 +205,10 @@ impl Field for Fq2 { c0.add_assign(&self.c0); c0.mul_assign(&c0c1); c0.sub_assign(&ab); - self.c1 = ab; - self.c1.add_assign(&ab); + let mut c1 = ab; + c1.add_assign(&ab); c0.add_assign(&ab); - self.c0 = c0; + Fq2 { c0, c1 } } fn double(&self) -> Self { @@ -221,10 +219,8 @@ impl Field for Fq2 { } fn inverse(&self) -> Option { - let mut t1 = self.c1; - t1.square(); - let mut t0 = self.c0; - t0.square(); + let t1 = self.c1.square(); + let mut t0 = self.c0.square(); t0.add_assign(&t1); t0.inverse().map(|t| Fq2 { c0: self.c0.mul(&t), @@ -257,8 +253,7 @@ impl SqrtField for Fq2 { 0x92c6e9ed90d2eb35, 0x680447a8e5ff9a6, ]); - let mut alpha = a1; - alpha.square(); + let mut alpha = a1.square(); alpha.mul_assign(self); let mut a0 = alpha; a0.frobenius_map(1); @@ -353,32 +348,30 @@ fn test_fq2_squaring() { use super::fq::FqRepr; use ff::PrimeField; - let mut a = Fq2 { + let a = Fq2 { c0: Fq::one(), c1: Fq::one(), }; // u + 1 - a.square(); assert_eq!( - a, + a.square(), Fq2 { c0: Fq::zero(), c1: Fq::from_repr(FqRepr::from(2)).unwrap(), } ); // 2u - let mut a = Fq2 { + let a = Fq2 { c0: Fq::zero(), c1: Fq::one(), }; // u - a.square(); - assert_eq!(a, { + assert_eq!(a.square(), { Fq2 { c0: Fq::one().neg(), c1: Fq::zero(), } }); // -1 - let mut a = Fq2 { + let a = Fq2 { c0: Fq::from_repr(FqRepr([ 0x9c2c6309bbf8b598, 0x4eef5c946536f602, @@ -398,9 +391,8 @@ fn test_fq2_squaring() { ])) .unwrap(), }; - a.square(); assert_eq!( - a, + a.square(), Fq2 { c0: Fq::from_repr(FqRepr([ 0xf262c28c538bcf68, diff --git a/pairing/src/bls12_381/fq6.rs b/pairing/src/bls12_381/fq6.rs index 8e5b394..f8cb619 100644 --- a/pairing/src/bls12_381/fq6.rs +++ b/pairing/src/bls12_381/fq6.rs @@ -303,35 +303,35 @@ impl Field for Fq6 { self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]); } - fn square(&mut self) { - let mut s0 = self.c0; - s0.square(); + fn square(&self) -> Self { + let s0 = self.c0.square(); let mut ab = self.c0; ab.mul_assign(&self.c1); let s1 = ab.double(); let mut s2 = self.c0; s2.sub_assign(&self.c1); s2.add_assign(&self.c2); - s2.square(); + s2 = s2.square(); let mut bc = self.c1; bc.mul_assign(&self.c2); let s3 = bc.double(); - let mut s4 = self.c2; - s4.square(); + let s4 = self.c2.square(); - self.c0 = s3; - self.c0.mul_by_nonresidue(); - self.c0.add_assign(&s0); + let mut c0 = s3; + c0.mul_by_nonresidue(); + c0.add_assign(&s0); - self.c1 = s4; - self.c1.mul_by_nonresidue(); - self.c1.add_assign(&s1); + let mut c1 = s4; + c1.mul_by_nonresidue(); + 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); + let mut c2 = s1; + c2.add_assign(&s2); + c2.add_assign(&s3); + c2.sub_assign(&s0); + c2.sub_assign(&s4); + + Fq6 { c0, c1, c2 } } fn inverse(&self) -> Option { @@ -340,20 +340,17 @@ impl Field for Fq6 { c0.mul_assign(&self.c1); c0 = c0.neg(); { - let mut c0s = self.c0; - c0s.square(); + let c0s = self.c0.square(); c0.add_assign(&c0s); } - let mut c1 = self.c2; - c1.square(); + let mut c1 = self.c2.square(); c1.mul_by_nonresidue(); { let mut c01 = self.c0; c01.mul_assign(&self.c1); c1.sub_assign(&c01); } - let mut c2 = self.c1; - c2.square(); + let mut c2 = self.c1.square(); { let mut c02 = self.c0; c02.mul_assign(&self.c2); diff --git a/pairing/src/bls12_381/fr.rs b/pairing/src/bls12_381/fr.rs index 21832de..777aa87 100644 --- a/pairing/src/bls12_381/fr.rs +++ b/pairing/src/bls12_381/fr.rs @@ -693,16 +693,15 @@ fn test_fr_mul_assign() { #[test] fn test_fr_squaring() { - let mut a = Fr(FrRepr([ + let a = Fr(FrRepr([ 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x73eda753299d7d47, ])); assert!(a.is_valid()); - a.square(); assert_eq!( - a, + a.square(), Fr::from_repr(FrRepr([ 0xc0d698e7bde077b8, 0xb79a310579e76ec2, @@ -720,14 +719,7 @@ fn test_fr_squaring() { for _ in 0..1000000 { // Ensure that (a * a) = a^2 let a = Fr::random(&mut rng); - - let mut tmp = a; - tmp.square(); - - let mut tmp2 = a; - tmp2.mul_assign(&a); - - assert_eq!(tmp, tmp2); + assert_eq!(a.square(), a * a); } } @@ -830,8 +822,7 @@ fn test_fr_sqrt() { // Ensure sqrt(a^2) = a or -a let a = Fr::random(&mut rng); let nega = a.neg(); - let mut b = a; - b.square(); + let b = a.square(); let b = b.sqrt().unwrap(); @@ -842,10 +833,8 @@ fn test_fr_sqrt() { // Ensure sqrt(a)^2 = a for random a let a = Fr::random(&mut rng); - if let Some(mut tmp) = a.sqrt() { - tmp.square(); - - assert_eq!(a, tmp); + if let Some(tmp) = a.sqrt() { + assert_eq!(a, tmp.square()); } } } diff --git a/pairing/src/bls12_381/mod.rs b/pairing/src/bls12_381/mod.rs index 0a3813d..5843e94 100644 --- a/pairing/src/bls12_381/mod.rs +++ b/pairing/src/bls12_381/mod.rs @@ -97,7 +97,7 @@ impl Engine for Bls12 { } } - f.square(); + f = f.square(); } for &mut (p, ref mut coeffs) in &mut pairs { @@ -131,8 +131,7 @@ impl Engine for Bls12 { } let mut x = BLS_X; - let mut y0 = r; - y0.square(); + let y0 = r.square(); let mut y1 = y0; exp_by_x(&mut y1, x); x >>= 1; @@ -185,18 +184,15 @@ impl G2Prepared { fn doubling_step(r: &mut G2) -> (Fq2, Fq2, Fq2) { // Adaptation of Algorithm 26, https://eprint.iacr.org/2010/354.pdf - let mut tmp0 = r.x; - tmp0.square(); + let mut tmp0 = r.x.square(); - let mut tmp1 = r.y; - tmp1.square(); + let mut tmp1 = r.y.square(); - let mut tmp2 = tmp1; - tmp2.square(); + let mut tmp2 = tmp1.square(); let mut tmp3 = tmp1; tmp3.add_assign(&r.x); - tmp3.square(); + tmp3 = tmp3.square(); tmp3.sub_assign(&tmp0); tmp3.sub_assign(&tmp2); tmp3 = tmp3.double(); @@ -207,18 +203,16 @@ impl G2Prepared { let mut tmp6 = r.x; tmp6.add_assign(&tmp4); - let mut tmp5 = tmp4; - tmp5.square(); + let tmp5 = tmp4.square(); - let mut zsquared = r.z; - zsquared.square(); + let zsquared = r.z.square(); r.x = tmp5; r.x.sub_assign(&tmp3); r.x.sub_assign(&tmp3); r.z.add_assign(&r.y); - r.z.square(); + r.z = r.z.square(); r.z.sub_assign(&tmp1); r.z.sub_assign(&zsquared); @@ -234,7 +228,7 @@ impl G2Prepared { tmp3.mul_assign(&zsquared); tmp3 = tmp3.double().neg(); - tmp6.square(); + tmp6 = tmp6.square(); tmp6.sub_assign(&tmp0); tmp6.sub_assign(&tmp5); @@ -251,18 +245,16 @@ impl G2Prepared { fn addition_step(r: &mut G2, q: &G2Affine) -> (Fq2, Fq2, Fq2) { // Adaptation of Algorithm 27, https://eprint.iacr.org/2010/354.pdf - let mut zsquared = r.z; - zsquared.square(); + let zsquared = r.z.square(); - let mut ysquared = q.y; - ysquared.square(); + let ysquared = q.y.square(); let mut t0 = zsquared; t0.mul_assign(&q.x); let mut t1 = q.y; t1.add_assign(&r.z); - t1.square(); + t1 = t1.square(); t1.sub_assign(&ysquared); t1.sub_assign(&zsquared); t1.mul_assign(&zsquared); @@ -270,8 +262,7 @@ impl G2Prepared { let mut t2 = t0; t2.sub_assign(&r.x); - let mut t3 = t2; - t3.square(); + let t3 = t2.square(); let t4 = t3.double().double(); @@ -288,14 +279,13 @@ impl G2Prepared { let mut t7 = t4; t7.mul_assign(&r.x); - r.x = t6; - r.x.square(); + r.x = t6.square(); r.x.sub_assign(&t5); r.x.sub_assign(&t7); r.x.sub_assign(&t7); r.z.add_assign(&t2); - r.z.square(); + r.z = r.z.square(); r.z.sub_assign(&zsquared); r.z.sub_assign(&t3); @@ -313,11 +303,10 @@ impl G2Prepared { r.y = t8; r.y.sub_assign(&t0); - t10.square(); + t10 = t10.square(); t10.sub_assign(&ysquared); - let mut ztsquared = r.z; - ztsquared.square(); + let ztsquared = r.z.square(); t10.sub_assign(&ztsquared); diff --git a/pairing/src/bls12_381/tests/mod.rs b/pairing/src/bls12_381/tests/mod.rs index 636fcfe..2fd4deb 100644 --- a/pairing/src/bls12_381/tests/mod.rs +++ b/pairing/src/bls12_381/tests/mod.rs @@ -189,8 +189,7 @@ fn test_g1_uncompressed_invalid_vectors() { let mut x = Fq::one(); loop { - let mut x3b = x; - x3b.square(); + let mut x3b = x.square(); x3b.mul_assign(&x); x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API? @@ -326,8 +325,7 @@ fn test_g2_uncompressed_invalid_vectors() { let mut x = Fq2::one(); loop { - let mut x3b = x; - x3b.square(); + let mut x3b = x.square(); x3b.mul_assign(&x); x3b.add_assign(&Fq2 { c0: Fq::from_repr(FqRepr::from(4)).unwrap(), @@ -422,8 +420,7 @@ fn test_g1_compressed_invalid_vectors() { let mut x = Fq::one(); loop { - let mut x3b = x; - x3b.square(); + let mut x3b = x.square(); x3b.mul_assign(&x); x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API? @@ -447,8 +444,7 @@ fn test_g1_compressed_invalid_vectors() { let mut x = Fq::one(); loop { - let mut x3b = x; - x3b.square(); + let mut x3b = x.square(); x3b.mul_assign(&x); x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API? @@ -553,8 +549,7 @@ fn test_g2_compressed_invalid_vectors() { }; loop { - let mut x3b = x; - x3b.square(); + let mut x3b = x.square(); x3b.mul_assign(&x); x3b.add_assign(&Fq2 { c0: Fq::from_repr(FqRepr::from(4)).unwrap(), @@ -585,8 +580,7 @@ fn test_g2_compressed_invalid_vectors() { }; loop { - let mut x3b = x; - x3b.square(); + let mut x3b = x.square(); x3b.mul_assign(&x); x3b.add_assign(&Fq2 { c0: Fq::from_repr(FqRepr::from(4)).unwrap(), diff --git a/pairing/src/tests/field.rs b/pairing/src/tests/field.rs index 304e142..eaba476 100644 --- a/pairing/src/tests/field.rs +++ b/pairing/src/tests/field.rs @@ -31,8 +31,7 @@ pub fn random_sqrt_tests() { for _ in 0..10000 { let a = F::random(&mut rng); - let mut b = a; - b.square(); + let b = a.square(); assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue); let b = b.sqrt().unwrap(); @@ -43,8 +42,7 @@ pub fn random_sqrt_tests() { let mut c = F::one(); for _ in 0..10000 { - let mut b = c; - b.square(); + let mut b = c.square(); assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue); b = b.sqrt().unwrap(); @@ -218,12 +216,8 @@ fn random_doubling_tests(rng: &mut R) { fn random_squaring_tests(rng: &mut R) { for _ in 0..10000 { - let mut a = F::random(rng); - let mut b = a; - a.mul_assign(&b); - b.square(); - - assert_eq!(a, b); + let a = F::random(rng); + assert_eq!(a * a, a.square()); } } diff --git a/zcash_primitives/src/jubjub/edwards.rs b/zcash_primitives/src/jubjub/edwards.rs index 45975cb..4ae2442 100644 --- a/zcash_primitives/src/jubjub/edwards.rs +++ b/zcash_primitives/src/jubjub/edwards.rs @@ -107,8 +107,7 @@ impl Point { // as dy^2 + 1 = 0 has no solution in Fr. // tmp1 = y^2 - let mut tmp1 = y; - tmp1.square(); + let mut tmp1 = y.square(); // tmp2 = (y^2 * d) + 1 let mut tmp2 = tmp1; @@ -335,17 +334,13 @@ impl Point { // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd // A = X1^2 - let mut a = self.x; - a.square(); + let a = self.x.square(); // B = Y1^2 - let mut b = self.y; - b.square(); + let b = self.y.square(); // C = 2*Z1^2 - let mut c = self.z; - c.square(); - c = c.double(); + let c = self.z.square().double(); // D = a*A // = -A @@ -354,7 +349,7 @@ impl Point { // E = (X1+Y1)^2 - A - B let mut e = self.x; e.add_assign(&self.y); - e.square(); + e = e.square(); e.add_assign(&d); // -A = D e.sub_assign(&b); diff --git a/zcash_primitives/src/jubjub/fs.rs b/zcash_primitives/src/jubjub/fs.rs index aa18590..da9bb3e 100644 --- a/zcash_primitives/src/jubjub/fs.rs +++ b/zcash_primitives/src/jubjub/fs.rs @@ -575,7 +575,7 @@ impl Field for Fs { } #[inline] - fn square(&mut self) { + fn square(&self) -> Self { let mut carry = 0; let r1 = mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); let r2 = mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); @@ -606,7 +606,10 @@ impl Field for Fs { let r5 = adc(r5, 0, &mut carry); let r6 = mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry); let r7 = adc(r7, 0, &mut carry); - self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7); + + let mut ret = *self; + ret.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7); + ret } } @@ -736,8 +739,7 @@ impl SqrtField for Fs { 0x4199cec0404d0ec0, 0x39f6d3a994cebea, ]); - let mut a0 = a1; - a0.square(); + let mut a0 = a1.square(); a0.mul_assign(self); if a0 == NEGATIVE_ONE { @@ -1403,16 +1405,15 @@ fn test_fs_mul_assign() { #[test] fn test_fr_squaring() { - let mut a = Fs(FsRepr([ + let a = Fs(FsRepr([ 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xe7db4ea6533afa8, ])); assert!(a.is_valid()); - a.square(); assert_eq!( - a, + a.square(), Fs::from_repr(FsRepr([ 0x12c7f55cbc52fbaa, 0xdedc98a0b5e6ce9e, @@ -1431,8 +1432,7 @@ fn test_fr_squaring() { // Ensure that (a * a) = a^2 let a = Fs::random(&mut rng); - let mut tmp = a; - tmp.square(); + let tmp = a.square(); let mut tmp2 = a; tmp2.mul_assign(&a); @@ -1538,8 +1538,7 @@ fn test_fs_sqrt() { // Ensure sqrt(a^2) = a or -a let a = Fs::random(&mut rng); let nega = a.neg(); - let mut b = a; - b.square(); + let b = a.square(); let b = b.sqrt().unwrap(); @@ -1550,10 +1549,8 @@ fn test_fs_sqrt() { // Ensure sqrt(a)^2 = a for random a let a = Fs::random(&mut rng); - if let Some(mut tmp) = a.sqrt() { - tmp.square(); - - assert_eq!(a, tmp); + if let Some(tmp) = a.sqrt() { + assert_eq!(a, tmp.square()); } } } diff --git a/zcash_primitives/src/jubjub/montgomery.rs b/zcash_primitives/src/jubjub/montgomery.rs index 5bb052f..a708d02 100644 --- a/zcash_primitives/src/jubjub/montgomery.rs +++ b/zcash_primitives/src/jubjub/montgomery.rs @@ -50,8 +50,7 @@ impl Point { pub fn get_for_x(x: E::Fr, sign: bool, params: &E::Params) -> Option { // Given an x on the curve, y = sqrt(x^3 + A*x^2 + x) - let mut x2 = x; - x2.square(); + let mut x2 = x.square(); let mut rhs = x2; rhs.mul_assign(params.montgomery_a()); @@ -220,8 +219,7 @@ impl Point { delta.add_assign(&tmp); } { - let mut tmp = self.x; - tmp.square(); + let mut tmp = self.x.square(); delta.add_assign(&tmp); tmp = tmp.double(); delta.add_assign(&tmp); @@ -231,8 +229,7 @@ impl Point { delta.mul_assign(&tmp.inverse().expect("y is nonzero so this must be nonzero")); } - let mut x3 = delta; - x3.square(); + let mut x3 = delta.square(); x3.sub_assign(params.montgomery_a()); x3.sub_assign(&self.x); x3.sub_assign(&self.x); @@ -281,8 +278,7 @@ impl Point { ); } - let mut x3 = delta; - x3.square(); + let mut x3 = delta.square(); x3.sub_assign(params.montgomery_a()); x3.sub_assign(&self.x); x3.sub_assign(&other.x); diff --git a/zcash_primitives/src/jubjub/tests.rs b/zcash_primitives/src/jubjub/tests.rs index 2469d58..f0bb464 100644 --- a/zcash_primitives/src/jubjub/tests.rs +++ b/zcash_primitives/src/jubjub/tests.rs @@ -20,11 +20,9 @@ pub fn test_suite(params: &E::Params) { } fn is_on_mont_curve>(x: E::Fr, y: E::Fr, params: &P) -> bool { - let mut lhs = y; - lhs.square(); + let lhs = y.square(); - let mut x2 = x; - x2.square(); + let x2 = x.square(); let mut x3 = x2; x3.mul_assign(&x); @@ -42,11 +40,9 @@ fn is_on_twisted_edwards_curve>( y: E::Fr, params: &P, ) -> bool { - let mut x2 = x; - x2.square(); + let x2 = x.square(); - let mut y2 = y; - y2.square(); + let y2 = y.square(); // -x^2 + y^2 let mut lhs = y2; @@ -346,8 +342,7 @@ fn test_jubjub_params(params: &E::Params) { { // Check that A^2 - 4 is nonsquare: - let mut tmp = params.montgomery_a().clone(); - tmp.square(); + let mut tmp = params.montgomery_a().square(); tmp.sub_assign(&E::Fr::from_str("4").unwrap()); assert!(tmp.legendre() == LegendreSymbol::QuadraticNonResidue); } diff --git a/zcash_proofs/src/circuit/ecc.rs b/zcash_proofs/src/circuit/ecc.rs index 9889a50..29c14a4 100644 --- a/zcash_proofs/src/circuit/ecc.rs +++ b/zcash_proofs/src/circuit/ecc.rs @@ -323,8 +323,7 @@ impl EdwardsPoint { // Compute C = d*A*A let c = AllocatedNum::alloc(cs.namespace(|| "C"), || { - let mut t0 = *a.get_value().get()?; - t0.square(); + let mut t0 = a.get_value().get()?.square(); t0.mul_assign(params.edwards_d()); Ok(t0) @@ -612,8 +611,7 @@ impl MontgomeryPoint { // Compute x'' = lambda^2 - A - x - x' let xprime = AllocatedNum::alloc(cs.namespace(|| "xprime"), || { - let mut t0 = *lambda.get_value().get()?; - t0.square(); + let mut t0 = lambda.get_value().get()?.square(); t0.sub_assign(params.montgomery_a()); t0.sub_assign(self.x.get_value().get()?); t0.sub_assign(other.x.get_value().get()?); From 662be3551fe18c6328882ac083a9ae0370b6f805 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 12 Dec 2019 23:15:48 +0000 Subject: [PATCH 4/4] impl ConditionallySelectable for Field --- Cargo.lock | 4 ++++ bellman/Cargo.toml | 1 + bellman/src/groth16/tests/dummy_engine.rs | 11 +++++++++++ ff/Cargo.toml | 1 + ff/ff_derive/src/lib.rs | 10 ++++++++++ ff/src/lib.rs | 2 ++ pairing/Cargo.toml | 1 + pairing/src/bls12_381/fq12.rs | 10 ++++++++++ pairing/src/bls12_381/fq2.rs | 10 ++++++++++ pairing/src/bls12_381/fq6.rs | 11 +++++++++++ zcash_primitives/Cargo.toml | 1 + zcash_primitives/src/jubjub/fs.rs | 12 ++++++++++++ 12 files changed, 74 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 4b9f5fa..b0dd6de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,6 +80,7 @@ dependencies = [ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -395,6 +396,7 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff_derive 0.4.0", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -617,6 +619,7 @@ dependencies = [ "group 0.2.0", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1020,6 +1023,7 @@ dependencies = [ "ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "secp256k1 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/bellman/Cargo.toml b/bellman/Cargo.toml index 4f125b4..e6996b0 100644 --- a/bellman/Cargo.toml +++ b/bellman/Cargo.toml @@ -22,6 +22,7 @@ crossbeam = { version = "0.7", optional = true } pairing = { version = "0.15.0", path = "../pairing", optional = true } rand_core = "0.5" byteorder = "1" +subtle = "2.2.1" [dev-dependencies] hex-literal = "0.2" diff --git a/bellman/src/groth16/tests/dummy_engine.rs b/bellman/src/groth16/tests/dummy_engine.rs index 0e722f2..5d6422f 100644 --- a/bellman/src/groth16/tests/dummy_engine.rs +++ b/bellman/src/groth16/tests/dummy_engine.rs @@ -10,6 +10,7 @@ use std::cmp::Ordering; use std::fmt; use std::num::Wrapping; use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use subtle::{Choice, ConditionallySelectable}; const MODULUS_R: Wrapping = Wrapping(64513); @@ -22,6 +23,16 @@ impl fmt::Display for Fr { } } +impl ConditionallySelectable for Fr { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + Fr(Wrapping(u32::conditional_select( + &(a.0).0, + &(b.0).0, + choice, + ))) + } +} + impl Neg for Fr { type Output = Self; diff --git a/ff/Cargo.toml b/ff/Cargo.toml index 9ac1f1e..907fcb2 100644 --- a/ff/Cargo.toml +++ b/ff/Cargo.toml @@ -14,6 +14,7 @@ edition = "2018" byteorder = "1" ff_derive = { version = "0.4.0", path = "ff_derive", optional = true } rand_core = "0.5" +subtle = "2.2.1" [features] default = [] diff --git a/ff/ff_derive/src/lib.rs b/ff/ff_derive/src/lib.rs index 73b560b..09d5e12 100644 --- a/ff/ff_derive/src/lib.rs +++ b/ff/ff_derive/src/lib.rs @@ -833,6 +833,16 @@ fn prime_field_impl( } } + impl ::subtle::ConditionallySelectable for #name { + fn conditional_select(a: &#name, b: &#name, choice: ::subtle::Choice) -> #name { + let mut res = [0u64; #limbs]; + for i in 0..#limbs { + res[i] = u64::conditional_select(&(a.0).0[i], &(b.0).0[i], choice); + } + #name(#repr(res)) + } + } + impl ::std::ops::Neg for #name { type Output = #name; diff --git a/ff/src/lib.rs b/ff/src/lib.rs index 10975a3..e59e627 100644 --- a/ff/src/lib.rs +++ b/ff/src/lib.rs @@ -12,6 +12,7 @@ use std::error::Error; use std::fmt; use std::io::{self, Read, Write}; use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use subtle::ConditionallySelectable; /// This trait represents an element of a field. pub trait Field: @@ -24,6 +25,7 @@ pub trait Field: + fmt::Debug + fmt::Display + 'static + + ConditionallySelectable + Add + Sub + Mul diff --git a/pairing/Cargo.toml b/pairing/Cargo.toml index 1c59855..32fc1be 100644 --- a/pairing/Cargo.toml +++ b/pairing/Cargo.toml @@ -21,6 +21,7 @@ byteorder = "1" ff = { version = "0.5.0", path = "../ff", features = ["derive"] } group = { version = "0.2.0", path = "../group" } rand_core = "0.5" +subtle = "2.2.1" [dev-dependencies] rand_xorshift = "0.2" diff --git a/pairing/src/bls12_381/fq12.rs b/pairing/src/bls12_381/fq12.rs index 77670e4..66608fa 100644 --- a/pairing/src/bls12_381/fq12.rs +++ b/pairing/src/bls12_381/fq12.rs @@ -4,6 +4,7 @@ use super::fq6::Fq6; use ff::Field; use rand_core::RngCore; use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use subtle::{Choice, ConditionallySelectable}; /// An element of Fq12, represented by c0 + c1 * w. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -40,6 +41,15 @@ impl Fq12 { } } +impl ConditionallySelectable for Fq12 { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + Fq12 { + c0: Fq6::conditional_select(&a.c0, &b.c0, choice), + c1: Fq6::conditional_select(&a.c1, &b.c1, choice), + } + } +} + impl Neg for Fq12 { type Output = Self; diff --git a/pairing/src/bls12_381/fq2.rs b/pairing/src/bls12_381/fq2.rs index f271913..823c635 100644 --- a/pairing/src/bls12_381/fq2.rs +++ b/pairing/src/bls12_381/fq2.rs @@ -3,6 +3,7 @@ use ff::{Field, SqrtField}; use rand_core::RngCore; use std::cmp::Ordering; use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use subtle::{Choice, ConditionallySelectable}; /// An element of Fq2, represented by c0 + c1 * u. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -54,6 +55,15 @@ impl Fq2 { } } +impl ConditionallySelectable for Fq2 { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + Fq2 { + c0: Fq::conditional_select(&a.c0, &b.c0, choice), + c1: Fq::conditional_select(&a.c1, &b.c1, choice), + } + } +} + impl Neg for Fq2 { type Output = Self; diff --git a/pairing/src/bls12_381/fq6.rs b/pairing/src/bls12_381/fq6.rs index f8cb619..a64d25b 100644 --- a/pairing/src/bls12_381/fq6.rs +++ b/pairing/src/bls12_381/fq6.rs @@ -3,6 +3,7 @@ use super::fq2::Fq2; use ff::Field; use rand_core::RngCore; use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use subtle::{Choice, ConditionallySelectable}; /// An element of Fq6, represented by c0 + c1 * v + c2 * v^(2). #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -100,6 +101,16 @@ impl Fq6 { } } +impl ConditionallySelectable for Fq6 { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + Fq6 { + c0: Fq2::conditional_select(&a.c0, &b.c0, choice), + c1: Fq2::conditional_select(&a.c1, &b.c1, choice), + c2: Fq2::conditional_select(&a.c2, &b.c2, choice), + } + } +} + impl Neg for Fq6 { type Output = Self; diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index 4766c7a..8ebbbb2 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -28,6 +28,7 @@ rand_core = "0.5.1" ripemd160 = { version = "0.8", optional = true } secp256k1 = { version = "=0.15.0", optional = true } sha2 = "0.8" +subtle = "2.2.1" [dev-dependencies] hex-literal = "0.2" diff --git a/zcash_primitives/src/jubjub/fs.rs b/zcash_primitives/src/jubjub/fs.rs index da9bb3e..b1f1d3f 100644 --- a/zcash_primitives/src/jubjub/fs.rs +++ b/zcash_primitives/src/jubjub/fs.rs @@ -6,6 +6,7 @@ use ff::{ }; use rand_core::RngCore; use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use subtle::{Choice, ConditionallySelectable}; use super::ToUniform; @@ -269,6 +270,17 @@ impl From for FsRepr { } } +impl ConditionallySelectable for Fs { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + Fs(FsRepr([ + u64::conditional_select(&(a.0).0[0], &(b.0).0[0], choice), + u64::conditional_select(&(a.0).0[1], &(b.0).0[1], choice), + u64::conditional_select(&(a.0).0[2], &(b.0).0[2], choice), + u64::conditional_select(&(a.0).0[3], &(b.0).0[3], choice), + ])) + } +} + impl Neg for Fs { type Output = Self;