mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-01-31 07:42:15 +00:00
Merge pull request #190 from str4d/ff-more-ops
More ff::Field operator refactoring
This commit is contained in:
commit
e85a9f309f
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -80,6 +80,7 @@ dependencies = [
|
|||||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
@ -395,6 +396,7 @@ dependencies = [
|
|||||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ff_derive 0.4.0",
|
"ff_derive 0.4.0",
|
||||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
@ -617,6 +619,7 @@ dependencies = [
|
|||||||
"group 0.2.0",
|
"group 0.2.0",
|
||||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
@ -1020,6 +1023,7 @@ dependencies = [
|
|||||||
"ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
|
@ -22,6 +22,7 @@ crossbeam = { version = "0.7", optional = true }
|
|||||||
pairing = { version = "0.15.0", path = "../pairing", optional = true }
|
pairing = { version = "0.15.0", path = "../pairing", optional = true }
|
||||||
rand_core = "0.5"
|
rand_core = "0.5"
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
|
subtle = "2.2.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex-literal = "0.2"
|
hex-literal = "0.2"
|
||||||
|
@ -63,7 +63,7 @@ impl<E: ScalarEngine, G: Group<E>> EvaluationDomain<E, G> {
|
|||||||
// Compute omega, the 2^exp primitive root of unity
|
// Compute omega, the 2^exp primitive root of unity
|
||||||
let mut omega = E::Fr::root_of_unity();
|
let mut omega = E::Fr::root_of_unity();
|
||||||
for _ in exp..E::Fr::S {
|
for _ in exp..E::Fr::S {
|
||||||
omega.square();
|
omega = omega.square();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extend the coeffs vector with zeroes if necessary
|
// Extend the coeffs vector with zeroes if necessary
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Window table lookup gadgets.
|
//! Window table lookup gadgets.
|
||||||
|
|
||||||
use ff::{Field, ScalarEngine};
|
use ff::{Field, ScalarEngine};
|
||||||
use std::ops::AddAssign;
|
use std::ops::{AddAssign, Neg};
|
||||||
|
|
||||||
use super::boolean::Boolean;
|
use super::boolean::Boolean;
|
||||||
use super::num::{AllocatedNum, Num};
|
use super::num::{AllocatedNum, Num};
|
||||||
@ -16,8 +16,7 @@ where
|
|||||||
assert_eq!(assignment.len(), 1 << window_size);
|
assert_eq!(assignment.len(), 1 << window_size);
|
||||||
|
|
||||||
for (i, constant) in constants.into_iter().enumerate() {
|
for (i, constant) in constants.into_iter().enumerate() {
|
||||||
let mut cur = assignment[i];
|
let mut cur = assignment[i].neg();
|
||||||
cur.negate();
|
|
||||||
cur.add_assign(constant);
|
cur.add_assign(constant);
|
||||||
assignment[i] = cur;
|
assignment[i] = cur;
|
||||||
for (j, eval) in assignment.iter_mut().enumerate().skip(i + 1) {
|
for (j, eval) in assignment.iter_mut().enumerate().skip(i + 1) {
|
||||||
@ -151,7 +150,7 @@ where
|
|||||||
let y = AllocatedNum::alloc(cs.namespace(|| "y"), || {
|
let y = AllocatedNum::alloc(cs.namespace(|| "y"), || {
|
||||||
let mut tmp = coords[*i.get()?].1;
|
let mut tmp = coords[*i.get()?].1;
|
||||||
if *bits[2].get_value().get()? {
|
if *bits[2].get_value().get()? {
|
||||||
tmp.negate();
|
tmp = tmp.neg();
|
||||||
}
|
}
|
||||||
Ok(tmp)
|
Ok(tmp)
|
||||||
})?;
|
})?;
|
||||||
@ -281,7 +280,7 @@ mod test {
|
|||||||
assert_eq!(res.0.get_value().unwrap(), points[index].0);
|
assert_eq!(res.0.get_value().unwrap(), points[index].0);
|
||||||
let mut tmp = points[index].1;
|
let mut tmp = points[index].1;
|
||||||
if c_val {
|
if c_val {
|
||||||
tmp.negate()
|
tmp = tmp.neg()
|
||||||
}
|
}
|
||||||
assert_eq!(res.1.get_value().unwrap(), tmp);
|
assert_eq!(res.1.get_value().unwrap(), tmp);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ where
|
|||||||
for bit in bits {
|
for bit in bits {
|
||||||
num = num.add_bool_with_coeff(CS::one(), bit, coeff);
|
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()?))?;
|
let input = cs.alloc_input(|| format!("input {}", i), || Ok(*num.get_value().get()?))?;
|
||||||
@ -63,7 +63,7 @@ pub fn compute_multipacking<E: ScalarEngine>(bits: &[bool]) -> Vec<E::Fr> {
|
|||||||
cur.add_assign(&coeff);
|
cur.add_assign(&coeff);
|
||||||
}
|
}
|
||||||
|
|
||||||
coeff.double();
|
coeff = coeff.double();
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push(cur);
|
result.push(cur);
|
||||||
|
@ -177,7 +177,7 @@ impl<E: ScalarEngine> AllocatedNum<E> {
|
|||||||
for bit in result.iter().rev() {
|
for bit in result.iter().rev() {
|
||||||
lc = lc + (coeff, bit.get_variable());
|
lc = lc + (coeff, bit.get_variable());
|
||||||
|
|
||||||
coeff.double();
|
coeff = coeff.double();
|
||||||
}
|
}
|
||||||
|
|
||||||
lc = lc - self.variable;
|
lc = lc - self.variable;
|
||||||
@ -203,7 +203,7 @@ impl<E: ScalarEngine> AllocatedNum<E> {
|
|||||||
for bit in bits.iter() {
|
for bit in bits.iter() {
|
||||||
lc = lc + (coeff, bit.get_variable());
|
lc = lc + (coeff, bit.get_variable());
|
||||||
|
|
||||||
coeff.double();
|
coeff = coeff.double();
|
||||||
}
|
}
|
||||||
|
|
||||||
lc = lc - self.variable;
|
lc = lc - self.variable;
|
||||||
@ -254,8 +254,7 @@ impl<E: ScalarEngine> AllocatedNum<E> {
|
|||||||
let var = cs.alloc(
|
let var = cs.alloc(
|
||||||
|| "squared num",
|
|| "squared num",
|
||||||
|| {
|
|| {
|
||||||
let mut tmp = *self.value.get()?;
|
let tmp = self.value.get()?.square();
|
||||||
tmp.square();
|
|
||||||
|
|
||||||
value = Some(tmp);
|
value = Some(tmp);
|
||||||
|
|
||||||
@ -417,7 +416,7 @@ mod test {
|
|||||||
use pairing::bls12_381::{Bls12, Fr};
|
use pairing::bls12_381::{Bls12, Fr};
|
||||||
use rand_core::SeedableRng;
|
use rand_core::SeedableRng;
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
use std::ops::SubAssign;
|
use std::ops::{Neg, SubAssign};
|
||||||
|
|
||||||
use super::{AllocatedNum, Boolean};
|
use super::{AllocatedNum, Boolean};
|
||||||
use crate::gadgets::test::*;
|
use crate::gadgets::test::*;
|
||||||
@ -519,8 +518,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_into_bits_strict() {
|
fn test_into_bits_strict() {
|
||||||
let mut negone = Fr::one();
|
let negone = Fr::one().neg();
|
||||||
negone.negate();
|
|
||||||
|
|
||||||
let mut cs = TestConstraintSystem::<Bls12>::new();
|
let mut cs = TestConstraintSystem::<Bls12>::new();
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use crate::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::ops::{AddAssign, MulAssign};
|
use std::ops::{AddAssign, MulAssign, Neg};
|
||||||
|
|
||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@ -152,11 +152,7 @@ impl<E: ScalarEngine> TestConstraintSystem<E> {
|
|||||||
pub fn pretty_print(&self) -> String {
|
pub fn pretty_print(&self) -> String {
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
|
|
||||||
let negone = {
|
let negone = E::Fr::one().neg();
|
||||||
let mut tmp = E::Fr::one();
|
|
||||||
tmp.negate();
|
|
||||||
tmp
|
|
||||||
};
|
|
||||||
|
|
||||||
let powers_of_two = (0..E::Fr::NUM_BITS)
|
let powers_of_two = (0..E::Fr::NUM_BITS)
|
||||||
.map(|i| E::Fr::from_str("2").unwrap().pow(&[u64::from(i)]))
|
.map(|i| E::Fr::from_str("2").unwrap().pow(&[u64::from(i)]))
|
||||||
|
@ -330,7 +330,7 @@ impl UInt32 {
|
|||||||
|
|
||||||
all_constants &= bit.is_constant();
|
all_constants &= bit.is_constant();
|
||||||
|
|
||||||
coeff.double();
|
coeff = coeff.double();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,7 +368,7 @@ impl UInt32 {
|
|||||||
|
|
||||||
max_value >>= 1;
|
max_value >>= 1;
|
||||||
i += 1;
|
i += 1;
|
||||||
coeff.double();
|
coeff = coeff.double();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce equality between the sum and result
|
// Enforce equality between the sum and result
|
||||||
|
@ -9,7 +9,8 @@ use rand_core::RngCore;
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::num::Wrapping;
|
use std::num::Wrapping;
|
||||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
use subtle::{Choice, ConditionallySelectable};
|
||||||
|
|
||||||
const MODULUS_R: Wrapping<u32> = Wrapping(64513);
|
const MODULUS_R: Wrapping<u32> = Wrapping(64513);
|
||||||
|
|
||||||
@ -22,6 +23,27 @@ 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;
|
||||||
|
|
||||||
|
fn neg(mut self) -> Self {
|
||||||
|
if !<Fr as Field>::is_zero(&self) {
|
||||||
|
self.0 = MODULUS_R - self.0;
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'r> Add<&'r Fr> for Fr {
|
impl<'r> Add<&'r Fr> for Fr {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@ -129,18 +151,12 @@ impl Field for Fr {
|
|||||||
(self.0).0 == 0
|
(self.0).0 == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn square(&mut self) {
|
fn square(&self) -> Self {
|
||||||
self.0 = (self.0 * self.0) % MODULUS_R;
|
Fr((self.0 * self.0) % MODULUS_R)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn double(&mut self) {
|
fn double(&self) -> Self {
|
||||||
self.0 = (self.0 << 1) % MODULUS_R;
|
Fr((self.0 << 1) % MODULUS_R)
|
||||||
}
|
|
||||||
|
|
||||||
fn negate(&mut self) {
|
|
||||||
if !<Fr as Field>::is_zero(self) {
|
|
||||||
self.0 = MODULUS_R - self.0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inverse(&self) -> Option<Self> {
|
fn inverse(&self) -> Option<Self> {
|
||||||
@ -186,22 +202,21 @@ impl SqrtField for Fr {
|
|||||||
while t != <Fr as Field>::one() {
|
while t != <Fr as Field>::one() {
|
||||||
let mut i = 1;
|
let mut i = 1;
|
||||||
{
|
{
|
||||||
let mut t2i = t;
|
let mut t2i = t.square();
|
||||||
t2i.square();
|
|
||||||
loop {
|
loop {
|
||||||
if t2i == <Fr as Field>::one() {
|
if t2i == <Fr as Field>::one() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t2i.square();
|
t2i = t2i.square();
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..(m - i - 1) {
|
for _ in 0..(m - i - 1) {
|
||||||
c.square();
|
c = c.square();
|
||||||
}
|
}
|
||||||
MulAssign::mul_assign(&mut r, &c);
|
MulAssign::mul_assign(&mut r, &c);
|
||||||
c.square();
|
c = c.square();
|
||||||
MulAssign::mul_assign(&mut t, &c);
|
MulAssign::mul_assign(&mut t, &c);
|
||||||
m = i;
|
m = i;
|
||||||
}
|
}
|
||||||
@ -401,7 +416,7 @@ impl CurveProjective for Fr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn double(&mut self) {
|
fn double(&mut self) {
|
||||||
<Fr as Field>::double(self);
|
self.0 = <Fr as Field>::double(self).0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_assign(&mut self, other: &Self) {
|
fn add_assign(&mut self, other: &Self) {
|
||||||
@ -413,7 +428,7 @@ impl CurveProjective for Fr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn negate(&mut self) {
|
fn negate(&mut self) {
|
||||||
<Fr as Field>::negate(self);
|
self.0 = self.neg().0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S) {
|
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S) {
|
||||||
@ -495,7 +510,7 @@ impl CurveAffine for Fr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn negate(&mut self) {
|
fn negate(&mut self) {
|
||||||
<Fr as Field>::negate(self);
|
self.0 = self.neg().0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective {
|
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective {
|
||||||
|
@ -148,7 +148,7 @@ use std::error::Error;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::marker::PhantomData;
|
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
|
/// Computations are expressed in terms of arithmetic circuits, in particular
|
||||||
/// rank-1 quadratic constraint systems. The `Circuit` trait represents a
|
/// rank-1 quadratic constraint systems. The `Circuit` trait represents a
|
||||||
@ -216,10 +216,8 @@ impl<E: ScalarEngine> Sub<(E::Fr, Variable)> for LinearCombination<E> {
|
|||||||
type Output = LinearCombination<E>;
|
type Output = LinearCombination<E>;
|
||||||
|
|
||||||
#[allow(clippy::suspicious_arithmetic_impl)]
|
#[allow(clippy::suspicious_arithmetic_impl)]
|
||||||
fn sub(self, (mut coeff, var): (E::Fr, Variable)) -> LinearCombination<E> {
|
fn sub(self, (coeff, var): (E::Fr, Variable)) -> LinearCombination<E> {
|
||||||
coeff.negate();
|
self + (coeff.neg(), var)
|
||||||
|
|
||||||
self + (coeff, var)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,8 +41,7 @@ fn mimc<E: Engine>(mut xl: E::Fr, mut xr: E::Fr, constants: &[E::Fr]) -> E::Fr {
|
|||||||
for i in 0..MIMC_ROUNDS {
|
for i in 0..MIMC_ROUNDS {
|
||||||
let mut tmp1 = xl;
|
let mut tmp1 = xl;
|
||||||
tmp1.add_assign(&constants[i]);
|
tmp1.add_assign(&constants[i]);
|
||||||
let mut tmp2 = tmp1;
|
let mut tmp2 = tmp1.square();
|
||||||
tmp2.square();
|
|
||||||
tmp2.mul_assign(&tmp1);
|
tmp2.mul_assign(&tmp1);
|
||||||
tmp2.add_assign(&xr);
|
tmp2.add_assign(&xr);
|
||||||
xr = xl;
|
xr = xl;
|
||||||
@ -88,8 +87,7 @@ impl<'a, E: Engine> Circuit<E> for MiMCDemo<'a, E> {
|
|||||||
// tmp = (xL + Ci)^2
|
// tmp = (xL + Ci)^2
|
||||||
let tmp_value = xl_value.map(|mut e| {
|
let tmp_value = xl_value.map(|mut e| {
|
||||||
e.add_assign(&self.constants[i]);
|
e.add_assign(&self.constants[i]);
|
||||||
e.square();
|
e.square()
|
||||||
e
|
|
||||||
});
|
});
|
||||||
let tmp = cs.alloc(
|
let tmp = cs.alloc(
|
||||||
|| "tmp",
|
|| "tmp",
|
||||||
|
@ -14,6 +14,7 @@ edition = "2018"
|
|||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
ff_derive = { version = "0.4.0", path = "ff_derive", optional = true }
|
ff_derive = { version = "0.4.0", path = "ff_derive", optional = true }
|
||||||
rand_core = "0.5"
|
rand_core = "0.5"
|
||||||
|
subtle = "2.2.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
@ -447,8 +447,7 @@ fn prime_field_constants_and_sqrt(
|
|||||||
|
|
||||||
let mut a1 = self.pow(#mod_minus_3_over_4);
|
let mut a1 = self.pow(#mod_minus_3_over_4);
|
||||||
|
|
||||||
let mut a0 = a1;
|
let mut a0 = a1.square();
|
||||||
a0.square();
|
|
||||||
a0.mul_assign(self);
|
a0.mul_assign(self);
|
||||||
|
|
||||||
if a0.0 == #repr(#rneg) {
|
if a0.0 == #repr(#rneg) {
|
||||||
@ -484,22 +483,21 @@ fn prime_field_constants_and_sqrt(
|
|||||||
while t != Self::one() {
|
while t != Self::one() {
|
||||||
let mut i = 1;
|
let mut i = 1;
|
||||||
{
|
{
|
||||||
let mut t2i = t;
|
let mut t2i = t.square();
|
||||||
t2i.square();
|
|
||||||
loop {
|
loop {
|
||||||
if t2i == Self::one() {
|
if t2i == Self::one() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t2i.square();
|
t2i = t2i.square();
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..(m - i - 1) {
|
for _ in 0..(m - i - 1) {
|
||||||
c.square();
|
c = c.square();
|
||||||
}
|
}
|
||||||
r.mul_assign(&c);
|
r.mul_assign(&c);
|
||||||
c.square();
|
c = c.square();
|
||||||
t.mul_assign(&c);
|
t.mul_assign(&c);
|
||||||
m = i;
|
m = i;
|
||||||
}
|
}
|
||||||
@ -715,7 +713,9 @@ fn prime_field_impl(
|
|||||||
);
|
);
|
||||||
|
|
||||||
gen.extend(quote! {
|
gen.extend(quote! {
|
||||||
self.mont_reduce(#mont_calling);
|
let mut ret = *self;
|
||||||
|
ret.mont_reduce(#mont_calling);
|
||||||
|
ret
|
||||||
});
|
});
|
||||||
|
|
||||||
gen
|
gen
|
||||||
@ -833,6 +833,31 @@ 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;
|
||||||
|
|
||||||
|
#[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 {
|
impl<'r> ::std::ops::Add<&'r #name> for #name {
|
||||||
type Output = #name;
|
type Output = #name;
|
||||||
|
|
||||||
@ -1025,21 +1050,16 @@ fn prime_field_impl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn double(&mut self) {
|
fn double(&self) -> Self {
|
||||||
|
let mut ret = *self;
|
||||||
|
|
||||||
// This cannot exceed the backing capacity.
|
// This cannot exceed the backing capacity.
|
||||||
self.0.mul2();
|
ret.0.mul2();
|
||||||
|
|
||||||
// However, it may need to be reduced.
|
// However, it may need to be reduced.
|
||||||
self.reduce();
|
ret.reduce();
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
ret
|
||||||
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> {
|
fn inverse(&self) -> Option<Self> {
|
||||||
@ -1103,7 +1123,7 @@ fn prime_field_impl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn square(&mut self)
|
fn square(&self) -> Self
|
||||||
{
|
{
|
||||||
#squaring_impl
|
#squaring_impl
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,8 @@ use rand_core::RngCore;
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::{self, Read, Write};
|
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};
|
||||||
|
use subtle::ConditionallySelectable;
|
||||||
|
|
||||||
/// This trait represents an element of a field.
|
/// This trait represents an element of a field.
|
||||||
pub trait Field:
|
pub trait Field:
|
||||||
@ -24,9 +25,11 @@ pub trait Field:
|
|||||||
+ fmt::Debug
|
+ fmt::Debug
|
||||||
+ fmt::Display
|
+ fmt::Display
|
||||||
+ 'static
|
+ 'static
|
||||||
|
+ ConditionallySelectable
|
||||||
+ Add<Output = Self>
|
+ Add<Output = Self>
|
||||||
+ Sub<Output = Self>
|
+ Sub<Output = Self>
|
||||||
+ Mul<Output = Self>
|
+ Mul<Output = Self>
|
||||||
|
+ Neg<Output = Self>
|
||||||
+ for<'a> Add<&'a Self, Output = Self>
|
+ for<'a> Add<&'a Self, Output = Self>
|
||||||
+ for<'a> Mul<&'a Self, Output = Self>
|
+ for<'a> Mul<&'a Self, Output = Self>
|
||||||
+ for<'a> Sub<&'a Self, Output = Self>
|
+ for<'a> Sub<&'a Self, Output = Self>
|
||||||
@ -50,13 +53,12 @@ pub trait Field:
|
|||||||
fn is_zero(&self) -> bool;
|
fn is_zero(&self) -> bool;
|
||||||
|
|
||||||
/// Squares this element.
|
/// Squares this element.
|
||||||
fn square(&mut self);
|
#[must_use]
|
||||||
|
fn square(&self) -> Self;
|
||||||
|
|
||||||
/// Doubles this element.
|
/// Doubles this element.
|
||||||
fn double(&mut self);
|
#[must_use]
|
||||||
|
fn double(&self) -> Self;
|
||||||
/// Negates this element.
|
|
||||||
fn negate(&mut self);
|
|
||||||
|
|
||||||
/// Computes the multiplicative inverse of this element, if nonzero.
|
/// Computes the multiplicative inverse of this element, if nonzero.
|
||||||
fn inverse(&self) -> Option<Self>;
|
fn inverse(&self) -> Option<Self>;
|
||||||
@ -74,7 +76,7 @@ pub trait Field:
|
|||||||
|
|
||||||
for i in BitIterator::new(exp) {
|
for i in BitIterator::new(exp) {
|
||||||
if found_one {
|
if found_one {
|
||||||
res.square();
|
res = res.square();
|
||||||
} else {
|
} else {
|
||||||
found_one = i;
|
found_one = i;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use ff::{Field, PrimeField};
|
use ff::{Field, PrimeField};
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
|
use std::ops::Neg;
|
||||||
|
|
||||||
use crate::{CurveAffine, CurveProjective, EncodedPoint};
|
use crate::{CurveAffine, CurveProjective, EncodedPoint};
|
||||||
|
|
||||||
@ -199,8 +200,7 @@ fn random_negation_tests<G: CurveProjective>() {
|
|||||||
let r = G::random(&mut rng);
|
let r = G::random(&mut rng);
|
||||||
|
|
||||||
let s = G::Scalar::random(&mut rng);
|
let s = G::Scalar::random(&mut rng);
|
||||||
let mut sneg = s;
|
let sneg = s.neg();
|
||||||
sneg.negate();
|
|
||||||
|
|
||||||
let mut t1 = r;
|
let mut t1 = r;
|
||||||
t1.mul_assign(s);
|
t1.mul_assign(s);
|
||||||
|
@ -21,6 +21,7 @@ byteorder = "1"
|
|||||||
ff = { version = "0.5.0", path = "../ff", features = ["derive"] }
|
ff = { version = "0.5.0", path = "../ff", features = ["derive"] }
|
||||||
group = { version = "0.2.0", path = "../group" }
|
group = { version = "0.2.0", path = "../group" }
|
||||||
rand_core = "0.5"
|
rand_core = "0.5"
|
||||||
|
subtle = "2.2.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand_xorshift = "0.2"
|
rand_xorshift = "0.2"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use rand_core::SeedableRng;
|
use rand_core::SeedableRng;
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||||
|
|
||||||
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
|
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
|
||||||
use pairing::bls12_381::*;
|
use pairing::bls12_381::*;
|
||||||
@ -210,8 +210,7 @@ fn bench_fq_square(b: &mut ::test::Bencher) {
|
|||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut tmp = v[count];
|
let tmp = v[count].square();
|
||||||
tmp.square();
|
|
||||||
count = (count + 1) % SAMPLES;
|
count = (count + 1) % SAMPLES;
|
||||||
tmp
|
tmp
|
||||||
});
|
});
|
||||||
@ -236,7 +235,7 @@ fn bench_fq_inverse(b: &mut ::test::Bencher) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_fq_negate(b: &mut ::test::Bencher) {
|
fn bench_fq_neg(b: &mut ::test::Bencher) {
|
||||||
const SAMPLES: usize = 1000;
|
const SAMPLES: usize = 1000;
|
||||||
|
|
||||||
let mut rng = XorShiftRng::from_seed([
|
let mut rng = XorShiftRng::from_seed([
|
||||||
@ -248,8 +247,7 @@ fn bench_fq_negate(b: &mut ::test::Bencher) {
|
|||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut tmp = v[count];
|
let tmp = v[count].neg();
|
||||||
tmp.negate();
|
|
||||||
count = (count + 1) % SAMPLES;
|
count = (count + 1) % SAMPLES;
|
||||||
tmp
|
tmp
|
||||||
});
|
});
|
||||||
@ -265,11 +263,7 @@ fn bench_fq_sqrt(b: &mut ::test::Bencher) {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
let v: Vec<Fq> = (0..SAMPLES)
|
let v: Vec<Fq> = (0..SAMPLES)
|
||||||
.map(|_| {
|
.map(|_| Fq::random(&mut rng).square())
|
||||||
let mut tmp = Fq::random(&mut rng);
|
|
||||||
tmp.square();
|
|
||||||
tmp
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
@ -84,8 +84,7 @@ fn bench_fq12_squaring(b: &mut ::test::Bencher) {
|
|||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut tmp = v[count];
|
let tmp = v[count].square();
|
||||||
tmp.square();
|
|
||||||
count = (count + 1) % SAMPLES;
|
count = (count + 1) % SAMPLES;
|
||||||
tmp
|
tmp
|
||||||
});
|
});
|
||||||
|
@ -84,8 +84,7 @@ fn bench_fq2_squaring(b: &mut ::test::Bencher) {
|
|||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut tmp = v[count];
|
let tmp = v[count].square();
|
||||||
tmp.square();
|
|
||||||
count = (count + 1) % SAMPLES;
|
count = (count + 1) % SAMPLES;
|
||||||
tmp
|
tmp
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use rand_core::SeedableRng;
|
use rand_core::SeedableRng;
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||||
|
|
||||||
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
|
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
|
||||||
use pairing::bls12_381::*;
|
use pairing::bls12_381::*;
|
||||||
@ -210,8 +210,7 @@ fn bench_fr_square(b: &mut ::test::Bencher) {
|
|||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut tmp = v[count];
|
let tmp = v[count].square();
|
||||||
tmp.square();
|
|
||||||
count = (count + 1) % SAMPLES;
|
count = (count + 1) % SAMPLES;
|
||||||
tmp
|
tmp
|
||||||
});
|
});
|
||||||
@ -236,7 +235,7 @@ fn bench_fr_inverse(b: &mut ::test::Bencher) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_fr_negate(b: &mut ::test::Bencher) {
|
fn bench_fr_neg(b: &mut ::test::Bencher) {
|
||||||
const SAMPLES: usize = 1000;
|
const SAMPLES: usize = 1000;
|
||||||
|
|
||||||
let mut rng = XorShiftRng::from_seed([
|
let mut rng = XorShiftRng::from_seed([
|
||||||
@ -248,8 +247,7 @@ fn bench_fr_negate(b: &mut ::test::Bencher) {
|
|||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut tmp = v[count];
|
let tmp = v[count].neg();
|
||||||
tmp.negate();
|
|
||||||
count = (count + 1) % SAMPLES;
|
count = (count + 1) % SAMPLES;
|
||||||
tmp
|
tmp
|
||||||
});
|
});
|
||||||
@ -265,11 +263,7 @@ fn bench_fr_sqrt(b: &mut ::test::Bencher) {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
let v: Vec<Fr> = (0..SAMPLES)
|
let v: Vec<Fr> = (0..SAMPLES)
|
||||||
.map(|_| {
|
.map(|_| Fr::random(&mut rng).square())
|
||||||
let mut tmp = Fr::random(&mut rng);
|
|
||||||
tmp.square();
|
|
||||||
tmp
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
@ -54,10 +54,8 @@ macro_rules! curve_impl {
|
|||||||
// are equal when (X * Z^2) = (X' * Z'^2)
|
// are equal when (X * Z^2) = (X' * Z'^2)
|
||||||
// and (Y * Z^3) = (Y' * Z'^3).
|
// and (Y * Z^3) = (Y' * Z'^3).
|
||||||
|
|
||||||
let mut z1 = self.z;
|
let mut z1 = self.z.square();
|
||||||
z1.square();
|
let mut z2 = other.z.square();
|
||||||
let mut z2 = other.z;
|
|
||||||
z2.square();
|
|
||||||
|
|
||||||
let mut tmp1 = self.x;
|
let mut tmp1 = self.x;
|
||||||
tmp1.mul_assign(&z2);
|
tmp1.mul_assign(&z2);
|
||||||
@ -101,14 +99,12 @@ macro_rules! curve_impl {
|
|||||||
/// largest y-coordinate be selected.
|
/// largest y-coordinate be selected.
|
||||||
fn get_point_from_x(x: $basefield, greatest: bool) -> Option<$affine> {
|
fn get_point_from_x(x: $basefield, greatest: bool) -> Option<$affine> {
|
||||||
// Compute x^3 + b
|
// Compute x^3 + b
|
||||||
let mut x3b = x;
|
let mut x3b = x.square();
|
||||||
x3b.square();
|
|
||||||
x3b.mul_assign(&x);
|
x3b.mul_assign(&x);
|
||||||
x3b.add_assign(&$affine::get_coeff_b());
|
x3b.add_assign(&$affine::get_coeff_b());
|
||||||
|
|
||||||
x3b.sqrt().map(|y| {
|
x3b.sqrt().map(|y| {
|
||||||
let mut negy = y;
|
let negy = y.neg();
|
||||||
negy.negate();
|
|
||||||
|
|
||||||
$affine {
|
$affine {
|
||||||
x: x,
|
x: x,
|
||||||
@ -123,11 +119,9 @@ macro_rules! curve_impl {
|
|||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
// Check that the point is on the curve
|
// Check that the point is on the curve
|
||||||
let mut y2 = self.y;
|
let y2 = self.y.square();
|
||||||
y2.square();
|
|
||||||
|
|
||||||
let mut x3b = self.x;
|
let mut x3b = self.x.square();
|
||||||
x3b.square();
|
|
||||||
x3b.mul_assign(&self.x);
|
x3b.mul_assign(&self.x);
|
||||||
x3b.add_assign(&Self::get_coeff_b());
|
x3b.add_assign(&Self::get_coeff_b());
|
||||||
|
|
||||||
@ -171,7 +165,7 @@ macro_rules! curve_impl {
|
|||||||
|
|
||||||
fn negate(&mut self) {
|
fn negate(&mut self) {
|
||||||
if !self.is_zero() {
|
if !self.is_zero() {
|
||||||
self.y.negate();
|
self.y = self.y.neg();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,8 +278,7 @@ macro_rules! curve_impl {
|
|||||||
|
|
||||||
// Perform affine transformations
|
// Perform affine transformations
|
||||||
for g in v.iter_mut().filter(|g| !g.is_normalized()) {
|
for g in v.iter_mut().filter(|g| !g.is_normalized()) {
|
||||||
let mut z = g.z; // 1/z
|
let mut z = g.z.square(); // 1/z^2
|
||||||
z.square(); // 1/z^2
|
|
||||||
g.x.mul_assign(&z); // x/z^2
|
g.x.mul_assign(&z); // x/z^2
|
||||||
z.mul_assign(&g.z); // 1/z^3
|
z.mul_assign(&g.z); // 1/z^3
|
||||||
g.y.mul_assign(&z); // y/z^3
|
g.y.mul_assign(&z); // y/z^3
|
||||||
@ -306,37 +299,32 @@ macro_rules! curve_impl {
|
|||||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
||||||
|
|
||||||
// A = X1^2
|
// A = X1^2
|
||||||
let mut a = self.x;
|
let a = self.x.square();
|
||||||
a.square();
|
|
||||||
|
|
||||||
// B = Y1^2
|
// B = Y1^2
|
||||||
let mut b = self.y;
|
let b = self.y.square();
|
||||||
b.square();
|
|
||||||
|
|
||||||
// C = B^2
|
// C = B^2
|
||||||
let mut c = b;
|
let mut c = b.square();
|
||||||
c.square();
|
|
||||||
|
|
||||||
// D = 2*((X1+B)2-A-C)
|
// D = 2*((X1+B)2-A-C)
|
||||||
let mut d = self.x;
|
let mut d = self.x;
|
||||||
d.add_assign(&b);
|
d.add_assign(&b);
|
||||||
d.square();
|
d = d.square();
|
||||||
d.sub_assign(&a);
|
d.sub_assign(&a);
|
||||||
d.sub_assign(&c);
|
d.sub_assign(&c);
|
||||||
d.double();
|
d = d.double();
|
||||||
|
|
||||||
// E = 3*A
|
// E = 3*A
|
||||||
let mut e = a;
|
let mut e = a.double();
|
||||||
e.double();
|
|
||||||
e.add_assign(&a);
|
e.add_assign(&a);
|
||||||
|
|
||||||
// F = E^2
|
// F = E^2
|
||||||
let mut f = e;
|
let f = e.square();
|
||||||
f.square();
|
|
||||||
|
|
||||||
// Z3 = 2*Y1*Z1
|
// Z3 = 2*Y1*Z1
|
||||||
self.z.mul_assign(&self.y);
|
self.z.mul_assign(&self.y);
|
||||||
self.z.double();
|
self.z = self.z.double();
|
||||||
|
|
||||||
// X3 = F-2*D
|
// X3 = F-2*D
|
||||||
self.x = f;
|
self.x = f;
|
||||||
@ -347,9 +335,7 @@ macro_rules! curve_impl {
|
|||||||
self.y = d;
|
self.y = d;
|
||||||
self.y.sub_assign(&self.x);
|
self.y.sub_assign(&self.x);
|
||||||
self.y.mul_assign(&e);
|
self.y.mul_assign(&e);
|
||||||
c.double();
|
c = c.double().double().double();
|
||||||
c.double();
|
|
||||||
c.double();
|
|
||||||
self.y.sub_assign(&c);
|
self.y.sub_assign(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,12 +352,10 @@ macro_rules! curve_impl {
|
|||||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
||||||
|
|
||||||
// Z1Z1 = Z1^2
|
// Z1Z1 = Z1^2
|
||||||
let mut z1z1 = self.z;
|
let z1z1 = self.z.square();
|
||||||
z1z1.square();
|
|
||||||
|
|
||||||
// Z2Z2 = Z2^2
|
// Z2Z2 = Z2^2
|
||||||
let mut z2z2 = other.z;
|
let z2z2 = other.z.square();
|
||||||
z2z2.square();
|
|
||||||
|
|
||||||
// U1 = X1*Z2Z2
|
// U1 = X1*Z2Z2
|
||||||
let mut u1 = self.x;
|
let mut u1 = self.x;
|
||||||
@ -402,9 +386,7 @@ macro_rules! curve_impl {
|
|||||||
h.sub_assign(&u1);
|
h.sub_assign(&u1);
|
||||||
|
|
||||||
// I = (2*H)^2
|
// I = (2*H)^2
|
||||||
let mut i = h;
|
let i = h.double().square();
|
||||||
i.double();
|
|
||||||
i.square();
|
|
||||||
|
|
||||||
// J = H*I
|
// J = H*I
|
||||||
let mut j = h;
|
let mut j = h;
|
||||||
@ -413,15 +395,14 @@ macro_rules! curve_impl {
|
|||||||
// r = 2*(S2-S1)
|
// r = 2*(S2-S1)
|
||||||
let mut r = s2;
|
let mut r = s2;
|
||||||
r.sub_assign(&s1);
|
r.sub_assign(&s1);
|
||||||
r.double();
|
r = r.double();
|
||||||
|
|
||||||
// V = U1*I
|
// V = U1*I
|
||||||
let mut v = u1;
|
let mut v = u1;
|
||||||
v.mul_assign(&i);
|
v.mul_assign(&i);
|
||||||
|
|
||||||
// X3 = r^2 - J - 2*V
|
// X3 = r^2 - J - 2*V
|
||||||
self.x = r;
|
self.x = r.square();
|
||||||
self.x.square();
|
|
||||||
self.x.sub_assign(&j);
|
self.x.sub_assign(&j);
|
||||||
self.x.sub_assign(&v);
|
self.x.sub_assign(&v);
|
||||||
self.x.sub_assign(&v);
|
self.x.sub_assign(&v);
|
||||||
@ -431,12 +412,12 @@ macro_rules! curve_impl {
|
|||||||
self.y.sub_assign(&self.x);
|
self.y.sub_assign(&self.x);
|
||||||
self.y.mul_assign(&r);
|
self.y.mul_assign(&r);
|
||||||
s1.mul_assign(&j); // S1 = S1 * J * 2
|
s1.mul_assign(&j); // S1 = S1 * J * 2
|
||||||
s1.double();
|
s1 = s1.double();
|
||||||
self.y.sub_assign(&s1);
|
self.y.sub_assign(&s1);
|
||||||
|
|
||||||
// Z3 = ((Z1+Z2)^2 - Z1Z1 - Z2Z2)*H
|
// Z3 = ((Z1+Z2)^2 - Z1Z1 - Z2Z2)*H
|
||||||
self.z.add_assign(&other.z);
|
self.z.add_assign(&other.z);
|
||||||
self.z.square();
|
self.z = self.z.square();
|
||||||
self.z.sub_assign(&z1z1);
|
self.z.sub_assign(&z1z1);
|
||||||
self.z.sub_assign(&z2z2);
|
self.z.sub_assign(&z2z2);
|
||||||
self.z.mul_assign(&h);
|
self.z.mul_assign(&h);
|
||||||
@ -458,8 +439,7 @@ macro_rules! curve_impl {
|
|||||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
|
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
|
||||||
|
|
||||||
// Z1Z1 = Z1^2
|
// Z1Z1 = Z1^2
|
||||||
let mut z1z1 = self.z;
|
let z1z1 = self.z.square();
|
||||||
z1z1.square();
|
|
||||||
|
|
||||||
// U2 = X2*Z1Z1
|
// U2 = X2*Z1Z1
|
||||||
let mut u2 = other.x;
|
let mut u2 = other.x;
|
||||||
@ -481,13 +461,10 @@ macro_rules! curve_impl {
|
|||||||
h.sub_assign(&self.x);
|
h.sub_assign(&self.x);
|
||||||
|
|
||||||
// HH = H^2
|
// HH = H^2
|
||||||
let mut hh = h;
|
let hh = h.square();
|
||||||
hh.square();
|
|
||||||
|
|
||||||
// I = 4*HH
|
// I = 4*HH
|
||||||
let mut i = hh;
|
let i = hh.double().double();
|
||||||
i.double();
|
|
||||||
i.double();
|
|
||||||
|
|
||||||
// J = H*I
|
// J = H*I
|
||||||
let mut j = h;
|
let mut j = h;
|
||||||
@ -496,22 +473,21 @@ macro_rules! curve_impl {
|
|||||||
// r = 2*(S2-Y1)
|
// r = 2*(S2-Y1)
|
||||||
let mut r = s2;
|
let mut r = s2;
|
||||||
r.sub_assign(&self.y);
|
r.sub_assign(&self.y);
|
||||||
r.double();
|
r = r.double();
|
||||||
|
|
||||||
// V = X1*I
|
// V = X1*I
|
||||||
let mut v = self.x;
|
let mut v = self.x;
|
||||||
v.mul_assign(&i);
|
v.mul_assign(&i);
|
||||||
|
|
||||||
// X3 = r^2 - J - 2*V
|
// X3 = r^2 - J - 2*V
|
||||||
self.x = r;
|
self.x = r.square();
|
||||||
self.x.square();
|
|
||||||
self.x.sub_assign(&j);
|
self.x.sub_assign(&j);
|
||||||
self.x.sub_assign(&v);
|
self.x.sub_assign(&v);
|
||||||
self.x.sub_assign(&v);
|
self.x.sub_assign(&v);
|
||||||
|
|
||||||
// Y3 = r*(V-X3)-2*Y1*J
|
// Y3 = r*(V-X3)-2*Y1*J
|
||||||
j.mul_assign(&self.y); // J = 2*Y1*J
|
j.mul_assign(&self.y); // J = 2*Y1*J
|
||||||
j.double();
|
j = j.double();
|
||||||
self.y = v;
|
self.y = v;
|
||||||
self.y.sub_assign(&self.x);
|
self.y.sub_assign(&self.x);
|
||||||
self.y.mul_assign(&r);
|
self.y.mul_assign(&r);
|
||||||
@ -519,7 +495,7 @@ macro_rules! curve_impl {
|
|||||||
|
|
||||||
// Z3 = (Z1+H)^2-Z1Z1-HH
|
// Z3 = (Z1+H)^2-Z1Z1-HH
|
||||||
self.z.add_assign(&h);
|
self.z.add_assign(&h);
|
||||||
self.z.square();
|
self.z = self.z.square();
|
||||||
self.z.sub_assign(&z1z1);
|
self.z.sub_assign(&z1z1);
|
||||||
self.z.sub_assign(&hh);
|
self.z.sub_assign(&hh);
|
||||||
}
|
}
|
||||||
@ -527,7 +503,7 @@ macro_rules! curve_impl {
|
|||||||
|
|
||||||
fn negate(&mut self) {
|
fn negate(&mut self) {
|
||||||
if !self.is_zero() {
|
if !self.is_zero() {
|
||||||
self.y.negate()
|
self.y = self.y.neg();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,8 +572,7 @@ macro_rules! curve_impl {
|
|||||||
} else {
|
} else {
|
||||||
// Z is nonzero, so it must have an inverse in a field.
|
// Z is nonzero, so it must have an inverse in a field.
|
||||||
let zinv = p.z.inverse().unwrap();
|
let zinv = p.z.inverse().unwrap();
|
||||||
let mut zinv_powered = zinv;
|
let mut zinv_powered = zinv.square();
|
||||||
zinv_powered.square();
|
|
||||||
|
|
||||||
// X/Z^2
|
// X/Z^2
|
||||||
let mut x = p.x;
|
let mut x = p.x;
|
||||||
@ -627,7 +602,7 @@ pub mod g1 {
|
|||||||
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
|
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||||
|
|
||||||
curve_impl!(
|
curve_impl!(
|
||||||
"G1",
|
"G1",
|
||||||
@ -849,8 +824,7 @@ pub mod g1 {
|
|||||||
affine.x.into_repr().write_be(&mut writer).unwrap();
|
affine.x.into_repr().write_be(&mut writer).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut negy = affine.y;
|
let negy = affine.y.neg();
|
||||||
negy.negate();
|
|
||||||
|
|
||||||
// Set the third most significant bit if the correct y-coordinate
|
// Set the third most significant bit if the correct y-coordinate
|
||||||
// is lexicographically largest.
|
// is lexicographically largest.
|
||||||
@ -941,15 +915,13 @@ pub mod g1 {
|
|||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
loop {
|
loop {
|
||||||
// y^2 = x^3 + b
|
// y^2 = x^3 + b
|
||||||
let mut rhs = x;
|
let mut rhs = x.square();
|
||||||
rhs.square();
|
|
||||||
rhs.mul_assign(&x);
|
rhs.mul_assign(&x);
|
||||||
rhs.add_assign(&G1Affine::get_coeff_b());
|
rhs.add_assign(&G1Affine::get_coeff_b());
|
||||||
|
|
||||||
if let Some(y) = rhs.sqrt() {
|
if let Some(y) = rhs.sqrt() {
|
||||||
let yrepr = y.into_repr();
|
let yrepr = y.into_repr();
|
||||||
let mut negy = y;
|
let negy = y.neg();
|
||||||
negy.negate();
|
|
||||||
let negyrepr = negy.into_repr();
|
let negyrepr = negy.into_repr();
|
||||||
|
|
||||||
let p = G1Affine {
|
let p = G1Affine {
|
||||||
@ -1297,7 +1269,7 @@ pub mod g2 {
|
|||||||
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
|
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||||
|
|
||||||
curve_impl!(
|
curve_impl!(
|
||||||
"G2",
|
"G2",
|
||||||
@ -1544,8 +1516,7 @@ pub mod g2 {
|
|||||||
affine.x.c0.into_repr().write_be(&mut writer).unwrap();
|
affine.x.c0.into_repr().write_be(&mut writer).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut negy = affine.y;
|
let negy = affine.y.neg();
|
||||||
negy.negate();
|
|
||||||
|
|
||||||
// Set the third most significant bit if the correct y-coordinate
|
// Set the third most significant bit if the correct y-coordinate
|
||||||
// is lexicographically largest.
|
// is lexicographically largest.
|
||||||
@ -1648,14 +1619,12 @@ pub mod g2 {
|
|||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
loop {
|
loop {
|
||||||
// y^2 = x^3 + b
|
// y^2 = x^3 + b
|
||||||
let mut rhs = x;
|
let mut rhs = x.square();
|
||||||
rhs.square();
|
|
||||||
rhs.mul_assign(&x);
|
rhs.mul_assign(&x);
|
||||||
rhs.add_assign(&G2Affine::get_coeff_b());
|
rhs.add_assign(&G2Affine::get_coeff_b());
|
||||||
|
|
||||||
if let Some(y) = rhs.sqrt() {
|
if let Some(y) = rhs.sqrt() {
|
||||||
let mut negy = y;
|
let negy = y.neg();
|
||||||
negy.negate();
|
|
||||||
|
|
||||||
let p = G2Affine {
|
let p = G2Affine {
|
||||||
x,
|
x,
|
||||||
|
@ -2,6 +2,9 @@ use super::fq2::Fq2;
|
|||||||
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr};
|
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr};
|
||||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
use std::ops::{AddAssign, MulAssign, SubAssign};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use std::ops::Neg;
|
||||||
|
|
||||||
// B coefficient of BLS12-381 curve, 4.
|
// B coefficient of BLS12-381 curve, 4.
|
||||||
pub const B_COEFF: Fq = Fq(FqRepr([
|
pub const B_COEFF: Fq = Fq(FqRepr([
|
||||||
0xaa270000000cfff3,
|
0xaa270000000cfff3,
|
||||||
@ -456,8 +459,7 @@ fn test_b_coeff() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_frob_coeffs() {
|
fn test_frob_coeffs() {
|
||||||
let mut nqr = Fq::one();
|
let nqr = Fq::one().neg();
|
||||||
nqr.negate();
|
|
||||||
|
|
||||||
assert_eq!(FROBENIUS_COEFF_FQ2_C1[0], Fq::one());
|
assert_eq!(FROBENIUS_COEFF_FQ2_C1[0], Fq::one());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -1167,8 +1169,7 @@ fn test_frob_coeffs() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_neg_one() {
|
fn test_neg_one() {
|
||||||
let mut o = Fq::one();
|
let o = Fq::one().neg();
|
||||||
o.negate();
|
|
||||||
|
|
||||||
assert_eq!(NEGATIVE_ONE, o);
|
assert_eq!(NEGATIVE_ONE, o);
|
||||||
}
|
}
|
||||||
@ -1929,7 +1930,7 @@ fn test_fq_mul_assign() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fq_squaring() {
|
fn test_fq_squaring() {
|
||||||
let mut a = Fq(FqRepr([
|
let a = Fq(FqRepr([
|
||||||
0xffffffffffffffff,
|
0xffffffffffffffff,
|
||||||
0xffffffffffffffff,
|
0xffffffffffffffff,
|
||||||
0xffffffffffffffff,
|
0xffffffffffffffff,
|
||||||
@ -1938,9 +1939,8 @@ fn test_fq_squaring() {
|
|||||||
0x19ffffffffffffff,
|
0x19ffffffffffffff,
|
||||||
]));
|
]));
|
||||||
assert!(a.is_valid());
|
assert!(a.is_valid());
|
||||||
a.square();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
a,
|
a.square(),
|
||||||
Fq::from_repr(FqRepr([
|
Fq::from_repr(FqRepr([
|
||||||
0x1cfb28fe7dfbbb86,
|
0x1cfb28fe7dfbbb86,
|
||||||
0x24cbe1731577a59,
|
0x24cbe1731577a59,
|
||||||
@ -1960,14 +1960,7 @@ fn test_fq_squaring() {
|
|||||||
for _ in 0..1000000 {
|
for _ in 0..1000000 {
|
||||||
// Ensure that (a * a) = a^2
|
// Ensure that (a * a) = a^2
|
||||||
let a = Fq::random(&mut rng);
|
let a = Fq::random(&mut rng);
|
||||||
|
assert_eq!(a.square(), a * a);
|
||||||
let mut tmp = a;
|
|
||||||
tmp.square();
|
|
||||||
|
|
||||||
let mut tmp2 = a;
|
|
||||||
tmp2.mul_assign(&a);
|
|
||||||
|
|
||||||
assert_eq!(tmp, tmp2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2000,19 +1993,15 @@ fn test_fq_double() {
|
|||||||
|
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
// Ensure doubling a is equivalent to adding a to itself.
|
// Ensure doubling a is equivalent to adding a to itself.
|
||||||
let mut a = Fq::random(&mut rng);
|
let a = Fq::random(&mut rng);
|
||||||
let mut b = a;
|
assert_eq!(a.double(), a + a);
|
||||||
b.add_assign(&a);
|
|
||||||
a.double();
|
|
||||||
assert_eq!(a, b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fq_negate() {
|
fn test_fq_neg() {
|
||||||
{
|
{
|
||||||
let mut a = Fq::zero();
|
let a = Fq::zero().neg();
|
||||||
a.negate();
|
|
||||||
|
|
||||||
assert!(a.is_zero());
|
assert!(a.is_zero());
|
||||||
}
|
}
|
||||||
@ -2025,8 +2014,7 @@ fn test_fq_negate() {
|
|||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
// Ensure (a - (-a)) = 0.
|
// Ensure (a - (-a)) = 0.
|
||||||
let mut a = Fq::random(&mut rng);
|
let mut a = Fq::random(&mut rng);
|
||||||
let mut b = a;
|
let b = a.neg();
|
||||||
b.negate();
|
|
||||||
a.add_assign(&b);
|
a.add_assign(&b);
|
||||||
|
|
||||||
assert!(a.is_zero());
|
assert!(a.is_zero());
|
||||||
@ -2074,10 +2062,8 @@ fn test_fq_sqrt() {
|
|||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
// Ensure sqrt(a^2) = a or -a
|
// Ensure sqrt(a^2) = a or -a
|
||||||
let a = Fq::random(&mut rng);
|
let a = Fq::random(&mut rng);
|
||||||
let mut nega = a;
|
let nega = a.neg();
|
||||||
nega.negate();
|
let b = a.square();
|
||||||
let mut b = a;
|
|
||||||
b.square();
|
|
||||||
|
|
||||||
let b = b.sqrt().unwrap();
|
let b = b.sqrt().unwrap();
|
||||||
|
|
||||||
@ -2088,10 +2074,8 @@ fn test_fq_sqrt() {
|
|||||||
// Ensure sqrt(a)^2 = a for random a
|
// Ensure sqrt(a)^2 = a for random a
|
||||||
let a = Fq::random(&mut rng);
|
let a = Fq::random(&mut rng);
|
||||||
|
|
||||||
if let Some(mut tmp) = a.sqrt() {
|
if let Some(tmp) = a.sqrt() {
|
||||||
tmp.square();
|
assert_eq!(a, tmp.square());
|
||||||
|
|
||||||
assert_eq!(a, tmp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,8 @@ use super::fq2::Fq2;
|
|||||||
use super::fq6::Fq6;
|
use super::fq6::Fq6;
|
||||||
use ff::Field;
|
use ff::Field;
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
use subtle::{Choice, ConditionallySelectable};
|
||||||
|
|
||||||
/// An element of Fq12, represented by c0 + c1 * w.
|
/// An element of Fq12, represented by c0 + c1 * w.
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
@ -20,7 +21,7 @@ impl ::std::fmt::Display for Fq12 {
|
|||||||
|
|
||||||
impl Fq12 {
|
impl Fq12 {
|
||||||
pub fn conjugate(&mut self) {
|
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) {
|
pub fn mul_by_014(&mut self, c0: &Fq2, c1: &Fq2, c4: &Fq2) {
|
||||||
@ -40,6 +41,26 @@ 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;
|
||||||
|
|
||||||
|
fn neg(self) -> Self {
|
||||||
|
Fq12 {
|
||||||
|
c0: self.c0.neg(),
|
||||||
|
c1: self.c1.neg(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'r> Add<&'r Fq12> for Fq12 {
|
impl<'r> Add<&'r Fq12> for Fq12 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@ -172,14 +193,11 @@ impl Field for Fq12 {
|
|||||||
self.c0.is_zero() && self.c1.is_zero()
|
self.c0.is_zero() && self.c1.is_zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn double(&mut self) {
|
fn double(&self) -> Self {
|
||||||
self.c0.double();
|
Fq12 {
|
||||||
self.c1.double();
|
c0: self.c0.double(),
|
||||||
}
|
c1: self.c1.double(),
|
||||||
|
}
|
||||||
fn negate(&mut self) {
|
|
||||||
self.c0.negate();
|
|
||||||
self.c1.negate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frobenius_map(&mut self, power: usize) {
|
fn frobenius_map(&mut self, power: usize) {
|
||||||
@ -191,7 +209,7 @@ impl Field for Fq12 {
|
|||||||
self.c1.c2.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
|
self.c1.c2.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn square(&mut self) {
|
fn square(&self) -> Self {
|
||||||
let mut ab = self.c0;
|
let mut ab = self.c0;
|
||||||
ab.mul_assign(&self.c1);
|
ab.mul_assign(&self.c1);
|
||||||
let mut c0c1 = self.c0;
|
let mut c0c1 = self.c0;
|
||||||
@ -201,28 +219,22 @@ impl Field for Fq12 {
|
|||||||
c0.add_assign(&self.c0);
|
c0.add_assign(&self.c0);
|
||||||
c0.mul_assign(&c0c1);
|
c0.mul_assign(&c0c1);
|
||||||
c0.sub_assign(&ab);
|
c0.sub_assign(&ab);
|
||||||
self.c1 = ab;
|
let mut c1 = ab;
|
||||||
self.c1.add_assign(&ab);
|
c1.add_assign(&ab);
|
||||||
ab.mul_by_nonresidue();
|
ab.mul_by_nonresidue();
|
||||||
c0.sub_assign(&ab);
|
c0.sub_assign(&ab);
|
||||||
self.c0 = c0;
|
Fq12 { c0, c1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inverse(&self) -> Option<Self> {
|
fn inverse(&self) -> Option<Self> {
|
||||||
let mut c0s = self.c0;
|
let mut c0s = self.c0.square();
|
||||||
c0s.square();
|
let mut c1s = self.c1.square();
|
||||||
let mut c1s = self.c1;
|
|
||||||
c1s.square();
|
|
||||||
c1s.mul_by_nonresidue();
|
c1s.mul_by_nonresidue();
|
||||||
c0s.sub_assign(&c1s);
|
c0s.sub_assign(&c1s);
|
||||||
|
|
||||||
c0s.inverse().map(|t| {
|
c0s.inverse().map(|t| Fq12 {
|
||||||
let mut tmp = Fq12 { c0: t, c1: t };
|
c0: t.mul(&self.c0),
|
||||||
tmp.c0.mul_assign(&self.c0);
|
c1: t.mul(&self.c1).neg(),
|
||||||
tmp.c1.mul_assign(&self.c1);
|
|
||||||
tmp.c1.negate();
|
|
||||||
|
|
||||||
tmp
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@ use super::fq::{Fq, FROBENIUS_COEFF_FQ2_C1, NEGATIVE_ONE};
|
|||||||
use ff::{Field, SqrtField};
|
use ff::{Field, SqrtField};
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
use subtle::{Choice, ConditionallySelectable};
|
||||||
|
|
||||||
/// An element of Fq2, represented by c0 + c1 * u.
|
/// An element of Fq2, represented by c0 + c1 * u.
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
@ -46,16 +47,34 @@ impl Fq2 {
|
|||||||
|
|
||||||
/// Norm of Fq2 as extension field in i over Fq
|
/// Norm of Fq2 as extension field in i over Fq
|
||||||
pub fn norm(&self) -> Fq {
|
pub fn norm(&self) -> Fq {
|
||||||
let mut t0 = self.c0;
|
let t0 = self.c0.square();
|
||||||
let mut t1 = self.c1;
|
let mut t1 = self.c1.square();
|
||||||
t0.square();
|
|
||||||
t1.square();
|
|
||||||
t1.add_assign(&t0);
|
t1.add_assign(&t0);
|
||||||
|
|
||||||
t1
|
t1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
fn neg(self) -> Self {
|
||||||
|
Fq2 {
|
||||||
|
c0: self.c0.neg(),
|
||||||
|
c1: self.c1.neg(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'r> Add<&'r Fq2> for Fq2 {
|
impl<'r> Add<&'r Fq2> for Fq2 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@ -187,48 +206,35 @@ impl Field for Fq2 {
|
|||||||
self.c0.is_zero() && self.c1.is_zero()
|
self.c0.is_zero() && self.c1.is_zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn square(&mut self) {
|
fn square(&self) -> Self {
|
||||||
let mut ab = self.c0;
|
let mut ab = self.c0;
|
||||||
ab.mul_assign(&self.c1);
|
ab.mul_assign(&self.c1);
|
||||||
let mut c0c1 = self.c0;
|
let mut c0c1 = self.c0;
|
||||||
c0c1.add_assign(&self.c1);
|
c0c1.add_assign(&self.c1);
|
||||||
let mut c0 = self.c1;
|
let mut c0 = self.c1.neg();
|
||||||
c0.negate();
|
|
||||||
c0.add_assign(&self.c0);
|
c0.add_assign(&self.c0);
|
||||||
c0.mul_assign(&c0c1);
|
c0.mul_assign(&c0c1);
|
||||||
c0.sub_assign(&ab);
|
c0.sub_assign(&ab);
|
||||||
self.c1 = ab;
|
let mut c1 = ab;
|
||||||
self.c1.add_assign(&ab);
|
c1.add_assign(&ab);
|
||||||
c0.add_assign(&ab);
|
c0.add_assign(&ab);
|
||||||
self.c0 = c0;
|
Fq2 { c0, c1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn double(&mut self) {
|
fn double(&self) -> Self {
|
||||||
self.c0.double();
|
Fq2 {
|
||||||
self.c1.double();
|
c0: self.c0.double(),
|
||||||
}
|
c1: self.c1.double(),
|
||||||
|
}
|
||||||
fn negate(&mut self) {
|
|
||||||
self.c0.negate();
|
|
||||||
self.c1.negate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inverse(&self) -> Option<Self> {
|
fn inverse(&self) -> Option<Self> {
|
||||||
let mut t1 = self.c1;
|
let t1 = self.c1.square();
|
||||||
t1.square();
|
let mut t0 = self.c0.square();
|
||||||
let mut t0 = self.c0;
|
|
||||||
t0.square();
|
|
||||||
t0.add_assign(&t1);
|
t0.add_assign(&t1);
|
||||||
t0.inverse().map(|t| {
|
t0.inverse().map(|t| Fq2 {
|
||||||
let mut tmp = Fq2 {
|
c0: self.c0.mul(&t),
|
||||||
c0: self.c0,
|
c1: self.c1.mul(&t).neg(),
|
||||||
c1: self.c1,
|
|
||||||
};
|
|
||||||
tmp.c0.mul_assign(&t);
|
|
||||||
tmp.c1.mul_assign(&t);
|
|
||||||
tmp.c1.negate();
|
|
||||||
|
|
||||||
tmp
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,8 +263,7 @@ impl SqrtField for Fq2 {
|
|||||||
0x92c6e9ed90d2eb35,
|
0x92c6e9ed90d2eb35,
|
||||||
0x680447a8e5ff9a6,
|
0x680447a8e5ff9a6,
|
||||||
]);
|
]);
|
||||||
let mut alpha = a1;
|
let mut alpha = a1.square();
|
||||||
alpha.square();
|
|
||||||
alpha.mul_assign(self);
|
alpha.mul_assign(self);
|
||||||
let mut a0 = alpha;
|
let mut a0 = alpha;
|
||||||
a0.frobenius_map(1);
|
a0.frobenius_map(1);
|
||||||
@ -353,34 +358,30 @@ fn test_fq2_squaring() {
|
|||||||
use super::fq::FqRepr;
|
use super::fq::FqRepr;
|
||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
|
|
||||||
let mut a = Fq2 {
|
let a = Fq2 {
|
||||||
c0: Fq::one(),
|
c0: Fq::one(),
|
||||||
c1: Fq::one(),
|
c1: Fq::one(),
|
||||||
}; // u + 1
|
}; // u + 1
|
||||||
a.square();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
a,
|
a.square(),
|
||||||
Fq2 {
|
Fq2 {
|
||||||
c0: Fq::zero(),
|
c0: Fq::zero(),
|
||||||
c1: Fq::from_repr(FqRepr::from(2)).unwrap(),
|
c1: Fq::from_repr(FqRepr::from(2)).unwrap(),
|
||||||
}
|
}
|
||||||
); // 2u
|
); // 2u
|
||||||
|
|
||||||
let mut a = Fq2 {
|
let a = Fq2 {
|
||||||
c0: Fq::zero(),
|
c0: Fq::zero(),
|
||||||
c1: Fq::one(),
|
c1: Fq::one(),
|
||||||
}; // u
|
}; // u
|
||||||
a.square();
|
assert_eq!(a.square(), {
|
||||||
assert_eq!(a, {
|
|
||||||
let mut neg1 = Fq::one();
|
|
||||||
neg1.negate();
|
|
||||||
Fq2 {
|
Fq2 {
|
||||||
c0: neg1,
|
c0: Fq::one().neg(),
|
||||||
c1: Fq::zero(),
|
c1: Fq::zero(),
|
||||||
}
|
}
|
||||||
}); // -1
|
}); // -1
|
||||||
|
|
||||||
let mut a = Fq2 {
|
let a = Fq2 {
|
||||||
c0: Fq::from_repr(FqRepr([
|
c0: Fq::from_repr(FqRepr([
|
||||||
0x9c2c6309bbf8b598,
|
0x9c2c6309bbf8b598,
|
||||||
0x4eef5c946536f602,
|
0x4eef5c946536f602,
|
||||||
@ -400,9 +401,8 @@ fn test_fq2_squaring() {
|
|||||||
]))
|
]))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
};
|
};
|
||||||
a.square();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
a,
|
a.square(),
|
||||||
Fq2 {
|
Fq2 {
|
||||||
c0: Fq::from_repr(FqRepr([
|
c0: Fq::from_repr(FqRepr([
|
||||||
0xf262c28c538bcf68,
|
0xf262c28c538bcf68,
|
||||||
@ -694,7 +694,7 @@ fn test_fq2_negation() {
|
|||||||
use super::fq::FqRepr;
|
use super::fq::FqRepr;
|
||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
|
|
||||||
let mut a = Fq2 {
|
let a = Fq2 {
|
||||||
c0: Fq::from_repr(FqRepr([
|
c0: Fq::from_repr(FqRepr([
|
||||||
0x2d0078036923ffc7,
|
0x2d0078036923ffc7,
|
||||||
0x11e59ea221a3b6d2,
|
0x11e59ea221a3b6d2,
|
||||||
@ -713,8 +713,8 @@ fn test_fq2_negation() {
|
|||||||
0x12d1137b8a6a837,
|
0x12d1137b8a6a837,
|
||||||
]))
|
]))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
};
|
}
|
||||||
a.negate();
|
.neg();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
a,
|
a,
|
||||||
Fq2 {
|
Fq2 {
|
||||||
@ -745,7 +745,7 @@ fn test_fq2_doubling() {
|
|||||||
use super::fq::FqRepr;
|
use super::fq::FqRepr;
|
||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
|
|
||||||
let mut a = Fq2 {
|
let a = Fq2 {
|
||||||
c0: Fq::from_repr(FqRepr([
|
c0: Fq::from_repr(FqRepr([
|
||||||
0x2d0078036923ffc7,
|
0x2d0078036923ffc7,
|
||||||
0x11e59ea221a3b6d2,
|
0x11e59ea221a3b6d2,
|
||||||
@ -765,9 +765,8 @@ fn test_fq2_doubling() {
|
|||||||
]))
|
]))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
};
|
};
|
||||||
a.double();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
a,
|
a.double(),
|
||||||
Fq2 {
|
Fq2 {
|
||||||
c0: Fq::from_repr(FqRepr([
|
c0: Fq::from_repr(FqRepr([
|
||||||
0x5a00f006d247ff8e,
|
0x5a00f006d247ff8e,
|
||||||
@ -1000,8 +999,7 @@ fn test_fq2_legendre() {
|
|||||||
|
|
||||||
assert_eq!(Zero, Fq2::zero().legendre());
|
assert_eq!(Zero, Fq2::zero().legendre());
|
||||||
// i^2 = -1
|
// i^2 = -1
|
||||||
let mut m1 = Fq2::one();
|
let mut m1 = Fq2::one().neg();
|
||||||
m1.negate();
|
|
||||||
assert_eq!(QuadraticResidue, m1.legendre());
|
assert_eq!(QuadraticResidue, m1.legendre());
|
||||||
m1.mul_by_nonresidue();
|
m1.mul_by_nonresidue();
|
||||||
assert_eq!(QuadraticNonResidue, m1.legendre());
|
assert_eq!(QuadraticNonResidue, m1.legendre());
|
||||||
|
@ -2,7 +2,8 @@ use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2};
|
|||||||
use super::fq2::Fq2;
|
use super::fq2::Fq2;
|
||||||
use ff::Field;
|
use ff::Field;
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
|
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).
|
/// An element of Fq6, represented by c0 + c1 * v + c2 * v^(2).
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
@ -100,6 +101,28 @@ 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;
|
||||||
|
|
||||||
|
fn neg(self) -> Self {
|
||||||
|
Fq6 {
|
||||||
|
c0: self.c0.neg(),
|
||||||
|
c1: self.c1.neg(),
|
||||||
|
c2: self.c2.neg(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'r> Add<&'r Fq6> for Fq6 {
|
impl<'r> Add<&'r Fq6> for Fq6 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@ -274,16 +297,12 @@ impl Field for Fq6 {
|
|||||||
self.c0.is_zero() && self.c1.is_zero() && self.c2.is_zero()
|
self.c0.is_zero() && self.c1.is_zero() && self.c2.is_zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn double(&mut self) {
|
fn double(&self) -> Self {
|
||||||
self.c0.double();
|
Fq6 {
|
||||||
self.c1.double();
|
c0: self.c0.double(),
|
||||||
self.c2.double();
|
c1: self.c1.double(),
|
||||||
}
|
c2: self.c2.double(),
|
||||||
|
}
|
||||||
fn negate(&mut self) {
|
|
||||||
self.c0.negate();
|
|
||||||
self.c1.negate();
|
|
||||||
self.c2.negate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frobenius_map(&mut self, power: usize) {
|
fn frobenius_map(&mut self, power: usize) {
|
||||||
@ -295,59 +314,54 @@ impl Field for Fq6 {
|
|||||||
self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]);
|
self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn square(&mut self) {
|
fn square(&self) -> Self {
|
||||||
let mut s0 = self.c0;
|
let s0 = self.c0.square();
|
||||||
s0.square();
|
|
||||||
let mut ab = self.c0;
|
let mut ab = self.c0;
|
||||||
ab.mul_assign(&self.c1);
|
ab.mul_assign(&self.c1);
|
||||||
let mut s1 = ab;
|
let s1 = ab.double();
|
||||||
s1.double();
|
|
||||||
let mut s2 = self.c0;
|
let mut s2 = self.c0;
|
||||||
s2.sub_assign(&self.c1);
|
s2.sub_assign(&self.c1);
|
||||||
s2.add_assign(&self.c2);
|
s2.add_assign(&self.c2);
|
||||||
s2.square();
|
s2 = s2.square();
|
||||||
let mut bc = self.c1;
|
let mut bc = self.c1;
|
||||||
bc.mul_assign(&self.c2);
|
bc.mul_assign(&self.c2);
|
||||||
let mut s3 = bc;
|
let s3 = bc.double();
|
||||||
s3.double();
|
let s4 = self.c2.square();
|
||||||
let mut s4 = self.c2;
|
|
||||||
s4.square();
|
|
||||||
|
|
||||||
self.c0 = s3;
|
let mut c0 = s3;
|
||||||
self.c0.mul_by_nonresidue();
|
c0.mul_by_nonresidue();
|
||||||
self.c0.add_assign(&s0);
|
c0.add_assign(&s0);
|
||||||
|
|
||||||
self.c1 = s4;
|
let mut c1 = s4;
|
||||||
self.c1.mul_by_nonresidue();
|
c1.mul_by_nonresidue();
|
||||||
self.c1.add_assign(&s1);
|
c1.add_assign(&s1);
|
||||||
|
|
||||||
self.c2 = s1;
|
let mut c2 = s1;
|
||||||
self.c2.add_assign(&s2);
|
c2.add_assign(&s2);
|
||||||
self.c2.add_assign(&s3);
|
c2.add_assign(&s3);
|
||||||
self.c2.sub_assign(&s0);
|
c2.sub_assign(&s0);
|
||||||
self.c2.sub_assign(&s4);
|
c2.sub_assign(&s4);
|
||||||
|
|
||||||
|
Fq6 { c0, c1, c2 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inverse(&self) -> Option<Self> {
|
fn inverse(&self) -> Option<Self> {
|
||||||
let mut c0 = self.c2;
|
let mut c0 = self.c2;
|
||||||
c0.mul_by_nonresidue();
|
c0.mul_by_nonresidue();
|
||||||
c0.mul_assign(&self.c1);
|
c0.mul_assign(&self.c1);
|
||||||
c0.negate();
|
c0 = c0.neg();
|
||||||
{
|
{
|
||||||
let mut c0s = self.c0;
|
let c0s = self.c0.square();
|
||||||
c0s.square();
|
|
||||||
c0.add_assign(&c0s);
|
c0.add_assign(&c0s);
|
||||||
}
|
}
|
||||||
let mut c1 = self.c2;
|
let mut c1 = self.c2.square();
|
||||||
c1.square();
|
|
||||||
c1.mul_by_nonresidue();
|
c1.mul_by_nonresidue();
|
||||||
{
|
{
|
||||||
let mut c01 = self.c0;
|
let mut c01 = self.c0;
|
||||||
c01.mul_assign(&self.c1);
|
c01.mul_assign(&self.c1);
|
||||||
c1.sub_assign(&c01);
|
c1.sub_assign(&c01);
|
||||||
}
|
}
|
||||||
let mut c2 = self.c1;
|
let mut c2 = self.c1.square();
|
||||||
c2.square();
|
|
||||||
{
|
{
|
||||||
let mut c02 = self.c0;
|
let mut c02 = self.c0;
|
||||||
c02.mul_assign(&self.c2);
|
c02.mul_assign(&self.c2);
|
||||||
|
@ -10,6 +10,8 @@ pub struct Fr(FrRepr);
|
|||||||
use rand_core::SeedableRng;
|
use rand_core::SeedableRng;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
|
#[cfg(test)]
|
||||||
|
use std::ops::Neg;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fr_repr_ordering() {
|
fn test_fr_repr_ordering() {
|
||||||
@ -691,16 +693,15 @@ fn test_fr_mul_assign() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fr_squaring() {
|
fn test_fr_squaring() {
|
||||||
let mut a = Fr(FrRepr([
|
let a = Fr(FrRepr([
|
||||||
0xffffffffffffffff,
|
0xffffffffffffffff,
|
||||||
0xffffffffffffffff,
|
0xffffffffffffffff,
|
||||||
0xffffffffffffffff,
|
0xffffffffffffffff,
|
||||||
0x73eda753299d7d47,
|
0x73eda753299d7d47,
|
||||||
]));
|
]));
|
||||||
assert!(a.is_valid());
|
assert!(a.is_valid());
|
||||||
a.square();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
a,
|
a.square(),
|
||||||
Fr::from_repr(FrRepr([
|
Fr::from_repr(FrRepr([
|
||||||
0xc0d698e7bde077b8,
|
0xc0d698e7bde077b8,
|
||||||
0xb79a310579e76ec2,
|
0xb79a310579e76ec2,
|
||||||
@ -718,14 +719,7 @@ fn test_fr_squaring() {
|
|||||||
for _ in 0..1000000 {
|
for _ in 0..1000000 {
|
||||||
// Ensure that (a * a) = a^2
|
// Ensure that (a * a) = a^2
|
||||||
let a = Fr::random(&mut rng);
|
let a = Fr::random(&mut rng);
|
||||||
|
assert_eq!(a.square(), a * a);
|
||||||
let mut tmp = a;
|
|
||||||
tmp.square();
|
|
||||||
|
|
||||||
let mut tmp2 = a;
|
|
||||||
tmp2.mul_assign(&a);
|
|
||||||
|
|
||||||
assert_eq!(tmp, tmp2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -758,19 +752,15 @@ fn test_fr_double() {
|
|||||||
|
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
// Ensure doubling a is equivalent to adding a to itself.
|
// Ensure doubling a is equivalent to adding a to itself.
|
||||||
let mut a = Fr::random(&mut rng);
|
let a = Fr::random(&mut rng);
|
||||||
let mut b = a;
|
assert_eq!(a.double(), a + a);
|
||||||
b.add_assign(&a);
|
|
||||||
a.double();
|
|
||||||
assert_eq!(a, b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fr_negate() {
|
fn test_fr_neg() {
|
||||||
{
|
{
|
||||||
let mut a = Fr::zero();
|
let a = Fr::zero().neg();
|
||||||
a.negate();
|
|
||||||
|
|
||||||
assert!(a.is_zero());
|
assert!(a.is_zero());
|
||||||
}
|
}
|
||||||
@ -783,8 +773,7 @@ fn test_fr_negate() {
|
|||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
// Ensure (a - (-a)) = 0.
|
// Ensure (a - (-a)) = 0.
|
||||||
let mut a = Fr::random(&mut rng);
|
let mut a = Fr::random(&mut rng);
|
||||||
let mut b = a;
|
let b = a.neg();
|
||||||
b.negate();
|
|
||||||
a.add_assign(&b);
|
a.add_assign(&b);
|
||||||
|
|
||||||
assert!(a.is_zero());
|
assert!(a.is_zero());
|
||||||
@ -832,10 +821,8 @@ fn test_fr_sqrt() {
|
|||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
// Ensure sqrt(a^2) = a or -a
|
// Ensure sqrt(a^2) = a or -a
|
||||||
let a = Fr::random(&mut rng);
|
let a = Fr::random(&mut rng);
|
||||||
let mut nega = a;
|
let nega = a.neg();
|
||||||
nega.negate();
|
let b = a.square();
|
||||||
let mut b = a;
|
|
||||||
b.square();
|
|
||||||
|
|
||||||
let b = b.sqrt().unwrap();
|
let b = b.sqrt().unwrap();
|
||||||
|
|
||||||
@ -846,10 +833,8 @@ fn test_fr_sqrt() {
|
|||||||
// Ensure sqrt(a)^2 = a for random a
|
// Ensure sqrt(a)^2 = a for random a
|
||||||
let a = Fr::random(&mut rng);
|
let a = Fr::random(&mut rng);
|
||||||
|
|
||||||
if let Some(mut tmp) = a.sqrt() {
|
if let Some(tmp) = a.sqrt() {
|
||||||
tmp.square();
|
assert_eq!(a, tmp.square());
|
||||||
|
|
||||||
assert_eq!(a, tmp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ use super::{Engine, PairingCurveAffine};
|
|||||||
|
|
||||||
use ff::{BitIterator, Field, ScalarEngine};
|
use ff::{BitIterator, Field, ScalarEngine};
|
||||||
use group::CurveAffine;
|
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
|
// The BLS parameter x for BLS12-381 is -0xd201000000010000
|
||||||
const BLS_X: u64 = 0xd201000000010000;
|
const BLS_X: u64 = 0xd201000000010000;
|
||||||
@ -97,7 +97,7 @@ impl Engine for Bls12 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f.square();
|
f = f.square();
|
||||||
}
|
}
|
||||||
|
|
||||||
for &mut (p, ref mut coeffs) in &mut pairs {
|
for &mut (p, ref mut coeffs) in &mut pairs {
|
||||||
@ -131,8 +131,7 @@ impl Engine for Bls12 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut x = BLS_X;
|
let mut x = BLS_X;
|
||||||
let mut y0 = r;
|
let y0 = r.square();
|
||||||
y0.square();
|
|
||||||
let mut y1 = y0;
|
let mut y1 = y0;
|
||||||
exp_by_x(&mut y1, x);
|
exp_by_x(&mut y1, x);
|
||||||
x >>= 1;
|
x >>= 1;
|
||||||
@ -185,41 +184,35 @@ impl G2Prepared {
|
|||||||
|
|
||||||
fn doubling_step(r: &mut G2) -> (Fq2, Fq2, Fq2) {
|
fn doubling_step(r: &mut G2) -> (Fq2, Fq2, Fq2) {
|
||||||
// Adaptation of Algorithm 26, https://eprint.iacr.org/2010/354.pdf
|
// Adaptation of Algorithm 26, https://eprint.iacr.org/2010/354.pdf
|
||||||
let mut tmp0 = r.x;
|
let mut tmp0 = r.x.square();
|
||||||
tmp0.square();
|
|
||||||
|
|
||||||
let mut tmp1 = r.y;
|
let mut tmp1 = r.y.square();
|
||||||
tmp1.square();
|
|
||||||
|
|
||||||
let mut tmp2 = tmp1;
|
let mut tmp2 = tmp1.square();
|
||||||
tmp2.square();
|
|
||||||
|
|
||||||
let mut tmp3 = tmp1;
|
let mut tmp3 = tmp1;
|
||||||
tmp3.add_assign(&r.x);
|
tmp3.add_assign(&r.x);
|
||||||
tmp3.square();
|
tmp3 = tmp3.square();
|
||||||
tmp3.sub_assign(&tmp0);
|
tmp3.sub_assign(&tmp0);
|
||||||
tmp3.sub_assign(&tmp2);
|
tmp3.sub_assign(&tmp2);
|
||||||
tmp3.double();
|
tmp3 = tmp3.double();
|
||||||
|
|
||||||
let mut tmp4 = tmp0;
|
let mut tmp4 = tmp0.double();
|
||||||
tmp4.double();
|
|
||||||
tmp4.add_assign(&tmp0);
|
tmp4.add_assign(&tmp0);
|
||||||
|
|
||||||
let mut tmp6 = r.x;
|
let mut tmp6 = r.x;
|
||||||
tmp6.add_assign(&tmp4);
|
tmp6.add_assign(&tmp4);
|
||||||
|
|
||||||
let mut tmp5 = tmp4;
|
let tmp5 = tmp4.square();
|
||||||
tmp5.square();
|
|
||||||
|
|
||||||
let mut zsquared = r.z;
|
let zsquared = r.z.square();
|
||||||
zsquared.square();
|
|
||||||
|
|
||||||
r.x = tmp5;
|
r.x = tmp5;
|
||||||
r.x.sub_assign(&tmp3);
|
r.x.sub_assign(&tmp3);
|
||||||
r.x.sub_assign(&tmp3);
|
r.x.sub_assign(&tmp3);
|
||||||
|
|
||||||
r.z.add_assign(&r.y);
|
r.z.add_assign(&r.y);
|
||||||
r.z.square();
|
r.z = r.z.square();
|
||||||
r.z.sub_assign(&tmp1);
|
r.z.sub_assign(&tmp1);
|
||||||
r.z.sub_assign(&zsquared);
|
r.z.sub_assign(&zsquared);
|
||||||
|
|
||||||
@ -227,47 +220,41 @@ impl G2Prepared {
|
|||||||
r.y.sub_assign(&r.x);
|
r.y.sub_assign(&r.x);
|
||||||
r.y.mul_assign(&tmp4);
|
r.y.mul_assign(&tmp4);
|
||||||
|
|
||||||
tmp2.double();
|
tmp2 = tmp2.double().double().double();
|
||||||
tmp2.double();
|
|
||||||
tmp2.double();
|
|
||||||
|
|
||||||
r.y.sub_assign(&tmp2);
|
r.y.sub_assign(&tmp2);
|
||||||
|
|
||||||
tmp3 = tmp4;
|
tmp3 = tmp4;
|
||||||
tmp3.mul_assign(&zsquared);
|
tmp3.mul_assign(&zsquared);
|
||||||
tmp3.double();
|
tmp3 = tmp3.double().neg();
|
||||||
tmp3.negate();
|
|
||||||
|
|
||||||
tmp6.square();
|
tmp6 = tmp6.square();
|
||||||
tmp6.sub_assign(&tmp0);
|
tmp6.sub_assign(&tmp0);
|
||||||
tmp6.sub_assign(&tmp5);
|
tmp6.sub_assign(&tmp5);
|
||||||
|
|
||||||
tmp1.double();
|
tmp1 = tmp1.double().double();
|
||||||
tmp1.double();
|
|
||||||
|
|
||||||
tmp6.sub_assign(&tmp1);
|
tmp6.sub_assign(&tmp1);
|
||||||
|
|
||||||
tmp0 = r.z;
|
tmp0 = r.z;
|
||||||
tmp0.mul_assign(&zsquared);
|
tmp0.mul_assign(&zsquared);
|
||||||
tmp0.double();
|
tmp0 = tmp0.double();
|
||||||
|
|
||||||
(tmp0, tmp3, tmp6)
|
(tmp0, tmp3, tmp6)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addition_step(r: &mut G2, q: &G2Affine) -> (Fq2, Fq2, Fq2) {
|
fn addition_step(r: &mut G2, q: &G2Affine) -> (Fq2, Fq2, Fq2) {
|
||||||
// Adaptation of Algorithm 27, https://eprint.iacr.org/2010/354.pdf
|
// Adaptation of Algorithm 27, https://eprint.iacr.org/2010/354.pdf
|
||||||
let mut zsquared = r.z;
|
let zsquared = r.z.square();
|
||||||
zsquared.square();
|
|
||||||
|
|
||||||
let mut ysquared = q.y;
|
let ysquared = q.y.square();
|
||||||
ysquared.square();
|
|
||||||
|
|
||||||
let mut t0 = zsquared;
|
let mut t0 = zsquared;
|
||||||
t0.mul_assign(&q.x);
|
t0.mul_assign(&q.x);
|
||||||
|
|
||||||
let mut t1 = q.y;
|
let mut t1 = q.y;
|
||||||
t1.add_assign(&r.z);
|
t1.add_assign(&r.z);
|
||||||
t1.square();
|
t1 = t1.square();
|
||||||
t1.sub_assign(&ysquared);
|
t1.sub_assign(&ysquared);
|
||||||
t1.sub_assign(&zsquared);
|
t1.sub_assign(&zsquared);
|
||||||
t1.mul_assign(&zsquared);
|
t1.mul_assign(&zsquared);
|
||||||
@ -275,12 +262,9 @@ impl G2Prepared {
|
|||||||
let mut t2 = t0;
|
let mut t2 = t0;
|
||||||
t2.sub_assign(&r.x);
|
t2.sub_assign(&r.x);
|
||||||
|
|
||||||
let mut t3 = t2;
|
let t3 = t2.square();
|
||||||
t3.square();
|
|
||||||
|
|
||||||
let mut t4 = t3;
|
let t4 = t3.double().double();
|
||||||
t4.double();
|
|
||||||
t4.double();
|
|
||||||
|
|
||||||
let mut t5 = t4;
|
let mut t5 = t4;
|
||||||
t5.mul_assign(&t2);
|
t5.mul_assign(&t2);
|
||||||
@ -295,14 +279,13 @@ impl G2Prepared {
|
|||||||
let mut t7 = t4;
|
let mut t7 = t4;
|
||||||
t7.mul_assign(&r.x);
|
t7.mul_assign(&r.x);
|
||||||
|
|
||||||
r.x = t6;
|
r.x = t6.square();
|
||||||
r.x.square();
|
|
||||||
r.x.sub_assign(&t5);
|
r.x.sub_assign(&t5);
|
||||||
r.x.sub_assign(&t7);
|
r.x.sub_assign(&t7);
|
||||||
r.x.sub_assign(&t7);
|
r.x.sub_assign(&t7);
|
||||||
|
|
||||||
r.z.add_assign(&t2);
|
r.z.add_assign(&t2);
|
||||||
r.z.square();
|
r.z = r.z.square();
|
||||||
r.z.sub_assign(&zsquared);
|
r.z.sub_assign(&zsquared);
|
||||||
r.z.sub_assign(&t3);
|
r.z.sub_assign(&t3);
|
||||||
|
|
||||||
@ -315,29 +298,26 @@ impl G2Prepared {
|
|||||||
|
|
||||||
t0 = r.y;
|
t0 = r.y;
|
||||||
t0.mul_assign(&t5);
|
t0.mul_assign(&t5);
|
||||||
t0.double();
|
t0 = t0.double();
|
||||||
|
|
||||||
r.y = t8;
|
r.y = t8;
|
||||||
r.y.sub_assign(&t0);
|
r.y.sub_assign(&t0);
|
||||||
|
|
||||||
t10.square();
|
t10 = t10.square();
|
||||||
t10.sub_assign(&ysquared);
|
t10.sub_assign(&ysquared);
|
||||||
|
|
||||||
let mut ztsquared = r.z;
|
let ztsquared = r.z.square();
|
||||||
ztsquared.square();
|
|
||||||
|
|
||||||
t10.sub_assign(&ztsquared);
|
t10.sub_assign(&ztsquared);
|
||||||
|
|
||||||
t9.double();
|
t9 = t9.double();
|
||||||
t9.sub_assign(&t10);
|
t9.sub_assign(&t10);
|
||||||
|
|
||||||
t10 = r.z;
|
t10 = r.z.double();
|
||||||
t10.double();
|
|
||||||
|
|
||||||
t6.negate();
|
t6 = t6.neg();
|
||||||
|
|
||||||
t1 = t6;
|
t1 = t6.double();
|
||||||
t1.double();
|
|
||||||
|
|
||||||
(t10, t1, t9)
|
(t10, t1, t9)
|
||||||
}
|
}
|
||||||
|
@ -189,8 +189,7 @@ fn test_g1_uncompressed_invalid_vectors() {
|
|||||||
let mut x = Fq::one();
|
let mut x = Fq::one();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut x3b = x;
|
let mut x3b = x.square();
|
||||||
x3b.square();
|
|
||||||
x3b.mul_assign(&x);
|
x3b.mul_assign(&x);
|
||||||
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API?
|
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();
|
let mut x = Fq2::one();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut x3b = x;
|
let mut x3b = x.square();
|
||||||
x3b.square();
|
|
||||||
x3b.mul_assign(&x);
|
x3b.mul_assign(&x);
|
||||||
x3b.add_assign(&Fq2 {
|
x3b.add_assign(&Fq2 {
|
||||||
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
||||||
@ -422,8 +420,7 @@ fn test_g1_compressed_invalid_vectors() {
|
|||||||
let mut x = Fq::one();
|
let mut x = Fq::one();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut x3b = x;
|
let mut x3b = x.square();
|
||||||
x3b.square();
|
|
||||||
x3b.mul_assign(&x);
|
x3b.mul_assign(&x);
|
||||||
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API?
|
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();
|
let mut x = Fq::one();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut x3b = x;
|
let mut x3b = x.square();
|
||||||
x3b.square();
|
|
||||||
x3b.mul_assign(&x);
|
x3b.mul_assign(&x);
|
||||||
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API?
|
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 {
|
loop {
|
||||||
let mut x3b = x;
|
let mut x3b = x.square();
|
||||||
x3b.square();
|
|
||||||
x3b.mul_assign(&x);
|
x3b.mul_assign(&x);
|
||||||
x3b.add_assign(&Fq2 {
|
x3b.add_assign(&Fq2 {
|
||||||
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
||||||
@ -585,8 +580,7 @@ fn test_g2_compressed_invalid_vectors() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut x3b = x;
|
let mut x3b = x.square();
|
||||||
x3b.square();
|
|
||||||
x3b.mul_assign(&x);
|
x3b.mul_assign(&x);
|
||||||
x3b.add_assign(&Fq2 {
|
x3b.add_assign(&Fq2 {
|
||||||
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
||||||
|
@ -31,27 +31,24 @@ pub fn random_sqrt_tests<F: SqrtField>() {
|
|||||||
|
|
||||||
for _ in 0..10000 {
|
for _ in 0..10000 {
|
||||||
let a = F::random(&mut rng);
|
let a = F::random(&mut rng);
|
||||||
let mut b = a;
|
let b = a.square();
|
||||||
b.square();
|
|
||||||
assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue);
|
assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue);
|
||||||
|
|
||||||
let b = b.sqrt().unwrap();
|
let b = b.sqrt().unwrap();
|
||||||
let mut negb = b;
|
let negb = b.neg();
|
||||||
negb.negate();
|
|
||||||
|
|
||||||
assert!(a == b || a == negb);
|
assert!(a == b || a == negb);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut c = F::one();
|
let mut c = F::one();
|
||||||
for _ in 0..10000 {
|
for _ in 0..10000 {
|
||||||
let mut b = c;
|
let mut b = c.square();
|
||||||
b.square();
|
|
||||||
assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue);
|
assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue);
|
||||||
|
|
||||||
b = b.sqrt().unwrap();
|
b = b.sqrt().unwrap();
|
||||||
|
|
||||||
if b != c {
|
if b != c {
|
||||||
b.negate();
|
b = b.neg();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(b, c);
|
assert_eq!(b, c);
|
||||||
@ -77,8 +74,7 @@ pub fn random_field_tests<F: Field>() {
|
|||||||
|
|
||||||
assert!(F::zero().is_zero());
|
assert!(F::zero().is_zero());
|
||||||
{
|
{
|
||||||
let mut z = F::zero();
|
let z = F::zero().neg();
|
||||||
z.negate();
|
|
||||||
assert!(z.is_zero());
|
assert!(z.is_zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,8 +200,7 @@ fn random_subtraction_tests<F: Field, R: RngCore>(rng: &mut R) {
|
|||||||
fn random_negation_tests<F: Field, R: RngCore>(rng: &mut R) {
|
fn random_negation_tests<F: Field, R: RngCore>(rng: &mut R) {
|
||||||
for _ in 0..10000 {
|
for _ in 0..10000 {
|
||||||
let a = F::random(rng);
|
let a = F::random(rng);
|
||||||
let mut b = a;
|
let mut b = a.neg();
|
||||||
b.negate();
|
|
||||||
b.add_assign(&a);
|
b.add_assign(&a);
|
||||||
|
|
||||||
assert!(b.is_zero());
|
assert!(b.is_zero());
|
||||||
@ -214,23 +209,15 @@ fn random_negation_tests<F: Field, R: RngCore>(rng: &mut R) {
|
|||||||
|
|
||||||
fn random_doubling_tests<F: Field, R: RngCore>(rng: &mut R) {
|
fn random_doubling_tests<F: Field, R: RngCore>(rng: &mut R) {
|
||||||
for _ in 0..10000 {
|
for _ in 0..10000 {
|
||||||
let mut a = F::random(rng);
|
let a = F::random(rng);
|
||||||
let mut b = a;
|
assert_eq!(a + a, a.double());
|
||||||
a.add_assign(&b);
|
|
||||||
b.double();
|
|
||||||
|
|
||||||
assert_eq!(a, b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_squaring_tests<F: Field, R: RngCore>(rng: &mut R) {
|
fn random_squaring_tests<F: Field, R: RngCore>(rng: &mut R) {
|
||||||
for _ in 0..10000 {
|
for _ in 0..10000 {
|
||||||
let mut a = F::random(rng);
|
let a = F::random(rng);
|
||||||
let mut b = a;
|
assert_eq!(a * a, a.square());
|
||||||
a.mul_assign(&b);
|
|
||||||
b.square();
|
|
||||||
|
|
||||||
assert_eq!(a, b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ rand_core = "0.5.1"
|
|||||||
ripemd160 = { version = "0.8", optional = true }
|
ripemd160 = { version = "0.8", optional = true }
|
||||||
secp256k1 = { version = "=0.15.0", optional = true }
|
secp256k1 = { version = "=0.15.0", optional = true }
|
||||||
sha2 = "0.8"
|
sha2 = "0.8"
|
||||||
|
subtle = "2.2.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex-literal = "0.2"
|
hex-literal = "0.2"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
|
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};
|
use super::{montgomery, JubjubEngine, JubjubParams, PrimeOrder, Unknown};
|
||||||
|
|
||||||
@ -107,8 +107,7 @@ impl<E: JubjubEngine> Point<E, Unknown> {
|
|||||||
// as dy^2 + 1 = 0 has no solution in Fr.
|
// as dy^2 + 1 = 0 has no solution in Fr.
|
||||||
|
|
||||||
// tmp1 = y^2
|
// tmp1 = y^2
|
||||||
let mut tmp1 = y;
|
let mut tmp1 = y.square();
|
||||||
tmp1.square();
|
|
||||||
|
|
||||||
// tmp2 = (y^2 * d) + 1
|
// tmp2 = (y^2 * d) + 1
|
||||||
let mut tmp2 = tmp1;
|
let mut tmp2 = tmp1;
|
||||||
@ -126,7 +125,7 @@ impl<E: JubjubEngine> Point<E, Unknown> {
|
|||||||
match tmp1.sqrt() {
|
match tmp1.sqrt() {
|
||||||
Some(mut x) => {
|
Some(mut x) => {
|
||||||
if x.into_repr().is_odd() != sign {
|
if x.into_repr().is_odd() != sign {
|
||||||
x.negate();
|
x = x.neg();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut t = x;
|
let mut t = x;
|
||||||
@ -213,12 +212,9 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
|
|||||||
// only point of order 2 that is not the neutral element.
|
// only point of order 2 that is not the neutral element.
|
||||||
if y.is_zero() {
|
if y.is_zero() {
|
||||||
// This must be the point (0, 0) as above.
|
// This must be the point (0, 0) as above.
|
||||||
let mut neg1 = E::Fr::one();
|
|
||||||
neg1.negate();
|
|
||||||
|
|
||||||
Point {
|
Point {
|
||||||
x: E::Fr::zero(),
|
x: E::Fr::zero(),
|
||||||
y: neg1,
|
y: E::Fr::one().neg(),
|
||||||
t: E::Fr::zero(),
|
t: E::Fr::zero(),
|
||||||
z: E::Fr::one(),
|
z: E::Fr::one(),
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
@ -324,8 +320,8 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
|
|||||||
pub fn negate(&self) -> Self {
|
pub fn negate(&self) -> Self {
|
||||||
let mut p = self.clone();
|
let mut p = self.clone();
|
||||||
|
|
||||||
p.x.negate();
|
p.x = p.x.neg();
|
||||||
p.t.negate();
|
p.t = p.t.neg();
|
||||||
|
|
||||||
p
|
p
|
||||||
}
|
}
|
||||||
@ -338,27 +334,22 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
|
|||||||
// http://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
|
// http://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
|
||||||
|
|
||||||
// A = X1^2
|
// A = X1^2
|
||||||
let mut a = self.x;
|
let a = self.x.square();
|
||||||
a.square();
|
|
||||||
|
|
||||||
// B = Y1^2
|
// B = Y1^2
|
||||||
let mut b = self.y;
|
let b = self.y.square();
|
||||||
b.square();
|
|
||||||
|
|
||||||
// C = 2*Z1^2
|
// C = 2*Z1^2
|
||||||
let mut c = self.z;
|
let c = self.z.square().double();
|
||||||
c.square();
|
|
||||||
c.double();
|
|
||||||
|
|
||||||
// D = a*A
|
// D = a*A
|
||||||
// = -A
|
// = -A
|
||||||
let mut d = a;
|
let d = a.neg();
|
||||||
d.negate();
|
|
||||||
|
|
||||||
// E = (X1+Y1)^2 - A - B
|
// E = (X1+Y1)^2 - A - B
|
||||||
let mut e = self.x;
|
let mut e = self.x;
|
||||||
e.add_assign(&self.y);
|
e.add_assign(&self.y);
|
||||||
e.square();
|
e = e.square();
|
||||||
e.add_assign(&d); // -A = D
|
e.add_assign(&d); // -A = D
|
||||||
e.sub_assign(&b);
|
e.sub_assign(&b);
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ use ff::{
|
|||||||
PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField,
|
PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField,
|
||||||
};
|
};
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
use subtle::{Choice, ConditionallySelectable};
|
||||||
|
|
||||||
use super::ToUniform;
|
use super::ToUniform;
|
||||||
|
|
||||||
@ -269,6 +270,31 @@ 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 {
|
impl<'r> Add<&'r Fs> for Fs {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@ -488,21 +514,16 @@ impl Field for Fs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn double(&mut self) {
|
fn double(&self) -> Self {
|
||||||
|
let mut ret = *self;
|
||||||
|
|
||||||
// This cannot exceed the backing capacity.
|
// This cannot exceed the backing capacity.
|
||||||
self.0.mul2();
|
ret.0.mul2();
|
||||||
|
|
||||||
// However, it may need to be reduced.
|
// However, it may need to be reduced.
|
||||||
self.reduce();
|
ret.reduce();
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
ret
|
||||||
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> {
|
fn inverse(&self) -> Option<Self> {
|
||||||
@ -566,7 +587,7 @@ impl Field for Fs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn square(&mut self) {
|
fn square(&self) -> Self {
|
||||||
let mut carry = 0;
|
let mut carry = 0;
|
||||||
let r1 = mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry);
|
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);
|
let r2 = mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry);
|
||||||
@ -597,7 +618,10 @@ impl Field for Fs {
|
|||||||
let r5 = adc(r5, 0, &mut carry);
|
let r5 = adc(r5, 0, &mut carry);
|
||||||
let r6 = mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &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);
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,7 +699,7 @@ impl Fs {
|
|||||||
fn mul_bits<S: AsRef<[u64]>>(&self, bits: BitIterator<S>) -> Self {
|
fn mul_bits<S: AsRef<[u64]>>(&self, bits: BitIterator<S>) -> Self {
|
||||||
let mut res = Self::zero();
|
let mut res = Self::zero();
|
||||||
for bit in bits {
|
for bit in bits {
|
||||||
res.double();
|
res = res.double();
|
||||||
|
|
||||||
if bit {
|
if bit {
|
||||||
res.add_assign(self)
|
res.add_assign(self)
|
||||||
@ -727,8 +751,7 @@ impl SqrtField for Fs {
|
|||||||
0x4199cec0404d0ec0,
|
0x4199cec0404d0ec0,
|
||||||
0x39f6d3a994cebea,
|
0x39f6d3a994cebea,
|
||||||
]);
|
]);
|
||||||
let mut a0 = a1;
|
let mut a0 = a1.square();
|
||||||
a0.square();
|
|
||||||
a0.mul_assign(self);
|
a0.mul_assign(self);
|
||||||
|
|
||||||
if a0 == NEGATIVE_ONE {
|
if a0 == NEGATIVE_ONE {
|
||||||
@ -742,8 +765,7 @@ impl SqrtField for Fs {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_neg_one() {
|
fn test_neg_one() {
|
||||||
let mut o = Fs::one();
|
let o = Fs::one().neg();
|
||||||
o.negate();
|
|
||||||
|
|
||||||
assert_eq!(NEGATIVE_ONE, o);
|
assert_eq!(NEGATIVE_ONE, o);
|
||||||
}
|
}
|
||||||
@ -1395,16 +1417,15 @@ fn test_fs_mul_assign() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fr_squaring() {
|
fn test_fr_squaring() {
|
||||||
let mut a = Fs(FsRepr([
|
let a = Fs(FsRepr([
|
||||||
0xffffffffffffffff,
|
0xffffffffffffffff,
|
||||||
0xffffffffffffffff,
|
0xffffffffffffffff,
|
||||||
0xffffffffffffffff,
|
0xffffffffffffffff,
|
||||||
0xe7db4ea6533afa8,
|
0xe7db4ea6533afa8,
|
||||||
]));
|
]));
|
||||||
assert!(a.is_valid());
|
assert!(a.is_valid());
|
||||||
a.square();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
a,
|
a.square(),
|
||||||
Fs::from_repr(FsRepr([
|
Fs::from_repr(FsRepr([
|
||||||
0x12c7f55cbc52fbaa,
|
0x12c7f55cbc52fbaa,
|
||||||
0xdedc98a0b5e6ce9e,
|
0xdedc98a0b5e6ce9e,
|
||||||
@ -1423,8 +1444,7 @@ fn test_fr_squaring() {
|
|||||||
// Ensure that (a * a) = a^2
|
// Ensure that (a * a) = a^2
|
||||||
let a = Fs::random(&mut rng);
|
let a = Fs::random(&mut rng);
|
||||||
|
|
||||||
let mut tmp = a;
|
let tmp = a.square();
|
||||||
tmp.square();
|
|
||||||
|
|
||||||
let mut tmp2 = a;
|
let mut tmp2 = a;
|
||||||
tmp2.mul_assign(&a);
|
tmp2.mul_assign(&a);
|
||||||
@ -1462,19 +1482,15 @@ fn test_fs_double() {
|
|||||||
|
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
// Ensure doubling a is equivalent to adding a to itself.
|
// Ensure doubling a is equivalent to adding a to itself.
|
||||||
let mut a = Fs::random(&mut rng);
|
let a = Fs::random(&mut rng);
|
||||||
let mut b = a;
|
assert_eq!(a.double(), a + a);
|
||||||
b.add_assign(&a);
|
|
||||||
a.double();
|
|
||||||
assert_eq!(a, b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fs_negate() {
|
fn test_fs_neg() {
|
||||||
{
|
{
|
||||||
let mut a = Fs::zero();
|
let a = Fs::zero().neg();
|
||||||
a.negate();
|
|
||||||
|
|
||||||
assert!(a.is_zero());
|
assert!(a.is_zero());
|
||||||
}
|
}
|
||||||
@ -1487,8 +1503,7 @@ fn test_fs_negate() {
|
|||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
// Ensure (a - (-a)) = 0.
|
// Ensure (a - (-a)) = 0.
|
||||||
let mut a = Fs::random(&mut rng);
|
let mut a = Fs::random(&mut rng);
|
||||||
let mut b = a;
|
let b = a.neg();
|
||||||
b.negate();
|
|
||||||
a.add_assign(&b);
|
a.add_assign(&b);
|
||||||
|
|
||||||
assert!(a.is_zero());
|
assert!(a.is_zero());
|
||||||
@ -1534,10 +1549,8 @@ fn test_fs_sqrt() {
|
|||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
// Ensure sqrt(a^2) = a or -a
|
// Ensure sqrt(a^2) = a or -a
|
||||||
let a = Fs::random(&mut rng);
|
let a = Fs::random(&mut rng);
|
||||||
let mut nega = a;
|
let nega = a.neg();
|
||||||
nega.negate();
|
let b = a.square();
|
||||||
let mut b = a;
|
|
||||||
b.square();
|
|
||||||
|
|
||||||
let b = b.sqrt().unwrap();
|
let b = b.sqrt().unwrap();
|
||||||
|
|
||||||
@ -1548,10 +1561,8 @@ fn test_fs_sqrt() {
|
|||||||
// Ensure sqrt(a)^2 = a for random a
|
// Ensure sqrt(a)^2 = a for random a
|
||||||
let a = Fs::random(&mut rng);
|
let a = Fs::random(&mut rng);
|
||||||
|
|
||||||
if let Some(mut tmp) = a.sqrt() {
|
if let Some(tmp) = a.sqrt() {
|
||||||
tmp.square();
|
assert_eq!(a, tmp.square());
|
||||||
|
|
||||||
assert_eq!(a, tmp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,8 +195,7 @@ impl JubjubParams<Bls12> for JubjubBls12 {
|
|||||||
impl JubjubBls12 {
|
impl JubjubBls12 {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let montgomery_a = Fr::from_str("40962").unwrap();
|
let montgomery_a = Fr::from_str("40962").unwrap();
|
||||||
let mut montgomery_2a = montgomery_a;
|
let montgomery_2a = montgomery_a.double();
|
||||||
montgomery_2a.double();
|
|
||||||
|
|
||||||
let mut tmp_params = JubjubBls12 {
|
let mut tmp_params = JubjubBls12 {
|
||||||
// d = -(10240/10241)
|
// d = -(10240/10241)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
|
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};
|
use super::{edwards, JubjubEngine, JubjubParams, PrimeOrder, Unknown};
|
||||||
|
|
||||||
@ -50,8 +50,7 @@ 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) -> Option<Self> {
|
||||||
// Given an x on the curve, y = sqrt(x^3 + A*x^2 + x)
|
// Given an x on the curve, y = sqrt(x^3 + A*x^2 + x)
|
||||||
|
|
||||||
let mut x2 = x;
|
let mut x2 = x.square();
|
||||||
x2.square();
|
|
||||||
|
|
||||||
let mut rhs = x2;
|
let mut rhs = x2;
|
||||||
rhs.mul_assign(params.montgomery_a());
|
rhs.mul_assign(params.montgomery_a());
|
||||||
@ -62,7 +61,7 @@ impl<E: JubjubEngine> Point<E, Unknown> {
|
|||||||
match rhs.sqrt() {
|
match rhs.sqrt() {
|
||||||
Some(mut y) => {
|
Some(mut y) => {
|
||||||
if y.into_repr().is_odd() != sign {
|
if y.into_repr().is_odd() != sign {
|
||||||
y.negate();
|
y = y.neg();
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Point {
|
Some(Point {
|
||||||
@ -190,7 +189,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
|
|||||||
pub fn negate(&self) -> Self {
|
pub fn negate(&self) -> Self {
|
||||||
let mut p = self.clone();
|
let mut p = self.clone();
|
||||||
|
|
||||||
p.y.negate();
|
p.y = p.y.neg();
|
||||||
|
|
||||||
p
|
p
|
||||||
}
|
}
|
||||||
@ -216,24 +215,21 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
|
|||||||
{
|
{
|
||||||
let mut tmp = *params.montgomery_a();
|
let mut tmp = *params.montgomery_a();
|
||||||
tmp.mul_assign(&self.x);
|
tmp.mul_assign(&self.x);
|
||||||
tmp.double();
|
tmp = tmp.double();
|
||||||
delta.add_assign(&tmp);
|
delta.add_assign(&tmp);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut tmp = self.x;
|
let mut tmp = self.x.square();
|
||||||
tmp.square();
|
|
||||||
delta.add_assign(&tmp);
|
delta.add_assign(&tmp);
|
||||||
tmp.double();
|
tmp = tmp.double();
|
||||||
delta.add_assign(&tmp);
|
delta.add_assign(&tmp);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut tmp = self.y;
|
let tmp = self.y.double();
|
||||||
tmp.double();
|
|
||||||
delta.mul_assign(&tmp.inverse().expect("y is nonzero so this must be nonzero"));
|
delta.mul_assign(&tmp.inverse().expect("y is nonzero so this must be nonzero"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut x3 = delta;
|
let mut x3 = delta.square();
|
||||||
x3.square();
|
|
||||||
x3.sub_assign(params.montgomery_a());
|
x3.sub_assign(params.montgomery_a());
|
||||||
x3.sub_assign(&self.x);
|
x3.sub_assign(&self.x);
|
||||||
x3.sub_assign(&self.x);
|
x3.sub_assign(&self.x);
|
||||||
@ -242,7 +238,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
|
|||||||
y3.sub_assign(&self.x);
|
y3.sub_assign(&self.x);
|
||||||
y3.mul_assign(&delta);
|
y3.mul_assign(&delta);
|
||||||
y3.add_assign(&self.y);
|
y3.add_assign(&self.y);
|
||||||
y3.negate();
|
y3 = y3.neg();
|
||||||
|
|
||||||
Point {
|
Point {
|
||||||
x: x3,
|
x: x3,
|
||||||
@ -282,8 +278,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut x3 = delta;
|
let mut x3 = delta.square();
|
||||||
x3.square();
|
|
||||||
x3.sub_assign(params.montgomery_a());
|
x3.sub_assign(params.montgomery_a());
|
||||||
x3.sub_assign(&self.x);
|
x3.sub_assign(&self.x);
|
||||||
x3.sub_assign(&other.x);
|
x3.sub_assign(&other.x);
|
||||||
@ -292,7 +287,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
|
|||||||
y3.sub_assign(&self.x);
|
y3.sub_assign(&self.x);
|
||||||
y3.mul_assign(&delta);
|
y3.mul_assign(&delta);
|
||||||
y3.add_assign(&self.y);
|
y3.add_assign(&self.y);
|
||||||
y3.negate();
|
y3 = y3.neg();
|
||||||
|
|
||||||
Point {
|
Point {
|
||||||
x: x3,
|
x: x3,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::{edwards, montgomery, JubjubEngine, JubjubParams, PrimeOrder};
|
use super::{edwards, montgomery, JubjubEngine, JubjubParams, PrimeOrder};
|
||||||
|
|
||||||
use ff::{Field, LegendreSymbol, PrimeField, PrimeFieldRepr, SqrtField};
|
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_core::{RngCore, SeedableRng};
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
@ -20,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 {
|
fn is_on_mont_curve<E: JubjubEngine, P: JubjubParams<E>>(x: E::Fr, y: E::Fr, params: &P) -> bool {
|
||||||
let mut lhs = y;
|
let lhs = y.square();
|
||||||
lhs.square();
|
|
||||||
|
|
||||||
let mut x2 = x;
|
let x2 = x.square();
|
||||||
x2.square();
|
|
||||||
|
|
||||||
let mut x3 = x2;
|
let mut x3 = x2;
|
||||||
x3.mul_assign(&x);
|
x3.mul_assign(&x);
|
||||||
@ -42,11 +40,9 @@ fn is_on_twisted_edwards_curve<E: JubjubEngine, P: JubjubParams<E>>(
|
|||||||
y: E::Fr,
|
y: E::Fr,
|
||||||
params: &P,
|
params: &P,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut x2 = x;
|
let x2 = x.square();
|
||||||
x2.square();
|
|
||||||
|
|
||||||
let mut y2 = y;
|
let y2 = y.square();
|
||||||
y2.square();
|
|
||||||
|
|
||||||
// -x^2 + y^2
|
// -x^2 + y^2
|
||||||
let mut lhs = y2;
|
let mut lhs = y2;
|
||||||
@ -310,15 +306,11 @@ fn test_back_and_forth<E: JubjubEngine>(params: &E::Params) {
|
|||||||
|
|
||||||
fn test_jubjub_params<E: JubjubEngine>(params: &E::Params) {
|
fn test_jubjub_params<E: JubjubEngine>(params: &E::Params) {
|
||||||
// a = -1
|
// a = -1
|
||||||
let mut a = E::Fr::one();
|
let a = E::Fr::one().neg();
|
||||||
a.negate();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// Check that 2A is consistent with A
|
// Check that 2A is consistent with A
|
||||||
let mut tmp = *params.montgomery_a();
|
assert_eq!(¶ms.montgomery_a().double(), params.montgomery_2a());
|
||||||
tmp.double();
|
|
||||||
|
|
||||||
assert_eq!(&tmp, params.montgomery_2a());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -339,7 +331,7 @@ fn test_jubjub_params<E: JubjubEngine>(params: &E::Params) {
|
|||||||
assert!(tmp.inverse().unwrap().legendre() == LegendreSymbol::QuadraticNonResidue);
|
assert!(tmp.inverse().unwrap().legendre() == LegendreSymbol::QuadraticNonResidue);
|
||||||
|
|
||||||
// tmp = -d
|
// tmp = -d
|
||||||
tmp.negate();
|
tmp = tmp.neg();
|
||||||
|
|
||||||
// -d is nonsquare
|
// -d is nonsquare
|
||||||
assert!(tmp.legendre() == LegendreSymbol::QuadraticNonResidue);
|
assert!(tmp.legendre() == LegendreSymbol::QuadraticNonResidue);
|
||||||
@ -350,8 +342,7 @@ fn test_jubjub_params<E: JubjubEngine>(params: &E::Params) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
// Check that A^2 - 4 is nonsquare:
|
// Check that A^2 - 4 is nonsquare:
|
||||||
let mut tmp = params.montgomery_a().clone();
|
let mut tmp = params.montgomery_a().square();
|
||||||
tmp.square();
|
|
||||||
tmp.sub_assign(&E::Fr::from_str("4").unwrap());
|
tmp.sub_assign(&E::Fr::from_str("4").unwrap());
|
||||||
assert!(tmp.legendre() == LegendreSymbol::QuadraticNonResidue);
|
assert!(tmp.legendre() == LegendreSymbol::QuadraticNonResidue);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::jubjub::*;
|
use crate::jubjub::*;
|
||||||
use ff::{Field, PrimeField, PrimeFieldRepr};
|
use ff::{Field, PrimeField, PrimeFieldRepr};
|
||||||
use std::ops::AddAssign;
|
use std::ops::{AddAssign, Neg};
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Personalization {
|
pub enum Personalization {
|
||||||
@ -58,14 +58,14 @@ where
|
|||||||
if a {
|
if a {
|
||||||
tmp.add_assign(&cur);
|
tmp.add_assign(&cur);
|
||||||
}
|
}
|
||||||
cur.double(); // 2^1 * cur
|
cur = cur.double(); // 2^1 * cur
|
||||||
if b {
|
if b {
|
||||||
tmp.add_assign(&cur);
|
tmp.add_assign(&cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
// conditionally negate
|
// conditionally negate
|
||||||
if c {
|
if c {
|
||||||
tmp.negate();
|
tmp = tmp.neg();
|
||||||
}
|
}
|
||||||
|
|
||||||
acc.add_assign(&tmp);
|
acc.add_assign(&tmp);
|
||||||
@ -75,9 +75,7 @@ where
|
|||||||
if chunks_remaining == 0 {
|
if chunks_remaining == 0 {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
cur.double(); // 2^2 * cur
|
cur = cur.double().double().double(); // 2^4 * cur
|
||||||
cur.double(); // 2^3 * cur
|
|
||||||
cur.double(); // 2^4 * cur
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use crate::jubjub::{edwards::Point, FixedGenerators, JubjubEngine, JubjubParams,
|
|||||||
use ff::{Field, PrimeField, PrimeFieldRepr};
|
use ff::{Field, PrimeField, PrimeFieldRepr};
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
use std::ops::{AddAssign, MulAssign};
|
use std::ops::{AddAssign, MulAssign, Neg};
|
||||||
|
|
||||||
use crate::util::hash_to_scalar;
|
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);
|
let z = E::Fs::random(rng);
|
||||||
|
|
||||||
s.mul_assign(&z);
|
s.mul_assign(&z);
|
||||||
s.negate();
|
s = s.neg();
|
||||||
|
|
||||||
r = r.mul(z, params);
|
r = r.mul(z, params);
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use ff::Field;
|
use ff::Field;
|
||||||
use pairing::Engine;
|
use pairing::Engine;
|
||||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||||
|
|
||||||
use bellman::{ConstraintSystem, SynthesisError};
|
use bellman::{ConstraintSystem, SynthesisError};
|
||||||
|
|
||||||
@ -323,8 +323,7 @@ impl<E: JubjubEngine> EdwardsPoint<E> {
|
|||||||
|
|
||||||
// Compute C = d*A*A
|
// Compute C = d*A*A
|
||||||
let c = AllocatedNum::alloc(cs.namespace(|| "C"), || {
|
let c = AllocatedNum::alloc(cs.namespace(|| "C"), || {
|
||||||
let mut t0 = *a.get_value().get()?;
|
let mut t0 = a.get_value().get()?.square();
|
||||||
t0.square();
|
|
||||||
t0.mul_assign(params.edwards_d());
|
t0.mul_assign(params.edwards_d());
|
||||||
|
|
||||||
Ok(t0)
|
Ok(t0)
|
||||||
@ -340,7 +339,7 @@ impl<E: JubjubEngine> EdwardsPoint<E> {
|
|||||||
// Compute x3 = (2.A) / (1 + C)
|
// Compute x3 = (2.A) / (1 + C)
|
||||||
let x3 = AllocatedNum::alloc(cs.namespace(|| "x3"), || {
|
let x3 = AllocatedNum::alloc(cs.namespace(|| "x3"), || {
|
||||||
let mut t0 = *a.get_value().get()?;
|
let mut t0 = *a.get_value().get()?;
|
||||||
t0.double();
|
t0 = t0.double();
|
||||||
|
|
||||||
let mut t1 = E::Fr::one();
|
let mut t1 = E::Fr::one();
|
||||||
t1.add_assign(c.get_value().get()?);
|
t1.add_assign(c.get_value().get()?);
|
||||||
@ -366,8 +365,7 @@ impl<E: JubjubEngine> EdwardsPoint<E> {
|
|||||||
// Compute y3 = (U - 2.A) / (1 - C)
|
// Compute y3 = (U - 2.A) / (1 - C)
|
||||||
let y3 = AllocatedNum::alloc(cs.namespace(|| "y3"), || {
|
let y3 = AllocatedNum::alloc(cs.namespace(|| "y3"), || {
|
||||||
let mut t0 = *a.get_value().get()?;
|
let mut t0 = *a.get_value().get()?;
|
||||||
t0.double();
|
t0 = t0.double().neg();
|
||||||
t0.negate();
|
|
||||||
t0.add_assign(t.get_value().get()?);
|
t0.add_assign(t.get_value().get()?);
|
||||||
|
|
||||||
let mut t1 = E::Fr::one();
|
let mut t1 = E::Fr::one();
|
||||||
@ -613,8 +611,7 @@ impl<E: JubjubEngine> MontgomeryPoint<E> {
|
|||||||
|
|
||||||
// Compute x'' = lambda^2 - A - x - x'
|
// Compute x'' = lambda^2 - A - x - x'
|
||||||
let xprime = AllocatedNum::alloc(cs.namespace(|| "xprime"), || {
|
let xprime = AllocatedNum::alloc(cs.namespace(|| "xprime"), || {
|
||||||
let mut t0 = *lambda.get_value().get()?;
|
let mut t0 = lambda.get_value().get()?.square();
|
||||||
t0.square();
|
|
||||||
t0.sub_assign(params.montgomery_a());
|
t0.sub_assign(params.montgomery_a());
|
||||||
t0.sub_assign(self.x.get_value().get()?);
|
t0.sub_assign(self.x.get_value().get()?);
|
||||||
t0.sub_assign(other.x.get_value().get()?);
|
t0.sub_assign(other.x.get_value().get()?);
|
||||||
@ -642,7 +639,7 @@ impl<E: JubjubEngine> MontgomeryPoint<E> {
|
|||||||
t0.sub_assign(self.x.get_value().get()?);
|
t0.sub_assign(self.x.get_value().get()?);
|
||||||
t0.mul_assign(lambda.get_value().get()?);
|
t0.mul_assign(lambda.get_value().get()?);
|
||||||
t0.add_assign(self.y.get_value().get()?);
|
t0.add_assign(self.y.get_value().get()?);
|
||||||
t0.negate();
|
t0 = t0.neg();
|
||||||
|
|
||||||
Ok(t0)
|
Ok(t0)
|
||||||
})?;
|
})?;
|
||||||
|
@ -245,7 +245,7 @@ impl<'a, E: JubjubEngine> Circuit<E> for Spend<'a, E> {
|
|||||||
let mut coeff = E::Fr::one();
|
let mut coeff = E::Fr::one();
|
||||||
for bit in &value_bits {
|
for bit in &value_bits {
|
||||||
value_num = value_num.add_bool_with_coeff(CS::one(), bit, coeff);
|
value_num = value_num.add_bool_with_coeff(CS::one(), bit, coeff);
|
||||||
coeff.double();
|
coeff = coeff.double();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place the value in the note
|
// Place the value in the note
|
||||||
|
@ -268,7 +268,7 @@ impl NoteValue {
|
|||||||
let mut coeff = E::Fr::one();
|
let mut coeff = E::Fr::one();
|
||||||
for b in &self.bits {
|
for b in &self.bits {
|
||||||
tmp = tmp + (coeff, b.get_variable());
|
tmp = tmp + (coeff, b.get_variable());
|
||||||
coeff.double();
|
coeff = coeff.double();
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp
|
tmp
|
||||||
|
@ -5,7 +5,7 @@ use bellman::{
|
|||||||
use ff::Field;
|
use ff::Field;
|
||||||
use pairing::bls12_381::{Bls12, Fr};
|
use pairing::bls12_381::{Bls12, Fr};
|
||||||
use rand_core::OsRng;
|
use rand_core::OsRng;
|
||||||
use std::ops::AddAssign;
|
use std::ops::{AddAssign, Neg};
|
||||||
use zcash_primitives::{
|
use zcash_primitives::{
|
||||||
jubjub::{edwards, fs::Fs, FixedGenerators, JubjubBls12, Unknown},
|
jubjub::{edwards, fs::Fs, FixedGenerators, JubjubBls12, Unknown},
|
||||||
primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment},
|
primitives::{Diversifier, Note, PaymentAddress, ProofGenerationKey, ValueCommitment},
|
||||||
@ -202,8 +202,7 @@ impl SaplingProvingContext {
|
|||||||
|
|
||||||
// Accumulate the value commitment randomness in the context
|
// Accumulate the value commitment randomness in the context
|
||||||
{
|
{
|
||||||
let mut tmp = rcv;
|
let mut tmp = rcv.neg(); // Outputs subtract from the total.
|
||||||
tmp.negate(); // Outputs subtract from the total.
|
|
||||||
tmp.add_assign(&self.bsk);
|
tmp.add_assign(&self.bsk);
|
||||||
|
|
||||||
// Update the context
|
// Update the context
|
||||||
|
Loading…
Reference in New Issue
Block a user