Merge branch 'develop'

This commit is contained in:
Jack Grigg
2020-03-14 10:36:58 +13:00
124 changed files with 15961 additions and 2084 deletions

View File

@@ -28,13 +28,19 @@ 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]
criterion = "0.3"
hex-literal = "0.2"
rand_xorshift = "0.2"
[features]
transparent-inputs = ["ripemd160", "secp256k1"]
[[bench]]
name = "pedersen_hash"
harness = false
[badges]
maintenance = { status = "actively-developed" }

View File

@@ -1,17 +1,10 @@
#![feature(test)]
extern crate pairing;
extern crate rand_core;
extern crate test;
extern crate zcash_primitives;
use criterion::{criterion_group, criterion_main, Criterion};
use pairing::bls12_381::Bls12;
use rand_core::{OsRng, RngCore};
use zcash_primitives::jubjub::JubjubBls12;
use zcash_primitives::pedersen_hash::{pedersen_hash, Personalization};
#[bench]
fn bench_pedersen_hash(b: &mut test::Bencher) {
fn bench_pedersen_hash(c: &mut Criterion) {
let params = JubjubBls12::new();
let rng = &mut OsRng;
let bits = (0..510)
@@ -19,5 +12,10 @@ fn bench_pedersen_hash(b: &mut test::Bencher) {
.collect::<Vec<_>>();
let personalization = Personalization::MerkleTree(31);
b.iter(|| pedersen_hash::<Bls12, _>(personalization, bits.clone(), &params));
c.bench_function("Pedersen hash", |b| {
b.iter(|| pedersen_hash::<Bls12, _>(personalization, bits.clone(), &params))
});
}
criterion_group!(benches, bench_pedersen_hash);
criterion_main!(benches);

View File

@@ -1,4 +1,6 @@
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
use subtle::CtOption;
use super::{montgomery, JubjubEngine, JubjubParams, PrimeOrder, Unknown};
@@ -89,8 +91,14 @@ impl<E: JubjubEngine> Point<E, Unknown> {
y_repr.as_mut()[3] &= 0x7fffffffffffffff;
match E::Fr::from_repr(y_repr) {
Ok(y) => Self::get_for_y(y, x_sign, params)
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "not on curve")),
Ok(y) => {
let p = Self::get_for_y(y, x_sign, params);
if bool::from(p.is_some()) {
Ok(p.unwrap())
} else {
Err(io::Error::new(io::ErrorKind::InvalidInput, "not on curve"))
}
}
Err(_) => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"y is not in field",
@@ -98,14 +106,13 @@ impl<E: JubjubEngine> Point<E, Unknown> {
}
}
pub fn get_for_y(y: E::Fr, sign: bool, params: &E::Params) -> Option<Self> {
pub fn get_for_y(y: E::Fr, sign: bool, params: &E::Params) -> CtOption<Self> {
// Given a y on the curve, x^2 = (y^2 - 1) / (dy^2 + 1)
// This is defined for all valid y-coordinates,
// 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;
@@ -115,33 +122,27 @@ impl<E: JubjubEngine> Point<E, Unknown> {
// tmp1 = y^2 - 1
tmp1.sub_assign(&E::Fr::one());
match tmp2.inverse() {
Some(tmp2) => {
// tmp1 = (y^2 - 1) / (dy^2 + 1)
tmp1.mul_assign(&tmp2);
tmp2.invert().and_then(|tmp2| {
// tmp1 = (y^2 - 1) / (dy^2 + 1)
tmp1.mul_assign(&tmp2);
match tmp1.sqrt() {
Some(mut x) => {
if x.into_repr().is_odd() != sign {
x.negate();
}
let mut t = x;
t.mul_assign(&y);
Some(Point {
x,
y,
t,
z: E::Fr::one(),
_marker: PhantomData,
})
}
None => None,
tmp1.sqrt().map(|mut x| {
if x.into_repr().is_odd() != sign {
x = x.neg();
}
}
None => None,
}
let mut t = x;
t.mul_assign(&y);
Point {
x,
y,
t,
z: E::Fr::one(),
_marker: PhantomData,
}
})
})
}
/// This guarantees the point is in the prime order subgroup
@@ -157,8 +158,9 @@ impl<E: JubjubEngine> Point<E, Unknown> {
let y = E::Fr::random(rng);
let sign = rng.next_u32() % 2 != 0;
if let Some(p) = Self::get_for_y(y, sign, params) {
return p;
let p = Self::get_for_y(y, sign, params);
if bool::from(p.is_some()) {
return p.unwrap();
}
}
}
@@ -210,12 +212,9 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
// 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,
@@ -306,7 +305,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
/// Convert to affine coordinates
pub fn to_xy(&self) -> (E::Fr, E::Fr) {
let zinv = self.z.inverse().unwrap();
let zinv = self.z.invert().unwrap();
let mut x = self.x;
x.mul_assign(&zinv);
@@ -321,8 +320,8 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
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
}
@@ -335,27 +334,22 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
// 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.double();
let c = self.z.square().double();
// 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;
e.add_assign(&self.y);
e.square();
e = e.square();
e.add_assign(&d); // -A = D
e.sub_assign(&b);

View File

@@ -1,10 +1,11 @@
use byteorder::{ByteOrder, LittleEndian};
use ff::{
adc, mac_with_carry, sbb, BitIterator, Field,
LegendreSymbol::{self, *},
PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField,
adc, mac_with_carry, sbb, BitIterator, Field, PrimeField, PrimeFieldDecodingError,
PrimeFieldRepr, SqrtField,
};
use rand_core::RngCore;
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use super::ToUniform;
@@ -256,6 +257,21 @@ impl PrimeFieldRepr for FsRepr {
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Fs(FsRepr);
impl Default for Fs {
fn default() -> Self {
Fs::zero()
}
}
impl ConstantTimeEq for Fs {
fn ct_eq(&self, other: &Fs) -> Choice {
(self.0).0[0].ct_eq(&(other.0).0[0])
& (self.0).0[1].ct_eq(&(other.0).0[1])
& (self.0).0[2].ct_eq(&(other.0).0[2])
& (self.0).0[3].ct_eq(&(other.0).0[3])
}
}
impl ::std::fmt::Display for Fs {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
write!(f, "Fs({})", self.into_repr())
@@ -268,6 +284,166 @@ impl From<Fs> 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;
#[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;
#[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;
@@ -278,7 +454,7 @@ impl PrimeField for Fs {
Ok(r)
} else {
Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0)))
Err(PrimeFieldDecodingError::NotInField)
}
}
@@ -352,45 +528,23 @@ impl Field for Fs {
}
#[inline]
fn add_assign(&mut self, other: &Fs) {
fn double(&self) -> Self {
let mut ret = *self;
// This cannot exceed the backing capacity.
self.0.add_nocarry(&other.0);
ret.0.mul2();
// However, it may need to be reduced.
self.reduce();
ret.reduce();
ret
}
#[inline]
fn double(&mut self) {
// This cannot exceed the backing capacity.
self.0.mul2();
// However, it may need to be reduced.
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() {
let mut tmp = MODULUS;
tmp.sub_noborrow(&self.0);
self.0 = tmp;
}
}
fn inverse(&self) -> Option<Self> {
/// WARNING: THIS IS NOT ACTUALLY CONSTANT TIME YET!
/// THIS WILL BE REPLACED BY THE jubjub CRATE, WHICH IS CONSTANT TIME!
fn invert(&self) -> CtOption<Self> {
if self.is_zero() {
None
CtOption::new(Self::zero(), Choice::from(0))
} else {
// Guajardo Kumar Paar Pelzl
// Efficient Software-Implementation of Finite Fields with Applications to Cryptography
@@ -436,9 +590,9 @@ impl Field for Fs {
}
if u == one {
Some(b)
CtOption::new(b, Choice::from(1))
} else {
Some(c)
CtOption::new(c, Choice::from(1))
}
}
}
@@ -449,36 +603,7 @@ impl Field for Fs {
}
#[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) {
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);
@@ -509,7 +634,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
}
}
@@ -587,7 +715,7 @@ impl Fs {
fn mul_bits<S: AsRef<[u64]>>(&self, bits: BitIterator<S>) -> Self {
let mut res = Self::zero();
for bit in bits {
res.double();
res = res.double();
if bit {
res.add_assign(self)
@@ -611,51 +739,28 @@ impl ToUniform for Fs {
}
impl SqrtField for Fs {
fn legendre(&self) -> LegendreSymbol {
// s = self^((s - 1) // 2)
let s = self.pow([
0x684b872f6b7b965b,
0x53341049e6640841,
0x83339d80809a1d80,
0x73eda753299d7d4,
]);
if s == Self::zero() {
Zero
} else if s == Self::one() {
QuadraticResidue
} else {
QuadraticNonResidue
}
}
fn sqrt(&self) -> Option<Self> {
fn sqrt(&self) -> CtOption<Self> {
// Shank's algorithm for s mod 4 = 3
// https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2)
// a1 = self^((s - 3) // 4)
let mut a1 = self.pow([
let mut a1 = self.pow_vartime([
0xb425c397b5bdcb2d,
0x299a0824f3320420,
0x4199cec0404d0ec0,
0x39f6d3a994cebea,
]);
let mut a0 = a1;
a0.square();
let mut a0 = a1.square();
a0.mul_assign(self);
a1.mul_assign(self);
if a0 == NEGATIVE_ONE {
None
} else {
a1.mul_assign(self);
Some(a1)
}
CtOption::new(a1, !a0.ct_eq(&NEGATIVE_ONE))
}
}
#[test]
fn test_neg_one() {
let mut o = Fs::one();
o.negate();
let o = Fs::one().neg();
assert_eq!(NEGATIVE_ONE, o);
}
@@ -907,27 +1012,6 @@ fn test_fs_repr_sub_noborrow() {
}
}
#[test]
fn test_fs_legendre() {
assert_eq!(QuadraticResidue, Fs::one().legendre());
assert_eq!(Zero, Fs::zero().legendre());
let e = FsRepr([
0x8385eec23df1f88e,
0x9a01fb412b2dba16,
0x4c928edcdd6c22f,
0x9f2df7ef69ecef9,
]);
assert_eq!(QuadraticResidue, Fs::from_repr(e).unwrap().legendre());
let e = FsRepr([
0xe8ed9f299da78568,
0x35efdebc88b2209,
0xc82125cb1f916dbe,
0x6813d2b38c39bd0,
]);
assert_eq!(QuadraticNonResidue, Fs::from_repr(e).unwrap().legendre());
}
#[test]
fn test_fr_repr_add_nocarry() {
let mut rng = XorShiftRng::from_seed([
@@ -1307,16 +1391,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,
@@ -1335,8 +1418,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);
@@ -1346,8 +1428,8 @@ fn test_fr_squaring() {
}
#[test]
fn test_fs_inverse() {
assert!(Fs::zero().inverse().is_none());
fn test_fs_invert() {
assert!(bool::from(Fs::zero().invert().is_none()));
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
@@ -1359,7 +1441,7 @@ fn test_fs_inverse() {
for _ in 0..1000 {
// Ensure that a * a^-1 = 1
let mut a = Fs::random(&mut rng);
let ainv = a.inverse().unwrap();
let ainv = a.invert().unwrap();
a.mul_assign(&ainv);
assert_eq!(a, one);
}
@@ -1374,19 +1456,15 @@ 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);
}
}
#[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());
}
@@ -1399,8 +1477,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());
@@ -1418,7 +1495,7 @@ fn test_fs_pow() {
// Exponentiate by various small numbers and ensure it consists with repeated
// multiplication.
let a = Fs::random(&mut rng);
let target = a.pow(&[i]);
let target = a.pow_vartime(&[i]);
let mut c = Fs::one();
for _ in 0..i {
c.mul_assign(&a);
@@ -1430,7 +1507,7 @@ fn test_fs_pow() {
// Exponentiating by the modulus should have no effect in a prime field.
let a = Fs::random(&mut rng);
assert_eq!(a, a.pow(Fs::char()));
assert_eq!(a, a.pow_vartime(Fs::char()));
}
}
@@ -1446,10 +1523,8 @@ 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 mut b = a;
b.square();
let nega = a.neg();
let b = a.square();
let b = b.sqrt().unwrap();
@@ -1460,10 +1535,9 @@ 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);
let tmp = a.sqrt();
if tmp.is_some().into() {
assert_eq!(a, tmp.unwrap().square());
}
}
}
@@ -1614,7 +1688,7 @@ fn test_fs_root_of_unity() {
Fs::from_repr(FsRepr::from(6)).unwrap()
);
assert_eq!(
Fs::multiplicative_generator().pow([
Fs::multiplicative_generator().pow_vartime([
0x684b872f6b7b965b,
0x53341049e6640841,
0x83339d80809a1d80,
@@ -1622,6 +1696,6 @@ fn test_fs_root_of_unity() {
]),
Fs::root_of_unity()
);
assert_eq!(Fs::root_of_unity().pow([1 << Fs::S]), Fs::one());
assert!(Fs::multiplicative_generator().sqrt().is_none());
assert_eq!(Fs::root_of_unity().pow_vartime([1 << Fs::S]), Fs::one());
assert!(bool::from(Fs::multiplicative_generator().sqrt().is_none()));
}

View File

@@ -195,8 +195,7 @@ impl JubjubParams<Bls12> 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)

View File

@@ -1,4 +1,6 @@
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
use subtle::CtOption;
use super::{edwards, JubjubEngine, JubjubParams, PrimeOrder, Unknown};
@@ -46,11 +48,10 @@ impl<E: JubjubEngine, Subgroup> PartialEq for Point<E, Subgroup> {
}
impl<E: JubjubEngine> Point<E, Unknown> {
pub fn get_for_x(x: E::Fr, sign: bool, params: &E::Params) -> Option<Self> {
pub fn get_for_x(x: E::Fr, sign: bool, params: &E::Params) -> CtOption<Self> {
// 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());
@@ -58,21 +59,18 @@ impl<E: JubjubEngine> Point<E, Unknown> {
x2.mul_assign(&x);
rhs.add_assign(&x2);
match rhs.sqrt() {
Some(mut y) => {
if y.into_repr().is_odd() != sign {
y.negate();
}
Some(Point {
x,
y,
infinity: false,
_marker: PhantomData,
})
rhs.sqrt().map(|mut y| {
if y.into_repr().is_odd() != sign {
y = y.neg();
}
None => None,
}
Point {
x,
y,
infinity: false,
_marker: PhantomData,
}
})
}
/// This guarantees the point is in the prime order subgroup
@@ -88,8 +86,9 @@ impl<E: JubjubEngine> Point<E, Unknown> {
let x = E::Fr::random(rng);
let sign = rng.next_u32() % 2 != 0;
if let Some(p) = Self::get_for_x(x, sign, params) {
return p;
let p = Self::get_for_x(x, sign, params);
if p.is_some().into() {
return p.unwrap();
}
}
}
@@ -139,11 +138,11 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
{
let mut tmp = E::Fr::one();
tmp.sub_assign(&y);
u.mul_assign(&tmp.inverse().unwrap())
u.mul_assign(&tmp.invert().unwrap())
}
let mut v = u;
v.mul_assign(&x.inverse().unwrap());
v.mul_assign(&x.invert().unwrap());
// Scale it into the correct curve constants
v.mul_assign(params.scale());
@@ -189,7 +188,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
pub fn negate(&self) -> Self {
let mut p = self.clone();
p.y.negate();
p.y = p.y.neg();
p
}
@@ -215,24 +214,22 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
{
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();
let mut tmp = self.x.square();
delta.add_assign(&tmp);
tmp.double();
tmp = tmp.double();
delta.add_assign(&tmp);
}
{
let mut tmp = self.y;
tmp.double();
delta.mul_assign(&tmp.inverse().expect("y is nonzero so this must be nonzero"));
let tmp = self.y.double();
// y is nonzero so this must be nonzero
delta.mul_assign(&tmp.invert().unwrap());
}
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);
@@ -241,7 +238,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
y3.sub_assign(&self.x);
y3.mul_assign(&delta);
y3.add_assign(&self.y);
y3.negate();
y3 = y3.neg();
Point {
x: x3,
@@ -275,14 +272,11 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
{
let mut tmp = other.x;
tmp.sub_assign(&self.x);
delta.mul_assign(
&tmp.inverse()
.expect("self.x != other.x, so this must be nonzero"),
);
// self.x != other.x, so this must be nonzero
delta.mul_assign(&tmp.invert().unwrap());
}
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);
@@ -291,7 +285,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
y3.sub_assign(&self.x);
y3.mul_assign(&delta);
y3.add_assign(&self.y);
y3.negate();
y3 = y3.neg();
Point {
x: x3,

View File

@@ -1,6 +1,7 @@
use super::{edwards, montgomery, JubjubEngine, JubjubParams, PrimeOrder};
use ff::{Field, LegendreSymbol, PrimeField, PrimeFieldRepr, SqrtField};
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
use rand_core::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;
@@ -19,11 +20,9 @@ pub fn test_suite<E: JubjubEngine>(params: &E::Params) {
}
fn is_on_mont_curve<E: JubjubEngine, P: JubjubParams<E>>(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);
@@ -41,11 +40,9 @@ fn is_on_twisted_edwards_curve<E: JubjubEngine, P: JubjubParams<E>>(
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;
@@ -237,7 +234,9 @@ fn test_get_for<E: JubjubEngine>(params: &E::Params) {
let y = E::Fr::random(rng);
let sign = rng.next_u32() % 2 == 1;
if let Some(mut p) = edwards::Point::<E, _>::get_for_y(y, sign, params) {
let p = edwards::Point::<E, _>::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);
p = p.negate();
assert!(edwards::Point::<E, _>::get_for_y(y, !sign, params).unwrap() == p);
@@ -309,23 +308,19 @@ fn test_back_and_forth<E: JubjubEngine>(params: &E::Params) {
fn test_jubjub_params<E: JubjubEngine>(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
let mut tmp = *params.montgomery_a();
tmp.double();
assert_eq!(&tmp, params.montgomery_2a());
assert_eq!(&params.montgomery_a().double(), params.montgomery_2a());
}
{
// The twisted Edwards addition law is complete when d is nonsquare
// and a is square.
assert!(params.edwards_d().legendre() == LegendreSymbol::QuadraticNonResidue);
assert!(a.legendre() == LegendreSymbol::QuadraticResidue);
assert!(bool::from(params.edwards_d().sqrt().is_none()));
assert!(bool::from(a.sqrt().is_some()));
}
{
@@ -335,38 +330,37 @@ fn test_jubjub_params<E: JubjubEngine>(params: &E::Params) {
let mut tmp = *params.edwards_d();
// 1 / d is nonsquare
assert!(tmp.inverse().unwrap().legendre() == LegendreSymbol::QuadraticNonResidue);
assert!(bool::from(tmp.invert().unwrap().sqrt().is_none()));
// tmp = -d
tmp.negate();
tmp = tmp.neg();
// -d is nonsquare
assert!(tmp.legendre() == LegendreSymbol::QuadraticNonResidue);
assert!(bool::from(tmp.sqrt().is_none()));
// 1 / -d is nonsquare
assert!(tmp.inverse().unwrap().legendre() == LegendreSymbol::QuadraticNonResidue);
assert!(bool::from(tmp.invert().unwrap().sqrt().is_none()));
}
{
// 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);
assert!(bool::from(tmp.sqrt().is_none()));
}
{
// Check that A - 2 is nonsquare:
let mut tmp = params.montgomery_a().clone();
tmp.sub_assign(&E::Fr::from_str("2").unwrap());
assert!(tmp.legendre() == LegendreSymbol::QuadraticNonResidue);
assert!(bool::from(tmp.sqrt().is_none()));
}
{
// Check the validity of the scaling factor
let mut tmp = a;
tmp.sub_assign(&params.edwards_d());
tmp = tmp.inverse().unwrap();
tmp = tmp.invert().unwrap();
tmp.mul_assign(&E::Fr::from_str("4").unwrap());
tmp = tmp.sqrt().unwrap();
assert_eq!(&tmp, params.scale());

View File

@@ -2,6 +2,7 @@
use crate::jubjub::*;
use ff::{Field, PrimeField, PrimeFieldRepr};
use std::ops::{AddAssign, Neg};
#[derive(Copy, Clone)]
pub enum Personalization {
@@ -57,14 +58,14 @@ where
if a {
tmp.add_assign(&cur);
}
cur.double(); // 2^1 * cur
cur = cur.double(); // 2^1 * cur
if b {
tmp.add_assign(&cur);
}
// conditionally negate
if c {
tmp.negate();
tmp = tmp.neg();
}
acc.add_assign(&tmp);
@@ -74,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
}
}

View File

@@ -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, Neg};
use crate::util::hash_to_scalar;
@@ -188,7 +189,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);

View File

@@ -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},