From 1fdca393bb1eeeabbdd46215a5281e93bd7a95d6 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 21 Apr 2020 19:05:19 +1200 Subject: [PATCH] ff: PrimeField::{is_even, is_odd} --- bellman/src/groth16/tests/dummy_engine.rs | 4 ++++ ff/ff_derive/src/lib.rs | 5 +++++ ff/src/lib.rs | 9 +++++++++ pairing/src/bls12_381/fq.rs | 12 ++++++++++++ pairing/src/bls12_381/fr.rs | 12 ++++++++++++ zcash_primitives/src/jubjub/edwards.rs | 5 ++--- zcash_primitives/src/jubjub/fs.rs | 5 +++++ zcash_primitives/src/jubjub/montgomery.rs | 4 ++-- zcash_primitives/src/jubjub/tests.rs | 2 +- zcash_proofs/src/circuit/sapling.rs | 4 ++-- 10 files changed, 54 insertions(+), 8 deletions(-) diff --git a/bellman/src/groth16/tests/dummy_engine.rs b/bellman/src/groth16/tests/dummy_engine.rs index 2ef9798c8..91f6993d9 100644 --- a/bellman/src/groth16/tests/dummy_engine.rs +++ b/bellman/src/groth16/tests/dummy_engine.rs @@ -332,6 +332,10 @@ impl PrimeField for Fr { FrRepr::from(*self) } + fn is_odd(&self) -> bool { + (self.0).0 % 2 != 0 + } + fn char() -> FrRepr { Fr(MODULUS_R).into() } diff --git a/ff/ff_derive/src/lib.rs b/ff/ff_derive/src/lib.rs index 9a8a74462..17ad39917 100644 --- a/ff/ff_derive/src/lib.rs +++ b/ff/ff_derive/src/lib.rs @@ -1029,6 +1029,11 @@ fn prime_field_impl( r.0 } + #[inline(always)] + fn is_odd(&self) -> bool { + self.into_repr().is_odd() + } + fn char() -> #repr { MODULUS } diff --git a/ff/src/lib.rs b/ff/src/lib.rs index e91210fc9..b2f4d3af6 100644 --- a/ff/src/lib.rs +++ b/ff/src/lib.rs @@ -309,6 +309,15 @@ pub trait PrimeField: Field + From { /// the number is an element of the field. fn into_repr(&self) -> Self::Repr; + /// Returns true iff this element is odd. + fn is_odd(&self) -> bool; + + /// Returns true iff this element is even. + #[inline(always)] + fn is_even(&self) -> bool { + !self.is_odd() + } + /// Returns the field characteristic; the modulus. fn char() -> Self::Repr; diff --git a/pairing/src/bls12_381/fq.rs b/pairing/src/bls12_381/fq.rs index 5a8f17307..8e5d66028 100644 --- a/pairing/src/bls12_381/fq.rs +++ b/pairing/src/bls12_381/fq.rs @@ -2182,6 +2182,18 @@ fn test_fq_display() { ); } +#[test] +fn test_fq_is_odd() { + assert!(!Fq::from(0).is_odd()); + assert!(Fq::from(0).is_even()); + assert!(Fq::from(1).is_odd()); + assert!(!Fq::from(1).is_even()); + assert!(!Fq::from(324834872).is_odd()); + assert!(Fq::from(324834872).is_even()); + assert!(Fq::from(324834873).is_odd()); + assert!(!Fq::from(324834873).is_even()); +} + #[test] fn test_fq_num_bits() { assert_eq!(Fq::NUM_BITS, 381); diff --git a/pairing/src/bls12_381/fr.rs b/pairing/src/bls12_381/fr.rs index 028287d20..cc02d220e 100644 --- a/pairing/src/bls12_381/fr.rs +++ b/pairing/src/bls12_381/fr.rs @@ -950,6 +950,18 @@ fn test_fr_display() { ); } +#[test] +fn test_fr_is_odd() { + assert!(!Fr::from(0).is_odd()); + assert!(Fr::from(0).is_even()); + assert!(Fr::from(1).is_odd()); + assert!(!Fr::from(1).is_even()); + assert!(!Fr::from(324834872).is_odd()); + assert!(Fr::from(324834872).is_even()); + assert!(Fr::from(324834873).is_odd()); + assert!(!Fr::from(324834873).is_even()); +} + #[test] fn test_fr_num_bits() { assert_eq!(Fr::NUM_BITS, 255); diff --git a/zcash_primitives/src/jubjub/edwards.rs b/zcash_primitives/src/jubjub/edwards.rs index 549d44140..cbe4d0be0 100644 --- a/zcash_primitives/src/jubjub/edwards.rs +++ b/zcash_primitives/src/jubjub/edwards.rs @@ -127,7 +127,7 @@ impl Point { tmp1.mul_assign(&tmp2); tmp1.sqrt().map(|mut x| { - if x.into_repr().is_odd() != sign { + if x.is_odd() != sign { x = x.neg(); } @@ -172,9 +172,8 @@ impl Point { assert_eq!(E::Fr::NUM_BITS, 255); - let x_repr = x.into_repr(); let mut y_repr = y.into_repr(); - if x_repr.is_odd() { + if x.is_odd() { y_repr.as_mut()[3] |= 0x8000000000000000u64; } diff --git a/zcash_primitives/src/jubjub/fs.rs b/zcash_primitives/src/jubjub/fs.rs index e163adc37..e4bea138d 100644 --- a/zcash_primitives/src/jubjub/fs.rs +++ b/zcash_primitives/src/jubjub/fs.rs @@ -481,6 +481,11 @@ impl PrimeField for Fs { r.0 } + #[inline(always)] + fn is_odd(&self) -> bool { + self.into_repr().is_odd() + } + fn char() -> FsRepr { MODULUS } diff --git a/zcash_primitives/src/jubjub/montgomery.rs b/zcash_primitives/src/jubjub/montgomery.rs index efdb29dcd..0992637fe 100644 --- a/zcash_primitives/src/jubjub/montgomery.rs +++ b/zcash_primitives/src/jubjub/montgomery.rs @@ -1,4 +1,4 @@ -use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; +use ff::{BitIterator, Field, PrimeField, SqrtField}; use std::ops::{AddAssign, MulAssign, Neg, SubAssign}; use subtle::CtOption; @@ -60,7 +60,7 @@ impl Point { rhs.add_assign(&x2); rhs.sqrt().map(|mut y| { - if y.into_repr().is_odd() != sign { + if y.is_odd() != sign { y = y.neg(); } diff --git a/zcash_primitives/src/jubjub/tests.rs b/zcash_primitives/src/jubjub/tests.rs index 84b3a9649..6f66c4446 100644 --- a/zcash_primitives/src/jubjub/tests.rs +++ b/zcash_primitives/src/jubjub/tests.rs @@ -237,7 +237,7 @@ fn test_get_for(params: &E::Params) { let p = edwards::Point::::get_for_y(y, sign, params); if bool::from(p.is_some()) { let mut p = p.unwrap(); - assert!(p.to_xy().0.into_repr().is_odd() == sign); + assert!(p.to_xy().0.is_odd() == sign); p = p.negate(); assert!(edwards::Point::::get_for_y(y, !sign, params).unwrap() == p); } diff --git a/zcash_proofs/src/circuit/sapling.rs b/zcash_proofs/src/circuit/sapling.rs index c3ddde9c6..7d1fbbabd 100644 --- a/zcash_proofs/src/circuit/sapling.rs +++ b/zcash_proofs/src/circuit/sapling.rs @@ -1,6 +1,6 @@ //! The Sapling circuits. -use ff::{Field, PrimeField, PrimeFieldRepr}; +use ff::{Field, PrimeField}; use bellman::{Circuit, ConstraintSystem, SynthesisError}; @@ -478,7 +478,7 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { // Witness the sign bit let sign_bit = boolean::Boolean::from(boolean::AllocatedBit::alloc( cs.namespace(|| "pk_d bit of x"), - pk_d.map(|e| e.0.into_repr().is_odd()), + pk_d.map(|e| e.0.is_odd()), )?); // Extend the note with pk_d representation