Merge pull request #223 from str4d/remove-primefieldrepr

Remove ff::PrimeFieldRepr
This commit is contained in:
str4d 2020-05-01 08:59:41 +12:00 committed by GitHub
commit b02cf3b467
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 2303 additions and 3752 deletions

View File

@ -11,7 +11,7 @@
//! [`EvaluationDomain`]: crate::domain::EvaluationDomain
//! [Groth16]: https://eprint.iacr.org/2016/260
use ff::{Field, PrimeField, ScalarEngine};
use ff::{Field, PowVartime, PrimeField, ScalarEngine};
use group::CurveProjective;
use std::ops::{AddAssign, MulAssign, SubAssign};

View File

@ -313,12 +313,12 @@ pub fn field_into_allocated_bits_le<E: ScalarEngine, CS: ConstraintSystem<E>, F:
// Deconstruct in big-endian bit order
let values = match value {
Some(ref value) => {
let mut field_char = BitIterator::new(F::char());
let mut field_char = BitIterator::<u8, _>::new(F::char());
let mut tmp = Vec::with_capacity(F::NUM_BITS as usize);
let mut found_one = false;
for b in BitIterator::new(value.into_repr()) {
for b in BitIterator::<u8, _>::new(value.into_repr()) {
// Skip leading bits
found_one |= field_char.next().unwrap();
if !found_one {

View File

@ -1,4 +1,4 @@
use ff::{Field, PrimeField, ScalarEngine};
use ff::{PowVartime, PrimeField, ScalarEngine};
use crate::{ConstraintSystem, LinearCombination, SynthesisError, Variable};

View File

@ -1,6 +1,6 @@
//! Gadgets representing numbers in the scalar field of the underlying curve.
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, ScalarEngine};
use ff::{BitIterator, Field, PrimeField, ScalarEngine};
use std::ops::{AddAssign, MulAssign};
use crate::{ConstraintSystem, LinearCombination, SynthesisError, Variable};
@ -103,9 +103,8 @@ impl<E: ScalarEngine> AllocatedNum<E> {
// We want to ensure that the bit representation of a is
// less than or equal to r - 1.
let mut a = self.value.map(|e| BitIterator::new(e.into_repr()));
let mut b = E::Fr::char();
b.sub_noborrow(&1.into());
let mut a = self.value.map(|e| BitIterator::<u8, _>::new(e.into_repr()));
let b = (-E::Fr::one()).into_repr();
let mut result = vec![];
@ -115,7 +114,7 @@ impl<E: ScalarEngine> AllocatedNum<E> {
let mut found_one = false;
let mut i = 0;
for b in BitIterator::new(b) {
for b in BitIterator::<u8, _>::new(b) {
let a_bit = a.as_mut().map(|e| e.next().unwrap());
// Skip over unset bits at the beginning
@ -558,7 +557,7 @@ mod test {
assert!(cs.is_satisfied());
for (b, a) in BitIterator::new(r.into_repr())
for (b, a) in BitIterator::<u8, _>::new(r.into_repr())
.skip(1)
.zip(bits.iter().rev())
{

View File

@ -1,6 +1,6 @@
//! Helpers for testing circuit implementations.
use ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine};
use ff::{Field, PowVartime, PrimeField, ScalarEngine};
use crate::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable};
@ -106,7 +106,12 @@ fn hash_lc<E: ScalarEngine>(terms: &[(Variable, E::Fr)], h: &mut Blake2sState) {
}
}
coeff.into_repr().write_be(&mut buf[9..]).unwrap();
// BLS12-381's Fr is canonically serialized in little-endian, but the hasher
// writes its coefficients in big endian. For now, we flip the endianness
// manually, which is not necessarily correct for circuits using other curves.
// TODO: Fix this in a standalone commit, and document the no-op change.
let coeff_be: Vec<_> = coeff.into_repr().as_ref().iter().cloned().rev().collect();
buf[9..].copy_from_slice(&coeff_be[..]);
h.update(&buf);
}

View File

@ -2,7 +2,7 @@ use rand_core::RngCore;
use std::ops::{AddAssign, MulAssign};
use std::sync::Arc;
use ff::{Field, PrimeField};
use ff::{Field, PowVartime};
use group::{CurveAffine, CurveProjective, Wnaf};
use pairing::Engine;
@ -273,7 +273,7 @@ where
exp.mul_assign(&coeff);
// Exponentiate
*h = g1_wnaf.scalar(exp.into_repr());
*h = g1_wnaf.scalar(&exp);
}
// Batch normalize
@ -376,14 +376,14 @@ where
// Compute A query (in G1)
if !at.is_zero() {
*a = g1_wnaf.scalar(at.into_repr());
*a = g1_wnaf.scalar(&at);
}
// Compute B query (in G1/G2)
if !bt.is_zero() {
let bt_repr = bt.into_repr();
*b_g1 = g1_wnaf.scalar(bt_repr);
*b_g2 = g2_wnaf.scalar(bt_repr);
();
*b_g1 = g1_wnaf.scalar(&bt);
*b_g2 = g2_wnaf.scalar(&bt);
}
at.mul_assign(&beta);
@ -394,7 +394,7 @@ where
e.add_assign(&ct);
e.mul_assign(inv);
*ext = g1_wnaf.scalar(e.into_repr());
*ext = g1_wnaf.scalar(&e);
}
// Batch normalize

View File

@ -4,7 +4,7 @@ use std::sync::Arc;
use futures::Future;
use ff::{Field, PrimeField};
use ff::Field;
use group::{CurveAffine, CurveProjective};
use pairing::Engine;
@ -229,26 +229,14 @@ where
let a_len = a.len() - 1;
a.truncate(a_len);
// TODO: parallelize if it's even helpful
let a = Arc::new(a.into_iter().map(|s| s.0.into_repr()).collect::<Vec<_>>());
let a = Arc::new(a.into_iter().map(|s| s.0).collect::<Vec<_>>());
multiexp(&worker, params.get_h(a.len())?, FullDensity, a)
};
// TODO: parallelize if it's even helpful
let input_assignment = Arc::new(
prover
.input_assignment
.into_iter()
.map(|s| s.into_repr())
.collect::<Vec<_>>(),
);
let aux_assignment = Arc::new(
prover
.aux_assignment
.into_iter()
.map(|s| s.into_repr())
.collect::<Vec<_>>(),
);
let input_assignment = Arc::new(prover.input_assignment);
let aux_assignment = Arc::new(prover.aux_assignment);
let l = multiexp(
&worker,

View File

@ -1,4 +1,4 @@
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, SqrtField};
use ff::{Field, PowVartime, PrimeField, ScalarEngine, SqrtField};
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
use pairing::{Engine, PairingCurveAffine};
@ -6,7 +6,7 @@ use rand_core::RngCore;
use std::cmp::Ordering;
use std::fmt;
use std::num::Wrapping;
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use std::ops::{Add, AddAssign, BitAnd, Mul, MulAssign, Neg, Shr, Sub, SubAssign};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
const MODULUS_R: Wrapping<u32> = Wrapping(64513);
@ -32,6 +32,12 @@ impl fmt::Display for Fr {
}
}
impl From<u64> for Fr {
fn from(v: u64) -> Fr {
Fr(Wrapping((v % MODULUS_R.0 as u64) as u32))
}
}
impl ConditionallySelectable for Fr {
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
Fr(Wrapping(u32::conditional_select(
@ -42,6 +48,18 @@ impl ConditionallySelectable for Fr {
}
}
impl Ord for Fr {
fn cmp(&self, other: &Fr) -> Ordering {
(self.0).0.cmp(&(other.0).0)
}
}
impl PartialOrd for Fr {
fn partial_cmp(&self, other: &Fr) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Neg for Fr {
type Output = Self;
@ -143,6 +161,23 @@ impl MulAssign for Fr {
}
}
impl BitAnd<u64> for Fr {
type Output = u64;
fn bitand(self, rhs: u64) -> u64 {
(self.0).0 as u64 & rhs
}
}
impl Shr<u32> for Fr {
type Output = Fr;
fn shr(mut self, rhs: u32) -> Fr {
self.0 = Wrapping((self.0).0 >> rhs);
self
}
}
impl Field for Fr {
fn random<R: RngCore + ?std::marker::Sized>(rng: &mut R) -> Self {
Fr(Wrapping(rng.next_u32()) % MODULUS_R)
@ -190,9 +225,9 @@ impl SqrtField for Fr {
// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
let mut c = Fr::root_of_unity();
// r = self^((t + 1) // 2)
let mut r = self.pow_vartime([32]);
let mut r = self.pow_vartime([32u64]);
// t = self^t
let mut t = self.pow_vartime([63]);
let mut t = self.pow_vartime([63u64]);
let mut m = Fr::S;
while t != <Fr as Field>::one() {
@ -222,86 +257,35 @@ impl SqrtField for Fr {
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct FrRepr([u64; 1]);
impl Ord for FrRepr {
fn cmp(&self, other: &FrRepr) -> Ordering {
(self.0)[0].cmp(&(other.0)[0])
}
}
impl PartialOrd for FrRepr {
fn partial_cmp(&self, other: &FrRepr) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl fmt::Display for FrRepr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}", (self.0)[0])
}
}
impl From<u64> for FrRepr {
fn from(v: u64) -> FrRepr {
FrRepr([v])
}
}
pub struct FrRepr([u8; 8]);
impl From<Fr> for FrRepr {
fn from(v: Fr) -> FrRepr {
FrRepr([(v.0).0 as u64])
FrRepr::from(&v)
}
}
impl AsMut<[u64]> for FrRepr {
fn as_mut(&mut self) -> &mut [u64] {
impl<'a> From<&'a Fr> for FrRepr {
fn from(v: &'a Fr) -> FrRepr {
FrRepr(((v.0).0 as u64).to_le_bytes())
}
}
impl AsMut<[u8]> for FrRepr {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0[..]
}
}
impl AsRef<[u64]> for FrRepr {
fn as_ref(&self) -> &[u64] {
impl AsRef<[u8]> for FrRepr {
fn as_ref(&self) -> &[u8] {
&self.0[..]
}
}
impl Default for FrRepr {
fn default() -> FrRepr {
FrRepr::from(0u64)
}
}
impl PrimeFieldRepr for FrRepr {
fn sub_noborrow(&mut self, other: &Self) {
self.0[0] = self.0[0].wrapping_sub(other.0[0]);
}
fn add_nocarry(&mut self, other: &Self) {
self.0[0] = self.0[0].wrapping_add(other.0[0]);
}
fn num_bits(&self) -> u32 {
64 - self.0[0].leading_zeros()
}
fn is_zero(&self) -> bool {
self.0[0] == 0
}
fn is_odd(&self) -> bool {
!self.is_even()
}
fn is_even(&self) -> bool {
self.0[0] % 2 == 0
}
fn div2(&mut self) {
self.shr(1)
}
fn shr(&mut self, amt: u32) {
self.0[0] >>= amt;
}
fn mul2(&mut self) {
self.shl(1)
}
fn shl(&mut self, amt: u32) {
self.0[0] <<= amt;
FrRepr([0; 8])
}
}
@ -312,11 +296,12 @@ impl PrimeField for Fr {
const CAPACITY: u32 = 15;
const S: u32 = 10;
fn from_repr(repr: FrRepr) -> Result<Self, PrimeFieldDecodingError> {
if repr.0[0] >= (MODULUS_R.0 as u64) {
Err(PrimeFieldDecodingError::NotInField)
fn from_repr(repr: FrRepr) -> Option<Self> {
let v = u64::from_le_bytes(repr.0);
if v >= (MODULUS_R.0 as u64) {
None
} else {
Ok(Fr(Wrapping(repr.0[0] as u32)))
Some(Fr(Wrapping(v as u32)))
}
}
@ -324,6 +309,10 @@ impl PrimeField for Fr {
FrRepr::from(*self)
}
fn is_odd(&self) -> bool {
(self.0).0 % 2 != 0
}
fn char() -> FrRepr {
Fr(MODULUS_R).into()
}
@ -423,7 +412,7 @@ impl CurveProjective for Fr {
*self
}
fn recommended_wnaf_for_scalar(_: <Self::Scalar as PrimeField>::Repr) -> usize {
fn recommended_wnaf_for_scalar(_: &Self::Scalar) -> usize {
3
}

View File

@ -1,4 +1,4 @@
use ff::{Field, PrimeField};
use ff::{Field, PowVartime, PrimeField};
use pairing::Engine;
mod dummy_engine;
@ -127,22 +127,22 @@ fn test_xordemo() {
let mut root_of_unity = Fr::root_of_unity();
// We expect this to be a 2^10 root of unity
assert_eq!(Fr::one(), root_of_unity.pow_vartime(&[1 << 10]));
assert_eq!(Fr::one(), root_of_unity.pow_vartime(&[1u64 << 10]));
// Let's turn it into a 2^3 root of unity.
root_of_unity = root_of_unity.pow_vartime(&[1 << 7]);
assert_eq!(Fr::one(), root_of_unity.pow_vartime(&[1 << 3]));
root_of_unity = root_of_unity.pow_vartime(&[1u64 << 7]);
assert_eq!(Fr::one(), root_of_unity.pow_vartime(&[1u64 << 3]));
assert_eq!(Fr::from_str("20201").unwrap(), root_of_unity);
// Let's compute all the points in our evaluation domain.
let mut points = Vec::with_capacity(8);
for i in 0..8 {
for i in 0u64..8 {
points.push(root_of_unity.pow_vartime(&[i]));
}
// Let's compute t(tau) = (tau - p_0)(tau - p_1)...
// = tau^8 - 1
let mut t_at_tau = tau.pow_vartime(&[8]);
let mut t_at_tau = tau.pow_vartime(&[8u64]);
t_at_tau.sub_assign(&Fr::one());
{
let mut tmp = Fr::one();

View File

@ -1,6 +1,6 @@
use super::multicore::Worker;
use bit_vec::{self, BitVec};
use ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine};
use ff::{Field, PrimeField, ScalarEngine};
use futures::Future;
use group::{CurveAffine, CurveProjective};
use std::io;
@ -154,7 +154,7 @@ fn multiexp_inner<Q, D, G, S>(
pool: &Worker,
bases: S,
density_map: D,
exponents: Arc<Vec<<<G::Engine as ScalarEngine>::Fr as PrimeField>::Repr>>,
exponents: Arc<Vec<<G::Engine as ScalarEngine>::Fr>>,
mut skip: u32,
c: u32,
handle_trivial: bool,
@ -181,13 +181,12 @@ where
// Create space for the buckets
let mut buckets = vec![G::zero(); (1 << c) - 1];
let zero = <G::Engine as ScalarEngine>::Fr::zero().into_repr();
let one = <G::Engine as ScalarEngine>::Fr::one().into_repr();
let one = <G::Engine as ScalarEngine>::Fr::one();
// Sort the bases into buckets
for (&exp, density) in exponents.iter().zip(density_map.as_ref().iter()) {
if density {
if exp == zero {
if exp.is_zero() {
bases.skip(1)?;
} else if exp == one {
if handle_trivial {
@ -196,9 +195,8 @@ where
bases.skip(1)?;
}
} else {
let mut exp = exp;
exp.shr(skip);
let exp = exp.as_ref()[0] % (1 << c);
let exp = exp >> skip;
let exp = exp & ((1 << c) - 1);
if exp != 0 {
(&mut buckets[(exp - 1) as usize])
@ -261,7 +259,7 @@ pub fn multiexp<Q, D, G, S>(
pool: &Worker,
bases: S,
density_map: D,
exponents: Arc<Vec<<<G::Engine as ScalarEngine>::Fr as PrimeField>::Repr>>,
exponents: Arc<Vec<<G::Engine as ScalarEngine>::Fr>>,
) -> Box<dyn Future<Item = G, Error = SynthesisError>>
where
for<'a> &'a Q: QueryDensity,
@ -290,14 +288,14 @@ where
fn test_with_bls12() {
fn naive_multiexp<G: CurveProjective>(
bases: Arc<Vec<<G as CurveProjective>::Affine>>,
exponents: Arc<Vec<<G::Scalar as PrimeField>::Repr>>,
exponents: Arc<Vec<G::Scalar>>,
) -> G {
assert_eq!(bases.len(), exponents.len());
let mut acc = G::zero();
for (base, exp) in bases.iter().zip(exponents.iter()) {
AddAssign::<&G>::add_assign(&mut acc, &base.mul(*exp));
AddAssign::<&G>::add_assign(&mut acc, &base.mul(exp.into_repr()));
}
acc
@ -311,7 +309,7 @@ fn test_with_bls12() {
let rng = &mut rand::thread_rng();
let v = Arc::new(
(0..SAMPLES)
.map(|_| <Bls12 as ScalarEngine>::Fr::random(rng).into_repr())
.map(|_| <Bls12 as ScalarEngine>::Fr::random(rng))
.collect::<Vec<_>>(),
);
let g = Arc::new(

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,10 @@ extern crate std;
#[cfg(feature = "derive")]
pub use ff_derive::*;
use core::convert::TryFrom;
use core::fmt;
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use core::marker::PhantomData;
use core::ops::{Add, AddAssign, BitAnd, Mul, MulAssign, Neg, Shr, Sub, SubAssign};
use rand_core::RngCore;
#[cfg(feature = "std")]
use std::io::{self, Read, Write};
@ -73,21 +75,36 @@ pub trait Field:
/// Exponentiates this element by a power of the base prime modulus via
/// the Frobenius automorphism.
fn frobenius_map(&mut self, power: usize);
}
pub trait PowVartime<L>: Field
where
L: Copy + PartialEq + PartialOrd + AddAssign,
L: BitAnd<Output = L>,
L: Shr<Output = L>,
L: Sub<Output = L>,
{
const ZERO: L;
const ONE: L;
const LIMB_SIZE: L;
/// Exponentiates `self` by `exp`, where `exp` is a little-endian order
/// integer exponent.
///
/// **This operation is variable time with respect to the exponent.** If the
/// exponent is fixed, this operation is effectively constant time.
fn pow_vartime<S: AsRef<[u64]>>(&self, exp: S) -> Self {
fn pow_vartime<S: AsRef<[L]>>(&self, exp: S) -> Self {
let mut res = Self::one();
for e in exp.as_ref().iter().rev() {
for i in (0..64).rev() {
let mut i = Self::ZERO;
while i < Self::LIMB_SIZE {
res = res.square();
if ((*e >> i) & 1) == 1 {
if ((*e >> (Self::LIMB_SIZE - Self::ONE - i)) & Self::ONE) == Self::ONE {
res.mul_assign(self);
}
i += Self::ONE;
}
}
@ -95,6 +112,18 @@ pub trait Field:
}
}
impl<T: Field> PowVartime<u8> for T {
const ZERO: u8 = 0;
const ONE: u8 = 1;
const LIMB_SIZE: u8 = 8;
}
impl<T: Field> PowVartime<u64> for T {
const ZERO: u64 = 0;
const ONE: u64 = 1;
const LIMB_SIZE: u64 = 64;
}
/// This trait represents an element of a field that has a square root operation described for it.
pub trait SqrtField: Field {
/// Returns the square root of the field element, if it is
@ -102,137 +131,13 @@ pub trait SqrtField: Field {
fn sqrt(&self) -> CtOption<Self>;
}
/// This trait represents a wrapper around a biginteger which can encode any element of a particular
/// prime field. It is a smart wrapper around a sequence of `u64` limbs, least-significant digit
/// first.
pub trait PrimeFieldRepr:
Sized
+ Copy
+ Clone
+ Eq
+ Ord
+ Send
+ Sync
+ Default
+ fmt::Debug
+ fmt::Display
+ 'static
+ AsRef<[u64]>
+ AsMut<[u64]>
+ From<u64>
{
/// Subtract another represetation from this one.
fn sub_noborrow(&mut self, other: &Self);
/// Add another representation to this one.
fn add_nocarry(&mut self, other: &Self);
/// Compute the number of bits needed to encode this number. Always a
/// multiple of 64.
fn num_bits(&self) -> u32;
/// Returns true iff this number is zero.
fn is_zero(&self) -> bool;
/// Returns true iff this number is odd.
fn is_odd(&self) -> bool;
/// Returns true iff this number is even.
fn is_even(&self) -> bool;
/// Performs a rightwise bitshift of this number, effectively dividing
/// it by 2.
fn div2(&mut self);
/// Performs a rightwise bitshift of this number by some amount.
fn shr(&mut self, amt: u32);
/// Performs a leftwise bitshift of this number, effectively multiplying
/// it by 2. Overflow is ignored.
fn mul2(&mut self);
/// Performs a leftwise bitshift of this number by some amount.
fn shl(&mut self, amt: u32);
/// Writes this `PrimeFieldRepr` as a big endian integer.
#[cfg(feature = "std")]
fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> {
use byteorder::{BigEndian, WriteBytesExt};
for digit in self.as_ref().iter().rev() {
writer.write_u64::<BigEndian>(*digit)?;
}
Ok(())
}
/// Reads a big endian integer into this representation.
#[cfg(feature = "std")]
fn read_be<R: Read>(&mut self, mut reader: R) -> io::Result<()> {
use byteorder::{BigEndian, ReadBytesExt};
for digit in self.as_mut().iter_mut().rev() {
*digit = reader.read_u64::<BigEndian>()?;
}
Ok(())
}
/// Writes this `PrimeFieldRepr` as a little endian integer.
#[cfg(feature = "std")]
fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
use byteorder::{LittleEndian, WriteBytesExt};
for digit in self.as_ref().iter() {
writer.write_u64::<LittleEndian>(*digit)?;
}
Ok(())
}
/// Reads a little endian integer into this representation.
#[cfg(feature = "std")]
fn read_le<R: Read>(&mut self, mut reader: R) -> io::Result<()> {
use byteorder::{LittleEndian, ReadBytesExt};
for digit in self.as_mut().iter_mut() {
*digit = reader.read_u64::<LittleEndian>()?;
}
Ok(())
}
}
/// An error that may occur when trying to interpret a `PrimeFieldRepr` as a
/// `PrimeField` element.
#[derive(Debug)]
pub enum PrimeFieldDecodingError {
/// The encoded value is not in the field
NotInField,
}
#[cfg(feature = "std")]
impl std::error::Error for PrimeFieldDecodingError {
fn description(&self) -> &str {
match *self {
PrimeFieldDecodingError::NotInField => "not an element of the field",
}
}
}
impl fmt::Display for PrimeFieldDecodingError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match *self {
PrimeFieldDecodingError::NotInField => write!(f, "not an element of the field"),
}
}
}
/// This represents an element of a prime field.
pub trait PrimeField: Field {
/// The prime field can be converted back and forth into this biginteger
pub trait PrimeField:
Field + Ord + From<u64> + BitAnd<u64, Output = u64> + Shr<u32, Output = Self>
{
/// The prime field can be converted back and forth into this binary
/// representation.
type Repr: PrimeFieldRepr + From<Self>;
type Repr: Default + AsRef<[u8]> + AsMut<[u8]> + From<Self> + for<'r> From<&'r Self>;
/// Interpret a string of numbers as a (congruent) prime field element.
/// Does not accept unnecessary leading zeroes or a blank string.
@ -247,7 +152,7 @@ pub trait PrimeField: Field {
let mut res = Self::zero();
let ten = Self::from_repr(Self::Repr::from(10)).unwrap();
let ten = Self::from(10);
let mut first_digit = true;
@ -263,7 +168,7 @@ pub trait PrimeField: Field {
}
res.mul_assign(&ten);
res.add_assign(&Self::from_repr(Self::Repr::from(u64::from(c))).unwrap());
res.add_assign(&Self::from(u64::from(c)));
}
None => {
return None;
@ -274,13 +179,31 @@ pub trait PrimeField: Field {
Some(res)
}
/// Convert this prime field element into a biginteger representation.
fn from_repr(_: Self::Repr) -> Result<Self, PrimeFieldDecodingError>;
/// Attempts to convert a byte representation of a field element into an element of
/// this prime field, failing if the input is not canonical (is not smaller than the
/// field's modulus).
///
/// The byte representation is interpreted with the same endianness as is returned
/// by [`PrimeField::into_repr`].
fn from_repr(_: Self::Repr) -> Option<Self>;
/// Convert a biginteger representation into a prime field element, if
/// the number is an element of the field.
/// Converts an element of the prime field into the standard byte representation for
/// this field.
///
/// Endianness of the byte representation is defined by the field implementation.
/// Callers should assume that it is the standard endianness used to represent encoded
/// elements of this particular field.
fn into_repr(&self) -> Self::Repr;
/// Returns true iff this element is odd.
fn is_odd(&self) -> bool;
/// Returns true iff this element is even.
#[inline(always)]
fn is_even(&self) -> bool {
!self.is_odd()
}
/// Returns the field characteristic; the modulus.
fn char() -> Self::Repr;
@ -311,20 +234,25 @@ pub trait ScalarEngine: Sized + 'static + Clone {
}
#[derive(Debug)]
pub struct BitIterator<E> {
pub struct BitIterator<T, E: AsRef<[T]>> {
t: E,
n: usize,
_limb: PhantomData<T>,
}
impl<E: AsRef<[u64]>> BitIterator<E> {
impl<E: AsRef<[u64]>> BitIterator<u64, E> {
pub fn new(t: E) -> Self {
let n = t.as_ref().len() * 64;
BitIterator { t, n }
BitIterator {
t,
n,
_limb: PhantomData::default(),
}
}
}
impl<E: AsRef<[u64]>> Iterator for BitIterator<E> {
impl<E: AsRef<[u64]>> Iterator for BitIterator<u64, E> {
type Item = bool;
fn next(&mut self) -> Option<bool> {
@ -340,9 +268,37 @@ impl<E: AsRef<[u64]>> Iterator for BitIterator<E> {
}
}
impl<E: AsRef<[u8]>> BitIterator<u8, E> {
pub fn new(t: E) -> Self {
let n = t.as_ref().len() * 8;
BitIterator {
t,
n,
_limb: PhantomData::default(),
}
}
}
impl<E: AsRef<[u8]>> Iterator for BitIterator<u8, E> {
type Item = bool;
fn next(&mut self) -> Option<bool> {
if self.n == 0 {
None
} else {
self.n -= 1;
let part = self.n / 8;
let bit = self.n - (8 * part);
Some(self.t.as_ref()[part] & (1 << bit) > 0)
}
}
}
#[test]
fn test_bit_iterator() {
let mut a = BitIterator::new([0xa953_d79b_83f6_ab59, 0x6dea_2059_e200_bd39]);
let mut a = BitIterator::<u64, _>::new([0xa953_d79b_83f6_ab59, 0x6dea_2059_e200_bd39]);
let expected = "01101101111010100010000001011001111000100000000010111101001110011010100101010011110101111001101110000011111101101010101101011001";
for e in expected.chars() {
@ -353,7 +309,7 @@ fn test_bit_iterator() {
let expected = "1010010101111110101010000101101011101000011101110101001000011001100100100011011010001011011011010001011011101100110100111011010010110001000011110100110001100110011101101000101100011100100100100100001010011101010111110011101011000011101000111011011101011001";
let mut a = BitIterator::new([
let mut a = BitIterator::<u64, _>::new([
0x429d_5f3a_c3a3_b759,
0xb10f_4c66_768b_1c92,
0x9236_8b6d_16ec_d3b4,

View File

@ -15,6 +15,7 @@ repository = "https://github.com/ebfull/group"
edition = "2018"
[dependencies]
byteorder = { version = "1", default-features = false }
ff = { version = "0.6", path = "../ff" }
rand = "0.7"
rand_xorshift = "0.2"

View File

@ -1,7 +1,7 @@
// Catch documentation errors caused by code changes.
#![deny(intra_doc_link_resolution_failure)]
use ff::{PrimeField, PrimeFieldDecodingError, ScalarEngine, SqrtField};
use ff::{PrimeField, ScalarEngine, SqrtField};
use rand::RngCore;
use std::error::Error;
use std::fmt;
@ -82,7 +82,7 @@ pub trait CurveProjective:
/// Recommends a wNAF window table size given a scalar. Always returns a number
/// between 2 and 22, inclusive.
fn recommended_wnaf_for_scalar(scalar: <Self::Scalar as PrimeField>::Repr) -> usize;
fn recommended_wnaf_for_scalar(scalar: &Self::Scalar) -> usize;
/// Recommends a wNAF window size given the number of scalars you intend to multiply
/// a base by. Always returns a number between 2 and 22, inclusive.
@ -178,7 +178,7 @@ pub enum GroupDecodingError {
/// The element is not part of the r-order subgroup.
NotInSubgroup,
/// One of the coordinates could not be decoded
CoordinateDecodingError(&'static str, PrimeFieldDecodingError),
CoordinateDecodingError(&'static str),
/// The compression mode of the encoded element was not as expected
UnexpectedCompressionMode,
/// The encoding contained bits that should not have been set
@ -202,8 +202,8 @@ impl Error for GroupDecodingError {
impl fmt::Display for GroupDecodingError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match *self {
GroupDecodingError::CoordinateDecodingError(description, ref err) => {
write!(f, "{} decoding error: {}", description, err)
GroupDecodingError::CoordinateDecodingError(description) => {
write!(f, "{} decoding error", description)
}
_ => write!(f, "{}", self.description()),
}

View File

@ -85,12 +85,12 @@ fn random_wnaf_tests<G: CurveProjective>() {
for w in 2..14 {
for _ in 0..100 {
let g = G::random(&mut rng);
let s = G::Scalar::random(&mut rng).into_repr();
let s = G::Scalar::random(&mut rng);
let mut g1 = g;
g1.mul_assign(s);
wnaf_table(&mut table, g, w);
wnaf_form(&mut wnaf, s, w);
wnaf_form(&mut wnaf, s.into_repr(), w);
let g2 = wnaf_exp(&table, &wnaf);
assert_eq!(g1, g2);
@ -103,17 +103,17 @@ fn random_wnaf_tests<G: CurveProjective>() {
for _ in 0..100 {
let g = G::random(&mut rng);
let s = G::Scalar::random(&mut rng).into_repr();
let s = G::Scalar::random(&mut rng);
let mut g1 = g;
g1.mul_assign(s);
let g2 = {
let mut wnaf = Wnaf::new();
wnaf.base(g, 1).scalar(s)
wnaf.base(g, 1).scalar(&s)
};
let g3 = {
let mut wnaf = Wnaf::new();
wnaf.scalar(s).base(g)
wnaf.scalar(&s).base(g)
};
let g4 = {
let mut wnaf = Wnaf::new();
@ -121,11 +121,11 @@ fn random_wnaf_tests<G: CurveProjective>() {
only_compiles_if_send(&shared);
shared.scalar(s)
shared.scalar(&s)
};
let g5 = {
let mut wnaf = Wnaf::new();
let mut shared = wnaf.scalar(s).shared();
let mut shared = wnaf.scalar(&s).shared();
only_compiles_if_send(&shared);
@ -137,40 +137,40 @@ fn random_wnaf_tests<G: CurveProjective>() {
{
// Populate the vectors.
wnaf.base(G::random(&mut rng), 1)
.scalar(G::Scalar::random(&mut rng).into_repr());
.scalar(&G::Scalar::random(&mut rng));
}
wnaf.base(g, 1).scalar(s)
wnaf.base(g, 1).scalar(&s)
};
let g7 = {
let mut wnaf = Wnaf::new();
{
// Populate the vectors.
wnaf.base(G::random(&mut rng), 1)
.scalar(G::Scalar::random(&mut rng).into_repr());
.scalar(&G::Scalar::random(&mut rng));
}
wnaf.scalar(s).base(g)
wnaf.scalar(&s).base(g)
};
let g8 = {
let mut wnaf = Wnaf::new();
{
// Populate the vectors.
wnaf.base(G::random(&mut rng), 1)
.scalar(G::Scalar::random(&mut rng).into_repr());
.scalar(&G::Scalar::random(&mut rng));
}
let mut shared = wnaf.base(g, 1).shared();
only_compiles_if_send(&shared);
shared.scalar(s)
shared.scalar(&s)
};
let g9 = {
let mut wnaf = Wnaf::new();
{
// Populate the vectors.
wnaf.base(G::random(&mut rng), 1)
.scalar(G::Scalar::random(&mut rng).into_repr());
.scalar(&G::Scalar::random(&mut rng));
}
let mut shared = wnaf.scalar(s).shared();
let mut shared = wnaf.scalar(&s).shared();
only_compiles_if_send(&shared);

View File

@ -1,4 +1,6 @@
use ff::{PrimeField, PrimeFieldRepr};
use byteorder::{ByteOrder, LittleEndian};
use ff::PrimeField;
use std::iter;
use super::CurveProjective;
@ -16,31 +18,60 @@ pub(crate) fn wnaf_table<G: CurveProjective>(table: &mut Vec<G>, mut base: G, wi
}
}
/// Replaces the contents of `wnaf` with the w-NAF representation of a scalar.
pub(crate) fn wnaf_form<S: PrimeFieldRepr>(wnaf: &mut Vec<i64>, mut c: S, window: usize) {
/// Replaces the contents of `wnaf` with the w-NAF representation of a little-endian
/// scalar.
pub(crate) fn wnaf_form<S: AsRef<[u8]>>(wnaf: &mut Vec<i64>, c: S, window: usize) {
// Required by the NAF definition
debug_assert!(window >= 2);
// Required so that the NAF digits fit in i64
debug_assert!(window <= 64);
wnaf.truncate(0);
while !c.is_zero() {
let mut u;
if c.is_odd() {
u = (c.as_ref()[0] % (1 << (window + 1))) as i64;
let bit_len = c.as_ref().len() * 8;
let u64_len = (bit_len + 1) / 64;
if u > (1 << window) {
u -= 1 << (window + 1);
}
let mut c_u64 = vec![0u64; u64_len + 1];
LittleEndian::read_u64_into(c.as_ref(), &mut c_u64[0..u64_len]);
if u > 0 {
c.sub_noborrow(&S::from(u as u64));
let width = 1u64 << window;
let window_mask = width - 1;
let mut pos = 0;
let mut carry = 0;
while pos < bit_len {
// Construct a buffer of bits of the scalar, starting at bit `pos`
let u64_idx = pos / 64;
let bit_idx = pos % 64;
let bit_buf = if bit_idx + window < 64 {
// This window's bits are contained in a single u64
c_u64[u64_idx] >> bit_idx
} else {
c.add_nocarry(&S::from((-u) as u64));
}
// Combine the current u64's bits with the bits from the next u64
(c_u64[u64_idx] >> bit_idx) | (c_u64[u64_idx + 1] << (64 - bit_idx))
};
// Add the carry into the current window
let window_val = carry + (bit_buf & window_mask);
if window_val & 1 == 0 {
// If the window value is even, preserve the carry and emit 0.
// Why is the carry preserved?
// If carry == 0 and window_val & 1 == 0, then the next carry should be 0
// If carry == 1 and window_val & 1 == 0, then bit_buf & 1 == 1 so the next carry should be 1
wnaf.push(0);
pos += 1;
} else {
u = 0;
wnaf.push(if window_val < width / 2 {
carry = 0;
window_val as i64
} else {
carry = 1;
(window_val as i64).wrapping_sub(width as i64)
});
wnaf.extend(iter::repeat(0).take(window - 1));
pos += window;
}
wnaf.push(u);
c.div2();
}
}
@ -112,13 +143,13 @@ impl<G: CurveProjective> Wnaf<(), Vec<G>, Vec<i64>> {
/// exponentiations with `.base(..)`.
pub fn scalar(
&mut self,
scalar: <<G as CurveProjective>::Scalar as PrimeField>::Repr,
scalar: &<G as CurveProjective>::Scalar,
) -> Wnaf<usize, &mut Vec<G>, &[i64]> {
// Compute the appropriate window size for the scalar.
let window_size = G::recommended_wnaf_for_scalar(scalar);
let window_size = G::recommended_wnaf_for_scalar(&scalar);
// Compute the wNAF form of the scalar.
wnaf_form(&mut self.scalar, scalar, window_size);
wnaf_form(&mut self.scalar, scalar.into_repr(), window_size);
// Return a Wnaf object that mutably borrows the base storage location, but
// immutably borrows the computed wNAF form scalar location.
@ -168,14 +199,11 @@ impl<B, S: AsRef<[i64]>> Wnaf<usize, B, S> {
impl<B, S: AsMut<Vec<i64>>> Wnaf<usize, B, S> {
/// Performs exponentiation given a scalar.
pub fn scalar<G: CurveProjective>(
&mut self,
scalar: <<G as CurveProjective>::Scalar as PrimeField>::Repr,
) -> G
pub fn scalar<G: CurveProjective>(&mut self, scalar: &<G as CurveProjective>::Scalar) -> G
where
B: AsRef<[G]>,
{
wnaf_form(self.scalar.as_mut(), scalar, self.window_size);
wnaf_form(self.scalar.as_mut(), scalar.into_repr(), self.window_size);
wnaf_exp(self.base.as_ref(), self.scalar.as_mut())
}
}

View File

@ -3,140 +3,9 @@ use rand_core::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
use ff::{Field, PrimeField, SqrtField};
use pairing::bls12_381::*;
fn bench_fq_repr_add_nocarry(c: &mut Criterion) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let v: Vec<(FqRepr, FqRepr)> = (0..SAMPLES)
.map(|_| {
let mut tmp1 = Fq::random(&mut rng).into_repr();
let mut tmp2 = Fq::random(&mut rng).into_repr();
// Shave a few bits off to avoid overflow.
for _ in 0..3 {
tmp1.div2();
tmp2.div2();
}
(tmp1, tmp2)
})
.collect();
let mut count = 0;
c.bench_function("FqRepr::add_nocarry", |b| {
b.iter(|| {
let mut tmp = v[count].0;
tmp.add_nocarry(&v[count].1);
count = (count + 1) % SAMPLES;
tmp
})
});
}
fn bench_fq_repr_sub_noborrow(c: &mut Criterion) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let v: Vec<(FqRepr, FqRepr)> = (0..SAMPLES)
.map(|_| {
let tmp1 = Fq::random(&mut rng).into_repr();
let mut tmp2 = tmp1;
// Ensure tmp2 is smaller than tmp1.
for _ in 0..10 {
tmp2.div2();
}
(tmp1, tmp2)
})
.collect();
let mut count = 0;
c.bench_function("FqRepr::sub_noborrow", |b| {
b.iter(|| {
let mut tmp = v[count].0;
tmp.sub_noborrow(&v[count].1);
count = (count + 1) % SAMPLES;
tmp
})
});
}
fn bench_fq_repr_num_bits(c: &mut Criterion) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let v: Vec<FqRepr> = (0..SAMPLES)
.map(|_| Fq::random(&mut rng).into_repr())
.collect();
let mut count = 0;
c.bench_function("FqRepr::num_bits", |b| {
b.iter(|| {
let tmp = v[count].num_bits();
count = (count + 1) % SAMPLES;
tmp
})
});
}
fn bench_fq_repr_mul2(c: &mut Criterion) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let v: Vec<FqRepr> = (0..SAMPLES)
.map(|_| Fq::random(&mut rng).into_repr())
.collect();
let mut count = 0;
c.bench_function("FqRepr::mul2", |b| {
b.iter(|| {
let mut tmp = v[count];
tmp.mul2();
count = (count + 1) % SAMPLES;
tmp
})
});
}
fn bench_fq_repr_div2(c: &mut Criterion) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let v: Vec<FqRepr> = (0..SAMPLES)
.map(|_| Fq::random(&mut rng).into_repr())
.collect();
let mut count = 0;
c.bench_function("FqRepr::div2", |b| {
b.iter(|| {
let mut tmp = v[count];
tmp.div2();
count = (count + 1) % SAMPLES;
tmp
})
});
}
fn bench_fq_add_assign(c: &mut Criterion) {
const SAMPLES: usize = 1000;
@ -328,11 +197,6 @@ fn bench_fq_from_repr(c: &mut Criterion) {
criterion_group!(
benches,
bench_fq_repr_add_nocarry,
bench_fq_repr_sub_noborrow,
bench_fq_repr_num_bits,
bench_fq_repr_mul2,
bench_fq_repr_div2,
bench_fq_add_assign,
bench_fq_sub_assign,
bench_fq_mul_assign,

View File

@ -3,140 +3,9 @@ use rand_core::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
use ff::{Field, PrimeField, SqrtField};
use pairing::bls12_381::*;
fn bench_fr_repr_add_nocarry(c: &mut Criterion) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let v: Vec<(FrRepr, FrRepr)> = (0..SAMPLES)
.map(|_| {
let mut tmp1 = Fr::random(&mut rng).into_repr();
let mut tmp2 = Fr::random(&mut rng).into_repr();
// Shave a few bits off to avoid overflow.
for _ in 0..3 {
tmp1.div2();
tmp2.div2();
}
(tmp1, tmp2)
})
.collect();
let mut count = 0;
c.bench_function("FrRepr::add_nocarry", |b| {
b.iter(|| {
let mut tmp = v[count].0;
tmp.add_nocarry(&v[count].1);
count = (count + 1) % SAMPLES;
tmp
})
});
}
fn bench_fr_repr_sub_noborrow(c: &mut Criterion) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let v: Vec<(FrRepr, FrRepr)> = (0..SAMPLES)
.map(|_| {
let tmp1 = Fr::random(&mut rng).into_repr();
let mut tmp2 = tmp1;
// Ensure tmp2 is smaller than tmp1.
for _ in 0..10 {
tmp2.div2();
}
(tmp1, tmp2)
})
.collect();
let mut count = 0;
c.bench_function("FrRepr::sub_noborrow", |b| {
b.iter(|| {
let mut tmp = v[count].0;
tmp.sub_noborrow(&v[count].1);
count = (count + 1) % SAMPLES;
tmp
})
});
}
fn bench_fr_repr_num_bits(c: &mut Criterion) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let v: Vec<FrRepr> = (0..SAMPLES)
.map(|_| Fr::random(&mut rng).into_repr())
.collect();
let mut count = 0;
c.bench_function("FrRepr::num_bits", |b| {
b.iter(|| {
let tmp = v[count].num_bits();
count = (count + 1) % SAMPLES;
tmp
})
});
}
fn bench_fr_repr_mul2(c: &mut Criterion) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let v: Vec<FrRepr> = (0..SAMPLES)
.map(|_| Fr::random(&mut rng).into_repr())
.collect();
let mut count = 0;
c.bench_function("FrRepr::mul2", |b| {
b.iter(|| {
let mut tmp = v[count];
tmp.mul2();
count = (count + 1) % SAMPLES;
tmp
})
});
}
fn bench_fr_repr_div2(c: &mut Criterion) {
const SAMPLES: usize = 1000;
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let v: Vec<FrRepr> = (0..SAMPLES)
.map(|_| Fr::random(&mut rng).into_repr())
.collect();
let mut count = 0;
c.bench_function("FrRepr::div2", |b| {
b.iter(|| {
let mut tmp = v[count];
tmp.div2();
count = (count + 1) % SAMPLES;
tmp
})
});
}
fn bench_fr_add_assign(c: &mut Criterion) {
const SAMPLES: usize = 1000;
@ -328,11 +197,6 @@ fn bench_fr_from_repr(c: &mut Criterion) {
criterion_group!(
benches,
bench_fr_repr_add_nocarry,
bench_fr_repr_sub_noborrow,
bench_fr_repr_num_bits,
bench_fr_repr_mul2,
bench_fr_repr_div2,
bench_fr_add_assign,
bench_fr_sub_assign,
bench_fr_mul_assign,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
use super::fq::{Fq, FROBENIUS_COEFF_FQ2_C1, NEGATIVE_ONE};
use ff::{Field, SqrtField};
use ff::{Field, PowVartime, SqrtField};
use rand_core::RngCore;
use std::cmp::Ordering;
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
@ -254,7 +254,7 @@ impl SqrtField for Fq2 {
} else {
// a1 = self^((q - 3) / 4)
let mut a1 = self.pow_vartime([
0xee7fbfffffffeaaa,
0xee7fbfffffffeaaau64,
0x7aaffffac54ffff,
0xd9cc34a83dac3d89,
0xd91dd2e13ce144af,
@ -286,7 +286,7 @@ impl SqrtField for Fq2 {
alpha.add_assign(&Fq2::one());
// alpha = alpha^((q - 1) / 2)
alpha = alpha.pow_vartime([
0xdcff7fffffffd555,
0xdcff7fffffffd555u64,
0xf55ffff58a9ffff,
0xb39869507b587b12,
0xb23ba5c279c2895f,
@ -302,6 +302,11 @@ impl SqrtField for Fq2 {
}
}
#[cfg(test)]
use super::fq::FqRepr;
#[cfg(test)]
use ff::PrimeField;
#[test]
fn test_fq2_ordering() {
let mut a = Fq2 {
@ -353,9 +358,6 @@ fn test_fq2_basics() {
#[test]
fn test_fq2_squaring() {
use super::fq::FqRepr;
use ff::PrimeField;
let a = Fq2 {
c0: Fq::one(),
c1: Fq::one(),
@ -364,7 +366,7 @@ fn test_fq2_squaring() {
a.square(),
Fq2 {
c0: Fq::zero(),
c1: Fq::from_repr(FqRepr::from(2)).unwrap(),
c1: Fq::from(2),
}
); // 2u
@ -381,21 +383,17 @@ fn test_fq2_squaring() {
let a = Fq2 {
c0: Fq::from_repr(FqRepr([
0x9c2c6309bbf8b598,
0x4eef5c946536f602,
0x90e34aab6fb6a6bd,
0xf7f295a94e58ae7c,
0x41b76dcc1c3fbe5e,
0x7080c5fa1d8e042,
0x07, 0x08, 0x0c, 0x5f, 0xa1, 0xd8, 0xe0, 0x42, 0x41, 0xb7, 0x6d, 0xcc, 0x1c, 0x3f,
0xbe, 0x5e, 0xf7, 0xf2, 0x95, 0xa9, 0x4e, 0x58, 0xae, 0x7c, 0x90, 0xe3, 0x4a, 0xab,
0x6f, 0xb6, 0xa6, 0xbd, 0x4e, 0xef, 0x5c, 0x94, 0x65, 0x36, 0xf6, 0x02, 0x9c, 0x2c,
0x63, 0x09, 0xbb, 0xf8, 0xb5, 0x98,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x38f473b3c870a4ab,
0x6ad3291177c8c7e5,
0xdac5a4c911a4353e,
0xbfb99020604137a0,
0xfc58a7b7be815407,
0x10d1615e75250a21,
0x10, 0xd1, 0x61, 0x5e, 0x75, 0x25, 0x0a, 0x21, 0xfc, 0x58, 0xa7, 0xb7, 0xbe, 0x81,
0x54, 0x07, 0xbf, 0xb9, 0x90, 0x20, 0x60, 0x41, 0x37, 0xa0, 0xda, 0xc5, 0xa4, 0xc9,
0x11, 0xa4, 0x35, 0x3e, 0x6a, 0xd3, 0x29, 0x11, 0x77, 0xc8, 0xc7, 0xe5, 0x38, 0xf4,
0x73, 0xb3, 0xc8, 0x70, 0xa4, 0xab,
]))
.unwrap(),
};
@ -403,21 +401,17 @@ fn test_fq2_squaring() {
a.square(),
Fq2 {
c0: Fq::from_repr(FqRepr([
0xf262c28c538bcf68,
0xb9f2a66eae1073ba,
0xdc46ab8fad67ae0,
0xcb674157618da176,
0x4cf17b5893c3d327,
0x7eac81369c43361
0x07, 0xea, 0xc8, 0x13, 0x69, 0xc4, 0x33, 0x61, 0x4c, 0xf1, 0x7b, 0x58, 0x93, 0xc3,
0xd3, 0x27, 0xcb, 0x67, 0x41, 0x57, 0x61, 0x8d, 0xa1, 0x76, 0x0d, 0xc4, 0x6a, 0xb8,
0xfa, 0xd6, 0x7a, 0xe0, 0xb9, 0xf2, 0xa6, 0x6e, 0xae, 0x10, 0x73, 0xba, 0xf2, 0x62,
0xc2, 0x8c, 0x53, 0x8b, 0xcf, 0x68,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0xc1579cf58e980cf8,
0xa23eb7e12dd54d98,
0xe75138bce4cec7aa,
0x38d0d7275a9689e1,
0x739c983042779a65,
0x1542a61c8a8db994
0x15, 0x42, 0xa6, 0x1c, 0x8a, 0x8d, 0xb9, 0x94, 0x73, 0x9c, 0x98, 0x30, 0x42, 0x77,
0x9a, 0x65, 0x38, 0xd0, 0xd7, 0x27, 0x5a, 0x96, 0x89, 0xe1, 0xe7, 0x51, 0x38, 0xbc,
0xe4, 0xce, 0xc7, 0xaa, 0xa2, 0x3e, 0xb7, 0xe1, 0x2d, 0xd5, 0x4d, 0x98, 0xc1, 0x57,
0x9c, 0xf5, 0x8e, 0x98, 0x0c, 0xf8,
]))
.unwrap(),
}
@ -431,41 +425,33 @@ fn test_fq2_mul() {
let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([
0x85c9f989e1461f03,
0xa2e33c333449a1d6,
0x41e461154a7354a3,
0x9ee53e7e84d7532e,
0x1c202d8ed97afb45,
0x51d3f9253e2516f,
0x05, 0x1d, 0x3f, 0x92, 0x53, 0xe2, 0x51, 0x6f, 0x1c, 0x20, 0x2d, 0x8e, 0xd9, 0x7a,
0xfb, 0x45, 0x9e, 0xe5, 0x3e, 0x7e, 0x84, 0xd7, 0x53, 0x2e, 0x41, 0xe4, 0x61, 0x15,
0x4a, 0x73, 0x54, 0xa3, 0xa2, 0xe3, 0x3c, 0x33, 0x34, 0x49, 0xa1, 0xd6, 0x85, 0xc9,
0xf9, 0x89, 0xe1, 0x46, 0x1f, 0x03,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0xa7348a8b511aedcf,
0x143c215d8176b319,
0x4cc48081c09b8903,
0x9533e4a9a5158be,
0x7a5e1ecb676d65f9,
0x180c3ee46656b008,
0x18, 0x0c, 0x3e, 0xe4, 0x66, 0x56, 0xb0, 0x08, 0x7a, 0x5e, 0x1e, 0xcb, 0x67, 0x6d,
0x65, 0xf9, 0x09, 0x53, 0x3e, 0x4a, 0x9a, 0x51, 0x58, 0xbe, 0x4c, 0xc4, 0x80, 0x81,
0xc0, 0x9b, 0x89, 0x03, 0x14, 0x3c, 0x21, 0x5d, 0x81, 0x76, 0xb3, 0x19, 0xa7, 0x34,
0x8a, 0x8b, 0x51, 0x1a, 0xed, 0xcf,
]))
.unwrap(),
};
a.mul_assign(&Fq2 {
c0: Fq::from_repr(FqRepr([
0xe21f9169805f537e,
0xfc87e62e179c285d,
0x27ece175be07a531,
0xcd460f9f0c23e430,
0x6c9110292bfa409,
0x2c93a72eb8af83e,
0x02, 0xc9, 0x3a, 0x72, 0xeb, 0x8a, 0xf8, 0x3e, 0x06, 0xc9, 0x11, 0x02, 0x92, 0xbf,
0xa4, 0x09, 0xcd, 0x46, 0x0f, 0x9f, 0x0c, 0x23, 0xe4, 0x30, 0x27, 0xec, 0xe1, 0x75,
0xbe, 0x07, 0xa5, 0x31, 0xfc, 0x87, 0xe6, 0x2e, 0x17, 0x9c, 0x28, 0x5d, 0xe2, 0x1f,
0x91, 0x69, 0x80, 0x5f, 0x53, 0x7e,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x4b1c3f936d8992d4,
0x1d2a72916dba4c8a,
0x8871c508658d1e5f,
0x57a06d3135a752ae,
0x634cd3c6c565096d,
0x19e17334d4e93558,
0x19, 0xe1, 0x73, 0x34, 0xd4, 0xe9, 0x35, 0x58, 0x63, 0x4c, 0xd3, 0xc6, 0xc5, 0x65,
0x09, 0x6d, 0x57, 0xa0, 0x6d, 0x31, 0x35, 0xa7, 0x52, 0xae, 0x88, 0x71, 0xc5, 0x08,
0x65, 0x8d, 0x1e, 0x5f, 0x1d, 0x2a, 0x72, 0x91, 0x6d, 0xba, 0x4c, 0x8a, 0x4b, 0x1c,
0x3f, 0x93, 0x6d, 0x89, 0x92, 0xd4,
]))
.unwrap(),
});
@ -473,21 +459,17 @@ fn test_fq2_mul() {
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x95b5127e6360c7e4,
0xde29c31a19a6937e,
0xf61a96dacf5a39bc,
0x5511fe4d84ee5f78,
0x5310a202d92f9963,
0x1751afbe166e5399
0x17, 0x51, 0xaf, 0xbe, 0x16, 0x6e, 0x53, 0x99, 0x53, 0x10, 0xa2, 0x02, 0xd9, 0x2f,
0x99, 0x63, 0x55, 0x11, 0xfe, 0x4d, 0x84, 0xee, 0x5f, 0x78, 0xf6, 0x1a, 0x96, 0xda,
0xcf, 0x5a, 0x39, 0xbc, 0xde, 0x29, 0xc3, 0x1a, 0x19, 0xa6, 0x93, 0x7e, 0x95, 0xb5,
0x12, 0x7e, 0x63, 0x60, 0xc7, 0xe4,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x84af0e1bd630117a,
0x6c63cd4da2c2aa7,
0x5ba6e5430e883d40,
0xc975106579c275ee,
0x33a9ac82ce4c5083,
0x1ef1a36c201589d
0x01, 0xef, 0x1a, 0x36, 0xc2, 0x01, 0x58, 0x9d, 0x33, 0xa9, 0xac, 0x82, 0xce, 0x4c,
0x50, 0x83, 0xc9, 0x75, 0x10, 0x65, 0x79, 0xc2, 0x75, 0xee, 0x5b, 0xa6, 0xe5, 0x43,
0x0e, 0x88, 0x3d, 0x40, 0x06, 0xc6, 0x3c, 0xd4, 0xda, 0x2c, 0x2a, 0xa7, 0x84, 0xaf,
0x0e, 0x1b, 0xd6, 0x30, 0x11, 0x7a,
]))
.unwrap(),
}
@ -503,21 +485,17 @@ fn test_fq2_invert() {
let a = Fq2 {
c0: Fq::from_repr(FqRepr([
0x85c9f989e1461f03,
0xa2e33c333449a1d6,
0x41e461154a7354a3,
0x9ee53e7e84d7532e,
0x1c202d8ed97afb45,
0x51d3f9253e2516f,
0x05, 0x1d, 0x3f, 0x92, 0x53, 0xe2, 0x51, 0x6f, 0x1c, 0x20, 0x2d, 0x8e, 0xd9, 0x7a,
0xfb, 0x45, 0x9e, 0xe5, 0x3e, 0x7e, 0x84, 0xd7, 0x53, 0x2e, 0x41, 0xe4, 0x61, 0x15,
0x4a, 0x73, 0x54, 0xa3, 0xa2, 0xe3, 0x3c, 0x33, 0x34, 0x49, 0xa1, 0xd6, 0x85, 0xc9,
0xf9, 0x89, 0xe1, 0x46, 0x1f, 0x03,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0xa7348a8b511aedcf,
0x143c215d8176b319,
0x4cc48081c09b8903,
0x9533e4a9a5158be,
0x7a5e1ecb676d65f9,
0x180c3ee46656b008,
0x18, 0x0c, 0x3e, 0xe4, 0x66, 0x56, 0xb0, 0x08, 0x7a, 0x5e, 0x1e, 0xcb, 0x67, 0x6d,
0x65, 0xf9, 0x09, 0x53, 0x3e, 0x4a, 0x9a, 0x51, 0x58, 0xbe, 0x4c, 0xc4, 0x80, 0x81,
0xc0, 0x9b, 0x89, 0x03, 0x14, 0x3c, 0x21, 0x5d, 0x81, 0x76, 0xb3, 0x19, 0xa7, 0x34,
0x8a, 0x8b, 0x51, 0x1a, 0xed, 0xcf,
]))
.unwrap(),
};
@ -526,21 +504,17 @@ fn test_fq2_invert() {
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x70300f9bcb9e594,
0xe5ecda5fdafddbb2,
0x64bef617d2915a8f,
0xdfba703293941c30,
0xa6c3d8f9586f2636,
0x1351ef01941b70c4
0x13, 0x51, 0xef, 0x01, 0x94, 0x1b, 0x70, 0xc4, 0xa6, 0xc3, 0xd8, 0xf9, 0x58, 0x6f,
0x26, 0x36, 0xdf, 0xba, 0x70, 0x32, 0x93, 0x94, 0x1c, 0x30, 0x64, 0xbe, 0xf6, 0x17,
0xd2, 0x91, 0x5a, 0x8f, 0xe5, 0xec, 0xda, 0x5f, 0xda, 0xfd, 0xdb, 0xb2, 0x07, 0x03,
0x00, 0xf9, 0xbc, 0xb9, 0xe5, 0x94,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x8c39fd76a8312cb4,
0x15d7b6b95defbff0,
0x947143f89faedee9,
0xcbf651a0f367afb2,
0xdf4e54f0d3ef15a6,
0x103bdf241afb0019
0x10, 0x3b, 0xdf, 0x24, 0x1a, 0xfb, 0x00, 0x19, 0xdf, 0x4e, 0x54, 0xf0, 0xd3, 0xef,
0x15, 0xa6, 0xcb, 0xf6, 0x51, 0xa0, 0xf3, 0x67, 0xaf, 0xb2, 0x94, 0x71, 0x43, 0xf8,
0x9f, 0xae, 0xde, 0xe9, 0x15, 0xd7, 0xb6, 0xb9, 0x5d, 0xef, 0xbf, 0xf0, 0x8c, 0x39,
0xfd, 0x76, 0xa8, 0x31, 0x2c, 0xb4,
]))
.unwrap(),
}
@ -554,41 +528,33 @@ fn test_fq2_addition() {
let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc,
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837,
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
]))
.unwrap(),
};
a.add_assign(&Fq2 {
c0: Fq::from_repr(FqRepr([
0x619a02d78dc70ef2,
0xb93adfc9119e33e8,
0x4bf0b99a9f0dca12,
0x3b88899a42a6318f,
0x986a4a62fa82a49d,
0x13ce433fa26027f5,
0x13, 0xce, 0x43, 0x3f, 0xa2, 0x60, 0x27, 0xf5, 0x98, 0x6a, 0x4a, 0x62, 0xfa, 0x82,
0xa4, 0x9d, 0x3b, 0x88, 0x89, 0x9a, 0x42, 0xa6, 0x31, 0x8f, 0x4b, 0xf0, 0xb9, 0x9a,
0x9f, 0x0d, 0xca, 0x12, 0xb9, 0x3a, 0xdf, 0xc9, 0x11, 0x9e, 0x33, 0xe8, 0x61, 0x9a,
0x02, 0xd7, 0x8d, 0xc7, 0x0e, 0xf2,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x66323bf80b58b9b9,
0xa1379b6facf6e596,
0x402aef1fb797e32f,
0x2236f55246d0d44d,
0x4c8c1800eb104566,
0x11d6e20e986c2085,
0x11, 0xd6, 0xe2, 0x0e, 0x98, 0x6c, 0x20, 0x85, 0x4c, 0x8c, 0x18, 0x00, 0xeb, 0x10,
0x45, 0x66, 0x22, 0x36, 0xf5, 0x52, 0x46, 0xd0, 0xd4, 0x4d, 0x40, 0x2a, 0xef, 0x1f,
0xb7, 0x97, 0xe3, 0x2f, 0xa1, 0x37, 0x9b, 0x6f, 0xac, 0xf6, 0xe5, 0x96, 0x66, 0x32,
0x3b, 0xf8, 0x0b, 0x58, 0xb9, 0xb9,
]))
.unwrap(),
});
@ -596,21 +562,17 @@ fn test_fq2_addition() {
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x8e9a7adaf6eb0eb9,
0xcb207e6b3341eaba,
0xd70b0c7b481d23ff,
0xf4ef57d604b6bca2,
0x65309427b3d5d090,
0x14c715d5553f01d2
0x14, 0xc7, 0x15, 0xd5, 0x55, 0x3f, 0x01, 0xd2, 0x65, 0x30, 0x94, 0x27, 0xb3, 0xd5,
0xd0, 0x90, 0xf4, 0xef, 0x57, 0xd6, 0x04, 0xb6, 0xbc, 0xa2, 0xd7, 0x0b, 0x0c, 0x7b,
0x48, 0x1d, 0x23, 0xff, 0xcb, 0x20, 0x7e, 0x6b, 0x33, 0x41, 0xea, 0xba, 0x8e, 0x9a,
0x7a, 0xda, 0xf6, 0xeb, 0x0e, 0xb9,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0xfdb032e7d9079a94,
0x35a2809d15468d83,
0xfe4b23317e0796d5,
0xd62fa51334f560fa,
0x9ad265eb46e01984,
0x1303f3465112c8bc
0x13, 0x03, 0xf3, 0x46, 0x51, 0x12, 0xc8, 0xbc, 0x9a, 0xd2, 0x65, 0xeb, 0x46, 0xe0,
0x19, 0x84, 0xd6, 0x2f, 0xa5, 0x13, 0x34, 0xf5, 0x60, 0xfa, 0xfe, 0x4b, 0x23, 0x31,
0x7e, 0x07, 0x96, 0xd5, 0x35, 0xa2, 0x80, 0x9d, 0x15, 0x46, 0x8d, 0x83, 0xfd, 0xb0,
0x32, 0xe7, 0xd9, 0x07, 0x9a, 0x94,
]))
.unwrap(),
}
@ -624,41 +586,33 @@ fn test_fq2_subtraction() {
let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc,
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837,
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
]))
.unwrap(),
};
a.sub_assign(&Fq2 {
c0: Fq::from_repr(FqRepr([
0x619a02d78dc70ef2,
0xb93adfc9119e33e8,
0x4bf0b99a9f0dca12,
0x3b88899a42a6318f,
0x986a4a62fa82a49d,
0x13ce433fa26027f5,
0x13, 0xce, 0x43, 0x3f, 0xa2, 0x60, 0x27, 0xf5, 0x98, 0x6a, 0x4a, 0x62, 0xfa, 0x82,
0xa4, 0x9d, 0x3b, 0x88, 0x89, 0x9a, 0x42, 0xa6, 0x31, 0x8f, 0x4b, 0xf0, 0xb9, 0x9a,
0x9f, 0x0d, 0xca, 0x12, 0xb9, 0x3a, 0xdf, 0xc9, 0x11, 0x9e, 0x33, 0xe8, 0x61, 0x9a,
0x02, 0xd7, 0x8d, 0xc7, 0x0e, 0xf2,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x66323bf80b58b9b9,
0xa1379b6facf6e596,
0x402aef1fb797e32f,
0x2236f55246d0d44d,
0x4c8c1800eb104566,
0x11d6e20e986c2085,
0x11, 0xd6, 0xe2, 0x0e, 0x98, 0x6c, 0x20, 0x85, 0x4c, 0x8c, 0x18, 0x00, 0xeb, 0x10,
0x45, 0x66, 0x22, 0x36, 0xf5, 0x52, 0x46, 0xd0, 0xd4, 0x4d, 0x40, 0x2a, 0xef, 0x1f,
0xb7, 0x97, 0xe3, 0x2f, 0xa1, 0x37, 0x9b, 0x6f, 0xac, 0xf6, 0xe5, 0x96, 0x66, 0x32,
0x3b, 0xf8, 0x0b, 0x58, 0xb9, 0xb9,
]))
.unwrap(),
});
@ -666,21 +620,17 @@ fn test_fq2_subtraction() {
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x8565752bdb5c9b80,
0x7756bed7c15982e9,
0xa65a6be700b285fe,
0xe255902672ef6c43,
0x7f77a718021c342d,
0x72ba14049fe9881
0x07, 0x2b, 0xa1, 0x40, 0x49, 0xfe, 0x98, 0x81, 0x7f, 0x77, 0xa7, 0x18, 0x02, 0x1c,
0x34, 0x2d, 0xe2, 0x55, 0x90, 0x26, 0x72, 0xef, 0x6c, 0x43, 0xa6, 0x5a, 0x6b, 0xe7,
0x00, 0xb2, 0x85, 0xfe, 0x77, 0x56, 0xbe, 0xd7, 0xc1, 0x59, 0x82, 0xe9, 0x85, 0x65,
0x75, 0x2b, 0xdb, 0x5c, 0x9b, 0x80,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0xeb4abaf7c255d1cd,
0x11df49bc6cacc256,
0xe52617930588c69a,
0xf63905f39ad8cb1f,
0x4cd5dd9fb40b3b8f,
0x957411359ba6e4c
0x09, 0x57, 0x41, 0x13, 0x59, 0xba, 0x6e, 0x4c, 0x4c, 0xd5, 0xdd, 0x9f, 0xb4, 0x0b,
0x3b, 0x8f, 0xf6, 0x39, 0x05, 0xf3, 0x9a, 0xd8, 0xcb, 0x1f, 0xe5, 0x26, 0x17, 0x93,
0x05, 0x88, 0xc6, 0x9a, 0x11, 0xdf, 0x49, 0xbc, 0x6c, 0xac, 0xc2, 0x56, 0xeb, 0x4a,
0xba, 0xf7, 0xc2, 0x55, 0xd1, 0xcd,
]))
.unwrap(),
}
@ -694,21 +644,17 @@ fn test_fq2_negation() {
let a = Fq2 {
c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc,
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837,
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
]))
.unwrap(),
}
@ -717,21 +663,17 @@ fn test_fq2_negation() {
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x8cfe87fc96dbaae4,
0xcc6615c8fb0492d,
0xdc167fc04da19c37,
0xab107d49317487ab,
0x7e555df189f880e3,
0x19083f5486a10cbd
0x19, 0x08, 0x3f, 0x54, 0x86, 0xa1, 0x0c, 0xbd, 0x7e, 0x55, 0x5d, 0xf1, 0x89, 0xf8,
0x80, 0xe3, 0xab, 0x10, 0x7d, 0x49, 0x31, 0x74, 0x87, 0xab, 0xdc, 0x16, 0x7f, 0xc0,
0x4d, 0xa1, 0x9c, 0x37, 0x0c, 0xc6, 0x61, 0x5c, 0x8f, 0xb0, 0x49, 0x2d, 0x8c, 0xfe,
0x87, 0xfc, 0x96, 0xdb, 0xaa, 0xe4,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x228109103250c9d0,
0x8a411ad149045812,
0xa9109e8f3041427e,
0xb07e9bc405608611,
0xfcd559cbe77bd8b8,
0x18d400b280d93e62
0x18, 0xd4, 0x00, 0xb2, 0x80, 0xd9, 0x3e, 0x62, 0xfc, 0xd5, 0x59, 0xcb, 0xe7, 0x7b,
0xd8, 0xb8, 0xb0, 0x7e, 0x9b, 0xc4, 0x05, 0x60, 0x86, 0x11, 0xa9, 0x10, 0x9e, 0x8f,
0x30, 0x41, 0x42, 0x7e, 0x8a, 0x41, 0x1a, 0xd1, 0x49, 0x04, 0x58, 0x12, 0x22, 0x81,
0x09, 0x10, 0x32, 0x50, 0xc9, 0xd0,
]))
.unwrap(),
}
@ -745,21 +687,17 @@ fn test_fq2_doubling() {
let a = Fq2 {
c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc,
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837,
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
]))
.unwrap(),
};
@ -767,21 +705,17 @@ fn test_fq2_doubling() {
a.double(),
Fq2 {
c0: Fq::from_repr(FqRepr([
0x5a00f006d247ff8e,
0x23cb3d4443476da4,
0x1634a5c1521eb3da,
0x72cd9c7784211627,
0x998c938972a657e7,
0x1f1a52b65bdb3b9
0x01, 0xf1, 0xa5, 0x2b, 0x65, 0xbd, 0xb3, 0xb9, 0x99, 0x8c, 0x93, 0x89, 0x72, 0xa6,
0x57, 0xe7, 0x72, 0xcd, 0x9c, 0x77, 0x84, 0x21, 0x16, 0x27, 0x16, 0x34, 0xa5, 0xc1,
0x52, 0x1e, 0xb3, 0xda, 0x23, 0xcb, 0x3d, 0x44, 0x43, 0x47, 0x6d, 0xa4, 0x5a, 0x00,
0xf0, 0x06, 0xd2, 0x47, 0xff, 0x8e,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x2efbeddf9b5dc1b6,
0x28d5ca5ad09f4fdb,
0x7c4068238cdf674b,
0x67f15f81dc49195b,
0x9c8c9bd4b79fa83d,
0x25a226f714d506e
0x02, 0x5a, 0x22, 0x6f, 0x71, 0x4d, 0x50, 0x6e, 0x9c, 0x8c, 0x9b, 0xd4, 0xb7, 0x9f,
0xa8, 0x3d, 0x67, 0xf1, 0x5f, 0x81, 0xdc, 0x49, 0x19, 0x5b, 0x7c, 0x40, 0x68, 0x23,
0x8c, 0xdf, 0x67, 0x4b, 0x28, 0xd5, 0xca, 0x5a, 0xd0, 0x9f, 0x4f, 0xdb, 0x2e, 0xfb,
0xed, 0xdf, 0x9b, 0x5d, 0xc1, 0xb6,
]))
.unwrap(),
}
@ -795,21 +729,17 @@ fn test_fq2_frobenius_map() {
let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc,
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837,
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
]))
.unwrap(),
};
@ -818,21 +748,17 @@ fn test_fq2_frobenius_map() {
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
]))
.unwrap(),
}
@ -842,21 +768,17 @@ fn test_fq2_frobenius_map() {
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x228109103250c9d0,
0x8a411ad149045812,
0xa9109e8f3041427e,
0xb07e9bc405608611,
0xfcd559cbe77bd8b8,
0x18d400b280d93e62
0x18, 0xd4, 0x00, 0xb2, 0x80, 0xd9, 0x3e, 0x62, 0xfc, 0xd5, 0x59, 0xcb, 0xe7, 0x7b,
0xd8, 0xb8, 0xb0, 0x7e, 0x9b, 0xc4, 0x05, 0x60, 0x86, 0x11, 0xa9, 0x10, 0x9e, 0x8f,
0x30, 0x41, 0x42, 0x7e, 0x8a, 0x41, 0x1a, 0xd1, 0x49, 0x04, 0x58, 0x12, 0x22, 0x81,
0x09, 0x10, 0x32, 0x50, 0xc9, 0xd0,
]))
.unwrap(),
}
@ -866,21 +788,17 @@ fn test_fq2_frobenius_map() {
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
]))
.unwrap(),
}
@ -890,21 +808,17 @@ fn test_fq2_frobenius_map() {
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc
0x00, 0xf8, 0xd2, 0x95, 0xb2, 0xde, 0xd9, 0xdc, 0xcc, 0xc6, 0x49, 0xc4, 0xb9, 0x53,
0x2b, 0xf3, 0xb9, 0x66, 0xce, 0x3b, 0xc2, 0x10, 0x8b, 0x13, 0x8b, 0x1a, 0x52, 0xe0,
0xa9, 0x0f, 0x59, 0xed, 0x11, 0xe5, 0x9e, 0xa2, 0x21, 0xa3, 0xb6, 0xd2, 0x2d, 0x00,
0x78, 0x03, 0x69, 0x23, 0xff, 0xc7,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837
0x01, 0x2d, 0x11, 0x37, 0xb8, 0xa6, 0xa8, 0x37, 0x4e, 0x46, 0x4d, 0xea, 0x5b, 0xcf,
0xd4, 0x1e, 0xb3, 0xf8, 0xaf, 0xc0, 0xee, 0x24, 0x8c, 0xad, 0xbe, 0x20, 0x34, 0x11,
0xc6, 0x6f, 0xb3, 0xa5, 0x94, 0x6a, 0xe5, 0x2d, 0x68, 0x4f, 0xa7, 0xed, 0x97, 0x7d,
0xf6, 0xef, 0xcd, 0xae, 0xe0, 0xdb,
]))
.unwrap(),
}
@ -919,21 +833,17 @@ fn test_fq2_sqrt() {
assert_eq!(
Fq2 {
c0: Fq::from_repr(FqRepr([
0x476b4c309720e227,
0x34c2d04faffdab6,
0xa57e6fc1bab51fd9,
0xdb4a116b5bf74aa1,
0x1e58b2159dfe10e2,
0x7ca7da1f13606ac
0x07, 0xca, 0x7d, 0xa1, 0xf1, 0x36, 0x06, 0xac, 0x1e, 0x58, 0xb2, 0x15, 0x9d, 0xfe,
0x10, 0xe2, 0xdb, 0x4a, 0x11, 0x6b, 0x5b, 0xf7, 0x4a, 0xa1, 0xa5, 0x7e, 0x6f, 0xc1,
0xba, 0xb5, 0x1f, 0xd9, 0x03, 0x4c, 0x2d, 0x04, 0xfa, 0xff, 0xda, 0xb6, 0x47, 0x6b,
0x4c, 0x30, 0x97, 0x20, 0xe2, 0x27,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0xfa8de88b7516d2c3,
0x371a75ed14f41629,
0x4cec2dca577a3eb6,
0x212611bca4e99121,
0x8ee5394d77afb3d,
0xec92336650e49d5
0x0e, 0xc9, 0x23, 0x36, 0x65, 0x0e, 0x49, 0xd5, 0x08, 0xee, 0x53, 0x94, 0xd7, 0x7a,
0xfb, 0x3d, 0x21, 0x26, 0x11, 0xbc, 0xa4, 0xe9, 0x91, 0x21, 0x4c, 0xec, 0x2d, 0xca,
0x57, 0x7a, 0x3e, 0xb6, 0x37, 0x1a, 0x75, 0xed, 0x14, 0xf4, 0x16, 0x29, 0xfa, 0x8d,
0xe8, 0x8b, 0x75, 0x16, 0xd2, 0xc3,
]))
.unwrap(),
}
@ -941,21 +851,17 @@ fn test_fq2_sqrt() {
.unwrap(),
Fq2 {
c0: Fq::from_repr(FqRepr([
0x40b299b2704258c5,
0x6ef7de92e8c68b63,
0x6d2ddbe552203e82,
0x8d7f1f723d02c1d3,
0x881b3e01b611c070,
0x10f6963bbad2ebc5
0x10, 0xf6, 0x96, 0x3b, 0xba, 0xd2, 0xeb, 0xc5, 0x88, 0x1b, 0x3e, 0x01, 0xb6, 0x11,
0xc0, 0x70, 0x8d, 0x7f, 0x1f, 0x72, 0x3d, 0x02, 0xc1, 0xd3, 0x6d, 0x2d, 0xdb, 0xe5,
0x52, 0x20, 0x3e, 0x82, 0x6e, 0xf7, 0xde, 0x92, 0xe8, 0xc6, 0x8b, 0x63, 0x40, 0xb2,
0x99, 0xb2, 0x70, 0x42, 0x58, 0xc5,
]))
.unwrap(),
c1: Fq::from_repr(FqRepr([
0xc099534fc209e752,
0x7670594665676447,
0x28a20faed211efe7,
0x6b852aeaf2afcb1b,
0xa4c93b08105d71a9,
0x8d7cfff94216330
0x08, 0xd7, 0xcf, 0xff, 0x94, 0x21, 0x63, 0x30, 0xa4, 0xc9, 0x3b, 0x08, 0x10, 0x5d,
0x71, 0xa9, 0x6b, 0x85, 0x2a, 0xea, 0xf2, 0xaf, 0xcb, 0x1b, 0x28, 0xa2, 0x0f, 0xae,
0xd2, 0x11, 0xef, 0xe7, 0x76, 0x70, 0x59, 0x46, 0x65, 0x67, 0x64, 0x47, 0xc0, 0x99,
0x53, 0x4f, 0xc2, 0x09, 0xe7, 0x52,
]))
.unwrap(),
}
@ -964,12 +870,10 @@ fn test_fq2_sqrt() {
assert_eq!(
Fq2 {
c0: Fq::from_repr(FqRepr([
0xb9f78429d1517a6b,
0x1eabfffeb153ffff,
0x6730d2a0f6b0f624,
0x64774b84f38512bf,
0x4b1ba7b6434bacd7,
0x1a0111ea397fe69a
0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, 0x43, 0x4b,
0xac, 0xd7, 0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, 0x67, 0x30, 0xd2, 0xa0,
0xf6, 0xb0, 0xf6, 0x24, 0x1e, 0xab, 0xff, 0xfe, 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xf7,
0x84, 0x29, 0xd1, 0x51, 0x7a, 0x6b,
]))
.unwrap(),
c1: Fq::zero(),
@ -979,12 +883,10 @@ fn test_fq2_sqrt() {
Fq2 {
c0: Fq::zero(),
c1: Fq::from_repr(FqRepr([
0xb9fefffffd4357a3,
0x1eabfffeb153ffff,
0x6730d2a0f6b0f624,
0x64774b84f38512bf,
0x4b1ba7b6434bacd7,
0x1a0111ea397fe69a
0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, 0x43, 0x4b,
0xac, 0xd7, 0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, 0x67, 0x30, 0xd2, 0xa0,
0xf6, 0xb0, 0xf6, 0x24, 0x1e, 0xab, 0xff, 0xfe, 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xfe,
0xff, 0xff, 0xfd, 0x43, 0x57, 0xa3,
]))
.unwrap(),
}

View File

@ -1,11 +1,14 @@
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr};
use ff::{Field, PrimeField};
use std::ops::{AddAssign, MulAssign, SubAssign};
#[derive(PrimeField)]
#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
#[PrimeFieldGenerator = "7"]
pub struct Fr(FrRepr);
#[PrimeFieldReprEndianness = "little"]
pub struct Fr([u64; 4]);
#[cfg(test)]
use ff::PowVartime;
#[cfg(test)]
use rand_core::SeedableRng;
#[cfg(test)]
@ -13,373 +16,26 @@ use rand_xorshift::XorShiftRng;
#[cfg(test)]
use std::ops::Neg;
#[test]
fn test_fr_repr_ordering() {
fn assert_equality(a: FrRepr, b: FrRepr) {
assert_eq!(a, b);
assert!(a.cmp(&b) == ::std::cmp::Ordering::Equal);
}
fn assert_lt(a: FrRepr, b: FrRepr) {
assert!(a < b);
assert!(b > a);
}
assert_equality(
FrRepr([9999, 9999, 9999, 9999]),
FrRepr([9999, 9999, 9999, 9999]),
);
assert_equality(
FrRepr([9999, 9998, 9999, 9999]),
FrRepr([9999, 9998, 9999, 9999]),
);
assert_equality(
FrRepr([9999, 9999, 9999, 9997]),
FrRepr([9999, 9999, 9999, 9997]),
);
assert_lt(
FrRepr([9999, 9997, 9999, 9998]),
FrRepr([9999, 9997, 9999, 9999]),
);
assert_lt(
FrRepr([9999, 9997, 9998, 9999]),
FrRepr([9999, 9997, 9999, 9999]),
);
assert_lt(
FrRepr([9, 9999, 9999, 9997]),
FrRepr([9999, 9999, 9999, 9997]),
);
}
#[test]
fn test_fr_repr_from() {
assert_eq!(FrRepr::from(100), FrRepr([100, 0, 0, 0]));
}
#[test]
fn test_fr_repr_is_odd() {
assert!(!FrRepr::from(0).is_odd());
assert!(FrRepr::from(0).is_even());
assert!(FrRepr::from(1).is_odd());
assert!(!FrRepr::from(1).is_even());
assert!(!FrRepr::from(324834872).is_odd());
assert!(FrRepr::from(324834872).is_even());
assert!(FrRepr::from(324834873).is_odd());
assert!(!FrRepr::from(324834873).is_even());
}
#[test]
fn test_fr_repr_is_zero() {
assert!(FrRepr::from(0).is_zero());
assert!(!FrRepr::from(1).is_zero());
assert!(!FrRepr([0, 0, 1, 0]).is_zero());
}
#[test]
fn test_fr_repr_div2() {
let mut a = FrRepr([
0xbd2920b19c972321,
0x174ed0466a3be37e,
0xd468d5e3b551f0b5,
0xcb67c072733beefc,
]);
a.div2();
assert_eq!(
a,
FrRepr([
0x5e949058ce4b9190,
0x8ba76823351df1bf,
0x6a346af1daa8f85a,
0x65b3e039399df77e
])
);
for _ in 0..10 {
a.div2();
}
assert_eq!(
a,
FrRepr([
0x6fd7a524163392e4,
0x16a2e9da08cd477c,
0xdf9a8d1abc76aa3e,
0x196cf80e4e677d
])
);
for _ in 0..200 {
a.div2();
}
assert_eq!(a, FrRepr([0x196cf80e4e67, 0x0, 0x0, 0x0]));
for _ in 0..40 {
a.div2();
}
assert_eq!(a, FrRepr([0x19, 0x0, 0x0, 0x0]));
for _ in 0..4 {
a.div2();
}
assert_eq!(a, FrRepr([0x1, 0x0, 0x0, 0x0]));
a.div2();
assert!(a.is_zero());
}
#[test]
fn test_fr_repr_shr() {
let mut a = FrRepr([
0xb33fbaec482a283f,
0x997de0d3a88cb3df,
0x9af62d2a9a0e5525,
0x36003ab08de70da1,
]);
a.shr(0);
assert_eq!(
a,
FrRepr([
0xb33fbaec482a283f,
0x997de0d3a88cb3df,
0x9af62d2a9a0e5525,
0x36003ab08de70da1
])
);
a.shr(1);
assert_eq!(
a,
FrRepr([
0xd99fdd762415141f,
0xccbef069d44659ef,
0xcd7b16954d072a92,
0x1b001d5846f386d0
])
);
a.shr(50);
assert_eq!(
a,
FrRepr([
0xbc1a7511967bf667,
0xc5a55341caa4b32f,
0x75611bce1b4335e,
0x6c0
])
);
a.shr(130);
assert_eq!(a, FrRepr([0x1d5846f386d0cd7, 0x1b0, 0x0, 0x0]));
a.shr(64);
assert_eq!(a, FrRepr([0x1b0, 0x0, 0x0, 0x0]));
}
#[test]
fn test_fr_repr_mul2() {
let mut a = FrRepr::from(23712937547);
a.mul2();
assert_eq!(a, FrRepr([0xb0acd6c96, 0x0, 0x0, 0x0]));
for _ in 0..60 {
a.mul2();
}
assert_eq!(a, FrRepr([0x6000000000000000, 0xb0acd6c9, 0x0, 0x0]));
for _ in 0..128 {
a.mul2();
}
assert_eq!(a, FrRepr([0x0, 0x0, 0x6000000000000000, 0xb0acd6c9]));
for _ in 0..60 {
a.mul2();
}
assert_eq!(a, FrRepr([0x0, 0x0, 0x0, 0x9600000000000000]));
for _ in 0..7 {
a.mul2();
}
assert!(a.is_zero());
}
#[test]
fn test_fr_repr_num_bits() {
let mut a = FrRepr::from(0);
assert_eq!(0, a.num_bits());
a = FrRepr::from(1);
for i in 1..257 {
assert_eq!(i, a.num_bits());
a.mul2();
}
assert_eq!(0, a.num_bits());
}
#[test]
fn test_fr_repr_sub_noborrow() {
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let mut t = FrRepr([
0x8e62a7e85264e2c3,
0xb23d34c1941d3ca,
0x5976930b7502dd15,
0x600f3fb517bf5495,
]);
t.sub_noborrow(&FrRepr([
0xd64f669809cbc6a4,
0xfa76cb9d90cf7637,
0xfefb0df9038d43b3,
0x298a30c744b31acf,
]));
assert!(
t == FrRepr([
0xb813415048991c1f,
0x10ad07ae88725d92,
0x5a7b851271759961,
0x36850eedd30c39c5
])
);
for _ in 0..1000 {
let mut a = Fr::random(&mut rng).into_repr();
a.0[3] >>= 30;
let mut b = a;
for _ in 0..10 {
b.mul2();
}
let mut c = b;
for _ in 0..10 {
c.mul2();
}
assert!(a < b);
assert!(b < c);
let mut csub_ba = c;
csub_ba.sub_noborrow(&b);
csub_ba.sub_noborrow(&a);
let mut csub_ab = c;
csub_ab.sub_noborrow(&a);
csub_ab.sub_noborrow(&b);
assert_eq!(csub_ab, csub_ba);
}
// Subtracting r+1 from r should produce -1 (mod 2**256)
let mut qplusone = FrRepr([
0xffffffff00000001,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]);
qplusone.sub_noborrow(&FrRepr([
0xffffffff00000002,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]));
assert_eq!(
qplusone,
FrRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff
])
);
}
#[test]
fn test_fr_repr_add_nocarry() {
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
let mut t = FrRepr([
0xd64f669809cbc6a4,
0xfa76cb9d90cf7637,
0xfefb0df9038d43b3,
0x298a30c744b31acf,
]);
t.add_nocarry(&FrRepr([
0x8e62a7e85264e2c3,
0xb23d34c1941d3ca,
0x5976930b7502dd15,
0x600f3fb517bf5495,
]));
assert_eq!(
t,
FrRepr([
0x64b20e805c30a967,
0x59a9ee9aa114a02,
0x5871a104789020c9,
0x8999707c5c726f65
])
);
// Test for the associativity of addition.
for _ in 0..1000 {
let mut a = Fr::random(&mut rng).into_repr();
let mut b = Fr::random(&mut rng).into_repr();
let mut c = Fr::random(&mut rng).into_repr();
// Unset the first few bits, so that overflow won't occur.
a.0[3] >>= 3;
b.0[3] >>= 3;
c.0[3] >>= 3;
let mut abc = a;
abc.add_nocarry(&b);
abc.add_nocarry(&c);
let mut acb = a;
acb.add_nocarry(&c);
acb.add_nocarry(&b);
let mut bac = b;
bac.add_nocarry(&a);
bac.add_nocarry(&c);
let mut bca = b;
bca.add_nocarry(&c);
bca.add_nocarry(&a);
let mut cab = c;
cab.add_nocarry(&a);
cab.add_nocarry(&b);
let mut cba = c;
cba.add_nocarry(&b);
cba.add_nocarry(&a);
assert_eq!(abc, acb);
assert_eq!(abc, bac);
assert_eq!(abc, bca);
assert_eq!(abc, cab);
assert_eq!(abc, cba);
}
// Adding 1 to (2^256 - 1) should produce zero
let mut x = FrRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
]);
x.add_nocarry(&FrRepr::from(1));
assert!(x.is_zero());
}
#[test]
fn test_fr_is_valid() {
let mut a = Fr(MODULUS);
let mut a = MODULUS_LIMBS;
assert!(!a.is_valid());
a.0.sub_noborrow(&FrRepr::from(1));
a.sub_noborrow(&Fr([1, 0, 0, 0]));
assert!(a.is_valid());
assert!(Fr(FrRepr::from(0)).is_valid());
assert!(Fr(FrRepr([
assert!(Fr::from(0).is_valid());
assert!(Fr([
0xffffffff00000000,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48
]))
])
.is_valid());
assert!(!Fr(FrRepr([
assert!(!Fr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff
]))
])
.is_valid());
let mut rng = XorShiftRng::from_seed([
@ -397,85 +53,85 @@ fn test_fr_is_valid() {
fn test_fr_add_assign() {
{
// Random number
let mut tmp = Fr(FrRepr([
let mut tmp = Fr([
0x437ce7616d580765,
0xd42d1ccb29d1235b,
0xed8f753821bd1423,
0x4eede1c9c89528ca,
]));
]);
assert!(tmp.is_valid());
// Test that adding zero has no effect.
tmp.add_assign(&Fr(FrRepr::from(0)));
tmp.add_assign(&Fr([0, 0, 0, 0]));
assert_eq!(
tmp,
Fr(FrRepr([
Fr([
0x437ce7616d580765,
0xd42d1ccb29d1235b,
0xed8f753821bd1423,
0x4eede1c9c89528ca
]))
])
);
// Add one and test for the result.
tmp.add_assign(&Fr(FrRepr::from(1)));
tmp.add_assign(&Fr([1, 0, 0, 0]));
assert_eq!(
tmp,
Fr(FrRepr([
Fr([
0x437ce7616d580766,
0xd42d1ccb29d1235b,
0xed8f753821bd1423,
0x4eede1c9c89528ca
]))
])
);
// Add another random number that exercises the reduction.
tmp.add_assign(&Fr(FrRepr([
tmp.add_assign(&Fr([
0x946f435944f7dc79,
0xb55e7ee6533a9b9b,
0x1e43b84c2f6194ca,
0x58717ab525463496,
])));
]));
assert_eq!(
tmp,
Fr(FrRepr([
Fr([
0xd7ec2abbb24fe3de,
0x35cdf7ae7d0d62f7,
0xd899557c477cd0e9,
0x3371b52bc43de018
]))
])
);
// Add one to (r - 1) and test for the result.
tmp = Fr(FrRepr([
tmp = Fr([
0xffffffff00000000,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]));
tmp.add_assign(&Fr(FrRepr::from(1)));
assert!(tmp.0.is_zero());
]);
tmp.add_assign(&Fr([1, 0, 0, 0]));
assert!(tmp.is_zero());
// Add a random number to another one such that the result is r - 1
tmp = Fr(FrRepr([
tmp = Fr([
0xade5adacdccb6190,
0xaa21ee0f27db3ccd,
0x2550f4704ae39086,
0x591d1902e7c5ba27,
]));
tmp.add_assign(&Fr(FrRepr([
]);
tmp.add_assign(&Fr([
0x521a525223349e70,
0xa99bb5f3d8231f31,
0xde8e397bebe477e,
0x1ad08e5041d7c321,
])));
]));
assert_eq!(
tmp,
Fr(FrRepr([
Fr([
0xffffffff00000000,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48
]))
])
);
// Add one to the result and test for it.
tmp.add_assign(&Fr(FrRepr::from(1)));
assert!(tmp.0.is_zero());
tmp.add_assign(&Fr([1, 0, 0, 0]));
assert!(tmp.is_zero());
}
// Test associativity
@ -509,71 +165,71 @@ fn test_fr_add_assign() {
fn test_fr_sub_assign() {
{
// Test arbitrary subtraction that tests reduction.
let mut tmp = Fr(FrRepr([
let mut tmp = Fr([
0x6a68c64b6f735a2b,
0xd5f4d143fe0a1972,
0x37c17f3829267c62,
0xa2f37391f30915c,
]));
tmp.sub_assign(&Fr(FrRepr([
]);
tmp.sub_assign(&Fr([
0xade5adacdccb6190,
0xaa21ee0f27db3ccd,
0x2550f4704ae39086,
0x591d1902e7c5ba27,
])));
]));
assert_eq!(
tmp,
Fr(FrRepr([
Fr([
0xbc83189d92a7f89c,
0x7f908737d62d38a3,
0x45aa62cfe7e4c3e1,
0x24ffc5896108547d
]))
])
);
// Test the opposite subtraction which doesn't test reduction.
tmp = Fr(FrRepr([
tmp = Fr([
0xade5adacdccb6190,
0xaa21ee0f27db3ccd,
0x2550f4704ae39086,
0x591d1902e7c5ba27,
]));
tmp.sub_assign(&Fr(FrRepr([
]);
tmp.sub_assign(&Fr([
0x6a68c64b6f735a2b,
0xd5f4d143fe0a1972,
0x37c17f3829267c62,
0xa2f37391f30915c,
])));
]));
assert_eq!(
tmp,
Fr(FrRepr([
Fr([
0x437ce7616d580765,
0xd42d1ccb29d1235b,
0xed8f753821bd1423,
0x4eede1c9c89528ca
]))
])
);
// Test for sensible results with zero
tmp = Fr(FrRepr::from(0));
tmp.sub_assign(&Fr(FrRepr::from(0)));
tmp = Fr::from(0);
tmp.sub_assign(&Fr::from(0));
assert!(tmp.is_zero());
tmp = Fr(FrRepr([
tmp = Fr([
0x437ce7616d580765,
0xd42d1ccb29d1235b,
0xed8f753821bd1423,
0x4eede1c9c89528ca,
]));
tmp.sub_assign(&Fr(FrRepr::from(0)));
]);
tmp.sub_assign(&Fr::from(0));
assert_eq!(
tmp,
Fr(FrRepr([
Fr([
0x437ce7616d580765,
0xd42d1ccb29d1235b,
0xed8f753821bd1423,
0x4eede1c9c89528ca
]))
])
);
}
@ -600,25 +256,25 @@ fn test_fr_sub_assign() {
#[test]
fn test_fr_mul_assign() {
let mut tmp = Fr(FrRepr([
let mut tmp = Fr([
0x6b7e9b8faeefc81a,
0xe30a8463f348ba42,
0xeff3cb67a8279c9c,
0x3d303651bd7c774d,
]));
tmp.mul_assign(&Fr(FrRepr([
]);
tmp.mul_assign(&Fr([
0x13ae28e3bc35ebeb,
0xa10f4488075cae2c,
0x8160e95a853c3b5d,
0x5ae3f03b561a841d,
])));
]));
assert!(
tmp == Fr(FrRepr([
tmp == Fr([
0x23717213ce710f71,
0xdbee1fe53a16e1af,
0xf565d3e1c2a48000,
0x4426507ee75df9d7
]))
])
);
let mut rng = XorShiftRng::from_seed([
@ -667,22 +323,76 @@ fn test_fr_mul_assign() {
}
}
#[test]
fn test_fr_shr() {
let mut a = Fr::from_repr(FrRepr([
0x3f, 0x28, 0x2a, 0x48, 0xec, 0xba, 0x3f, 0xb3, 0xdf, 0xb3, 0x8c, 0xa8, 0xd3, 0xe0, 0x7d,
0x99, 0x25, 0x55, 0x0e, 0x9a, 0x2a, 0x2d, 0xf6, 0x9a, 0xa1, 0x0d, 0xe7, 0x8d, 0xb0, 0x3a,
0x00, 0x36,
]))
.unwrap();
a = a >> 0;
assert_eq!(
a.into_repr(),
FrRepr([
0x3f, 0x28, 0x2a, 0x48, 0xec, 0xba, 0x3f, 0xb3, 0xdf, 0xb3, 0x8c, 0xa8, 0xd3, 0xe0,
0x7d, 0x99, 0x25, 0x55, 0x0e, 0x9a, 0x2a, 0x2d, 0xf6, 0x9a, 0xa1, 0x0d, 0xe7, 0x8d,
0xb0, 0x3a, 0x00, 0x36,
])
);
a = a >> 1;
assert_eq!(
a.into_repr(),
FrRepr([
0x1f, 0x14, 0x15, 0x24, 0x76, 0xdd, 0x9f, 0xd9, 0xef, 0x59, 0x46, 0xd4, 0x69, 0xf0,
0xbe, 0xcc, 0x92, 0x2a, 0x07, 0x4d, 0x95, 0x16, 0x7b, 0xcd, 0xd0, 0x86, 0xf3, 0x46,
0x58, 0x1d, 0x00, 0x1b,
])
);
a = a >> 50;
assert_eq!(
a.into_repr(),
FrRepr([
0x67, 0xf6, 0x7b, 0x96, 0x11, 0x75, 0x1a, 0xbc, 0x2f, 0xb3, 0xa4, 0xca, 0x41, 0x53,
0xa5, 0xc5, 0x5e, 0x33, 0xb4, 0xe1, 0xbc, 0x11, 0x56, 0x07, 0xc0, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
])
);
a = a >> 130;
assert_eq!(
a.into_repr(),
FrRepr([
0xd7, 0x0c, 0x6d, 0x38, 0x6f, 0x84, 0xd5, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
])
);
a = a >> 64;
assert_eq!(
a.into_repr(),
FrRepr([
0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
])
);
}
#[test]
fn test_fr_squaring() {
let a = Fr(FrRepr([
let a = Fr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0x73eda753299d7d47,
]));
]);
assert!(a.is_valid());
assert_eq!(
a.square(),
Fr::from_repr(FrRepr([
0xc0d698e7bde077b8,
0xb79a310579e76ec2,
0xac1da8d0a9af4e5f,
0x13f629c49bf23e97
0xb8, 0x77, 0xe0, 0xbd, 0xe7, 0x98, 0xd6, 0xc0, 0xc2, 0x6e, 0xe7, 0x79, 0x05, 0x31,
0x9a, 0xb7, 0x5f, 0x4e, 0xaf, 0xa9, 0xd0, 0xa8, 0x1d, 0xac, 0x97, 0x3e, 0xf2, 0x9b,
0xc4, 0x29, 0xf6, 0x13,
]))
.unwrap()
);
@ -763,7 +473,7 @@ fn test_fr_pow() {
0xe5,
]);
for i in 0..1000 {
for i in 0u64..1000 {
// Exponentiate by various small numbers and ensure it consists with repeated
// multiplication.
let a = Fr::random(&mut rng);
@ -820,42 +530,38 @@ fn test_fr_sqrt() {
fn test_fr_from_into_repr() {
// r + 1 should not be in the field
assert!(Fr::from_repr(FrRepr([
0xffffffff00000002,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48
0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x5b, 0xfe, 0xff, 0x02, 0xa4, 0xbd,
0x53, 0x05, 0xd8, 0xa1, 0x09, 0x08, 0xd8, 0x39, 0x33, 0x48, 0x7d, 0x9d, 0x29, 0x53, 0xa7,
0xed, 0x73,
]))
.is_err());
.is_none());
// r should not be in the field
assert!(Fr::from_repr(Fr::char()).is_err());
assert!(Fr::from_repr(Fr::char()).is_none());
// Multiply some arbitrary representations to see if the result is as expected.
let a = FrRepr([
0x25ebe3a3ad3c0c6a,
0x6990e39d092e817c,
0x941f900d42f5658e,
0x44f8a103b38a71e0,
0x6a, 0x0c, 0x3c, 0xad, 0xa3, 0xe3, 0xeb, 0x25, 0x7c, 0x81, 0x2e, 0x09, 0x9d, 0xe3, 0x90,
0x69, 0x8e, 0x65, 0xf5, 0x42, 0x0d, 0x90, 0x1f, 0x94, 0xe0, 0x71, 0x8a, 0xb3, 0x03, 0xa1,
0xf8, 0x44,
]);
let mut a_fr = Fr::from_repr(a).unwrap();
let b = FrRepr([
0x264e9454885e2475,
0x46f7746bb0308370,
0x4683ef5347411f9,
0x58838d7f208d4492,
0x75, 0x24, 0x5e, 0x88, 0x54, 0x94, 0x4e, 0x26, 0x70, 0x83, 0x30, 0xb0, 0x6b, 0x74, 0xf7,
0x46, 0xf9, 0x11, 0x74, 0x34, 0xf5, 0x3e, 0x68, 0x04, 0x92, 0x44, 0x8d, 0x20, 0x7f, 0x8d,
0x83, 0x58,
]);
let b_fr = Fr::from_repr(b).unwrap();
let c = FrRepr([
0x48a09ab93cfc740d,
0x3a6600fbfc7a671,
0x838567017501d767,
0x7161d6da77745512,
0x0d, 0x74, 0xfc, 0x3c, 0xb9, 0x9a, 0xa0, 0x48, 0x71, 0xa6, 0xc7, 0xbf, 0x0f, 0x60, 0xa6,
0x03, 0x67, 0xd7, 0x01, 0x75, 0x01, 0x67, 0x85, 0x83, 0x12, 0x55, 0x74, 0x77, 0xda, 0xd6,
0x61, 0x71,
]);
a_fr.mul_assign(&b_fr);
assert_eq!(a_fr.into_repr(), c);
// Zero should be in the field.
assert!(Fr::from_repr(FrRepr::from(0)).unwrap().is_zero());
assert!(Fr::from_repr(FrRepr([0; 32])).unwrap().is_zero());
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
@ -874,60 +580,15 @@ fn test_fr_from_into_repr() {
}
}
#[test]
fn test_fr_repr_display() {
assert_eq!(
format!(
"{}",
FrRepr([
0x2829c242fa826143,
0x1f32cf4dd4330917,
0x932e4e479d168cd9,
0x513c77587f563f64
])
),
"0x513c77587f563f64932e4e479d168cd91f32cf4dd43309172829c242fa826143".to_string()
);
assert_eq!(
format!(
"{}",
FrRepr([
0x25ebe3a3ad3c0c6a,
0x6990e39d092e817c,
0x941f900d42f5658e,
0x44f8a103b38a71e0
])
),
"0x44f8a103b38a71e0941f900d42f5658e6990e39d092e817c25ebe3a3ad3c0c6a".to_string()
);
assert_eq!(
format!(
"{}",
FrRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff
])
),
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".to_string()
);
assert_eq!(
format!("{}", FrRepr([0, 0, 0, 0])),
"0x0000000000000000000000000000000000000000000000000000000000000000".to_string()
);
}
#[test]
fn test_fr_display() {
assert_eq!(
format!(
"{}",
Fr::from_repr(FrRepr([
0xc3cae746a3b5ecc7,
0x185ec8eb3f5b5aee,
0x684499ffe4b9dd99,
0x7c9bba7afb68faa
0xc7, 0xec, 0xb5, 0xa3, 0x46, 0xe7, 0xca, 0xc3, 0xee, 0x5a, 0x5b, 0x3f, 0xeb, 0xc8,
0x5e, 0x18, 0x99, 0xdd, 0xb9, 0xe4, 0xff, 0x99, 0x44, 0x68, 0xaa, 0x8f, 0xb6, 0xaf,
0xa7, 0xbb, 0xc9, 0x07,
]))
.unwrap()
),
@ -937,10 +598,9 @@ fn test_fr_display() {
format!(
"{}",
Fr::from_repr(FrRepr([
0x44c71298ff198106,
0xb0ad10817df79b6a,
0xd034a80a2b74132b,
0x41cf9a1336f50719
0x06, 0x81, 0x19, 0xff, 0x98, 0x12, 0xc7, 0x44, 0x6a, 0x9b, 0xf7, 0x7d, 0x81, 0x10,
0xad, 0xb0, 0x2b, 0x13, 0x74, 0x2b, 0x0a, 0xa8, 0x34, 0xd0, 0x19, 0x07, 0xf5, 0x36,
0x13, 0x9a, 0xcf, 0x41,
]))
.unwrap()
),
@ -948,6 +608,18 @@ fn test_fr_display() {
);
}
#[test]
fn test_fr_is_odd() {
assert!(!Fr::from(0).is_odd());
assert!(Fr::from(0).is_even());
assert!(Fr::from(1).is_odd());
assert!(!Fr::from(1).is_even());
assert!(!Fr::from(324834872).is_odd());
assert!(Fr::from(324834872).is_even());
assert!(Fr::from(324834873).is_odd());
assert!(!Fr::from(324834873).is_even());
}
#[test]
fn test_fr_num_bits() {
assert_eq!(Fr::NUM_BITS, 255);
@ -959,20 +631,17 @@ fn test_fr_root_of_unity() {
use ff::SqrtField;
assert_eq!(Fr::S, 32);
assert_eq!(
Fr::multiplicative_generator(),
Fr::from_repr(FrRepr::from(7)).unwrap()
);
assert_eq!(Fr::multiplicative_generator(), Fr::from(7));
assert_eq!(
Fr::multiplicative_generator().pow_vartime([
0xfffe5bfeffffffff,
0xfffe5bfeffffffffu64,
0x9a1d80553bda402,
0x299d7d483339d808,
0x73eda753
]),
Fr::root_of_unity()
);
assert_eq!(Fr::root_of_unity().pow_vartime([1 << Fr::S]), Fr::one());
assert_eq!(Fr::root_of_unity().pow_vartime([1u64 << Fr::S]), Fr::one());
assert!(bool::from(Fr::multiplicative_generator().sqrt().is_none()));
}

View File

@ -23,7 +23,7 @@ pub use self::fr::{Fr, FrRepr};
use super::{Engine, PairingCurveAffine};
use ff::{BitIterator, Field, ScalarEngine};
use ff::{BitIterator, Field, PowVartime, ScalarEngine};
use group::CurveAffine;
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
use subtle::CtOption;
@ -82,7 +82,7 @@ impl Engine for Bls12 {
let mut f = Fq12::one();
let mut found_one = false;
for i in BitIterator::new(&[BLS_X >> 1]) {
for i in BitIterator::<u64, _>::new(&[BLS_X >> 1]) {
if !found_one {
found_one = i;
continue;
@ -324,7 +324,7 @@ impl G2Prepared {
let mut r: G2 = q.into();
let mut found_one = false;
for i in BitIterator::new([BLS_X >> 1]) {
for i in BitIterator::<u64, _>::new([BLS_X >> 1]) {
if !found_one {
found_one = i;
continue;

View File

@ -1,4 +1,4 @@
use ff::PrimeFieldRepr;
use ff::PrimeField;
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
use super::*;
@ -147,13 +147,15 @@ fn test_g1_uncompressed_invalid_vectors() {
}
}
let m = Fq::char();
// PrimeField::char() returns the modulus in its little-endian byte representation,
// but Fq field elements use big-endian encoding, so flip the endianness.
let m: Vec<_> = Fq::char().as_ref().iter().cloned().rev().collect();
{
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
o.as_mut()[..48].copy_from_slice(&m[..]);
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate");
} else {
panic!("should have rejected the point")
@ -162,9 +164,9 @@ fn test_g1_uncompressed_invalid_vectors() {
{
let mut o = o;
m.write_be(&mut o.as_mut()[48..]).unwrap();
o.as_mut()[48..].copy_from_slice(&m[..]);
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "y coordinate");
} else {
panic!("should have rejected the point")
@ -175,7 +177,7 @@ fn test_g1_uncompressed_invalid_vectors() {
let m = Fq::zero().into_repr();
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
o.as_mut()[..48].copy_from_slice(m.as_ref());
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
// :)
@ -191,15 +193,15 @@ fn test_g1_uncompressed_invalid_vectors() {
loop {
let mut x3b = x.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API?
x3b.add_assign(&Fq::from(4)); // TODO: perhaps expose coeff_b through API?
let y = x3b.sqrt();
if y.is_some().into() {
let y = y.unwrap();
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
x.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
y.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
o.as_mut()[..48].copy_from_slice(x.into_repr().as_ref());
o.as_mut()[48..].copy_from_slice(y.into_repr().as_ref());
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
break;
@ -263,13 +265,15 @@ fn test_g2_uncompressed_invalid_vectors() {
}
}
let m = Fq::char();
// PrimeField::char() returns the modulus in its little-endian byte representation,
// but Fq field elements use big-endian encoding, so flip the endianness.
let m: Vec<_> = Fq::char().as_ref().iter().cloned().rev().collect();
{
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
o.as_mut()[..48].copy_from_slice(&m[..]);
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c1)");
} else {
panic!("should have rejected the point")
@ -278,9 +282,9 @@ fn test_g2_uncompressed_invalid_vectors() {
{
let mut o = o;
m.write_be(&mut o.as_mut()[48..]).unwrap();
o.as_mut()[48..96].copy_from_slice(&m[..]);
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c0)");
} else {
panic!("should have rejected the point")
@ -289,9 +293,9 @@ fn test_g2_uncompressed_invalid_vectors() {
{
let mut o = o;
m.write_be(&mut o.as_mut()[96..]).unwrap();
o.as_mut()[96..144].copy_from_slice(&m[..]);
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "y coordinate (c1)");
} else {
panic!("should have rejected the point")
@ -300,9 +304,9 @@ fn test_g2_uncompressed_invalid_vectors() {
{
let mut o = o;
m.write_be(&mut o.as_mut()[144..]).unwrap();
o.as_mut()[144..].copy_from_slice(&m[..]);
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "y coordinate (c0)");
} else {
panic!("should have rejected the point")
@ -313,8 +317,8 @@ fn test_g2_uncompressed_invalid_vectors() {
let m = Fq::zero().into_repr();
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
m.write_be(&mut o.as_mut()[48..]).unwrap();
o.as_mut()[..48].copy_from_slice(m.as_ref());
o.as_mut()[48..96].copy_from_slice(m.as_ref());
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
// :)
@ -331,8 +335,8 @@ fn test_g2_uncompressed_invalid_vectors() {
let mut x3b = x.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq2 {
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
c1: Fq::from_repr(FqRepr::from(4)).unwrap(),
c0: Fq::from(4),
c1: Fq::from(4),
}); // TODO: perhaps expose coeff_b through API?
let y = x3b.sqrt();
@ -340,10 +344,10 @@ fn test_g2_uncompressed_invalid_vectors() {
let y = y.unwrap();
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
x.c1.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
x.c0.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
y.c1.into_repr().write_be(&mut o.as_mut()[96..]).unwrap();
y.c0.into_repr().write_be(&mut o.as_mut()[144..]).unwrap();
o.as_mut()[..48].copy_from_slice(x.c1.into_repr().as_ref());
o.as_mut()[48..96].copy_from_slice(x.c0.into_repr().as_ref());
o.as_mut()[96..144].copy_from_slice(y.c1.into_repr().as_ref());
o.as_mut()[144..].copy_from_slice(y.c0.into_repr().as_ref());
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
break;
@ -407,14 +411,16 @@ fn test_g1_compressed_invalid_vectors() {
}
}
let m = Fq::char();
// PrimeField::char() returns the modulus in its little-endian byte representation,
// but Fq field elements use big-endian encoding, so flip the endianness.
let m: Vec<_> = Fq::char().as_ref().iter().cloned().rev().collect();
{
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
o.as_mut()[..48].copy_from_slice(&m[..]);
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate");
} else {
panic!("should have rejected the point")
@ -428,12 +434,12 @@ fn test_g1_compressed_invalid_vectors() {
loop {
let mut x3b = x.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API?
x3b.add_assign(&Fq::from(4)); // TODO: perhaps expose coeff_b through API?
if x3b.sqrt().is_some().into() {
x.add_assign(&Fq::one());
} else {
x.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
o.as_mut().copy_from_slice(x.into_repr().as_ref());
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
@ -452,11 +458,11 @@ fn test_g1_compressed_invalid_vectors() {
loop {
let mut x3b = x.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API?
x3b.add_assign(&Fq::from(4)); // TODO: perhaps expose coeff_b through API?
if x3b.sqrt().is_some().into() {
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
x.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
o.as_mut().copy_from_slice(x.into_repr().as_ref());
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
@ -521,14 +527,16 @@ fn test_g2_compressed_invalid_vectors() {
}
}
let m = Fq::char();
// PrimeField::char() returns the modulus in its little-endian byte representation,
// but Fq field elements use big-endian encoding, so flip the endianness.
let m: Vec<_> = Fq::char().as_ref().iter().cloned().rev().collect();
{
let mut o = o;
m.write_be(&mut o.as_mut()[0..]).unwrap();
o.as_mut()[..48].copy_from_slice(&m[..]);
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c1)");
} else {
panic!("should have rejected the point")
@ -537,10 +545,10 @@ fn test_g2_compressed_invalid_vectors() {
{
let mut o = o;
m.write_be(&mut o.as_mut()[48..]).unwrap();
o.as_mut()[48..96].copy_from_slice(&m[..]);
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate, _)) = o.into_affine() {
if let Err(GroupDecodingError::CoordinateDecodingError(coordinate)) = o.into_affine() {
assert_eq!(coordinate, "x coordinate (c0)");
} else {
panic!("should have rejected the point")
@ -558,15 +566,15 @@ fn test_g2_compressed_invalid_vectors() {
let mut x3b = x.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq2 {
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
c1: Fq::from_repr(FqRepr::from(4)).unwrap(),
c0: Fq::from(4),
c1: Fq::from(4),
}); // TODO: perhaps expose coeff_b through API?
if x3b.sqrt().is_some().into() {
x.add_assign(&Fq2::one());
} else {
x.c1.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
x.c0.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
o.as_mut()[..48].copy_from_slice(x.c1.into_repr().as_ref());
o.as_mut()[48..].copy_from_slice(x.c0.into_repr().as_ref());
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
@ -589,14 +597,14 @@ fn test_g2_compressed_invalid_vectors() {
let mut x3b = x.square();
x3b.mul_assign(&x);
x3b.add_assign(&Fq2 {
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
c1: Fq::from_repr(FqRepr::from(4)).unwrap(),
c0: Fq::from(4),
c1: Fq::from(4),
}); // TODO: perhaps expose coeff_b through API?
if x3b.sqrt().is_some().into() {
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
x.c1.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
x.c0.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
o.as_mut()[..48].copy_from_slice(x.c1.into_repr().as_ref());
o.as_mut()[48..].copy_from_slice(x.c0.into_repr().as_ref());
o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {

View File

@ -1,3 +1,4 @@
use ff::PowVartime;
use group::{CurveAffine, CurveProjective};
use rand_core::SeedableRng;
use rand_xorshift::XorShiftRng;

View File

@ -1,8 +1,8 @@
use ff::{Field, PrimeField, SqrtField};
use ff::{Field, PowVartime, PrimeField, SqrtField};
use rand_core::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;
pub fn random_frobenius_tests<F: Field, C: AsRef<[u64]>>(characteristic: C, maxpower: usize) {
pub fn random_frobenius_tests<F: Field, C: AsRef<[u8]>>(characteristic: C, maxpower: usize) {
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
@ -119,7 +119,7 @@ pub fn from_str_tests<F: PrimeField>() {
let n = rng.next_u64();
let a = F::from_str(&format!("{}", n)).unwrap();
let b = F::from_repr(n.into()).unwrap();
let b = F::from(n);
assert_eq!(a, b);
}

View File

@ -1,10 +1,9 @@
use ff::{PrimeField, PrimeFieldRepr};
use ff::PrimeField;
use rand_core::SeedableRng;
use rand_xorshift::XorShiftRng;
pub fn random_repr_tests<P: PrimeField>() {
random_encoding_tests::<P>();
random_shl_tests::<P>();
random_shr_tests::<P>();
}
@ -15,72 +14,13 @@ fn random_encoding_tests<P: PrimeField>() {
]);
for _ in 0..1000 {
let r = P::random(&mut rng).into_repr();
let r = P::random(&mut rng);
// Big endian
{
let mut rdecoded = <P as PrimeField>::Repr::default();
let mut v: Vec<u8> = vec![];
r.write_be(&mut v).unwrap();
rdecoded.read_be(&v[0..]).unwrap();
let v = r.into_repr();
let rdecoded = P::from_repr(v).unwrap();
assert_eq!(r, rdecoded);
}
// Little endian
{
let mut rdecoded = <P as PrimeField>::Repr::default();
let mut v: Vec<u8> = vec![];
r.write_le(&mut v).unwrap();
rdecoded.read_le(&v[0..]).unwrap();
assert_eq!(r, rdecoded);
}
{
let mut rdecoded_le = <P as PrimeField>::Repr::default();
let mut rdecoded_be_flip = <P as PrimeField>::Repr::default();
let mut v: Vec<u8> = vec![];
r.write_le(&mut v).unwrap();
// This reads in little-endian, so we are done.
rdecoded_le.read_le(&v[..]).unwrap();
// This reads in big-endian, so we perform a swap of the
// bytes beforehand.
let v: Vec<u8> = v.into_iter().rev().collect();
rdecoded_be_flip.read_be(&v[..]).unwrap();
assert_eq!(rdecoded_le, rdecoded_be_flip);
}
}
}
fn random_shl_tests<P: PrimeField>() {
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
]);
for _ in 0..100 {
let r = P::random(&mut rng).into_repr();
for shift in 0..=r.num_bits() {
let mut r1 = r;
let mut r2 = r;
for _ in 0..shift {
r1.mul2();
}
r2.shl(shift);
assert_eq!(r1, r2);
}
}
}
fn random_shr_tests<P: PrimeField>() {
@ -90,19 +30,22 @@ fn random_shr_tests<P: PrimeField>() {
]);
for _ in 0..100 {
let r = P::random(&mut rng).into_repr();
let r = P::random(&mut rng);
for shift in 0..=r.num_bits() {
let mut r1 = r;
let mut r2 = r;
for shift in 0..P::NUM_BITS {
let r1 = r >> shift;
// Doubling the shifted element inserts zeros on the right; re-shifting should
// undo the doubling.
let mut r2 = r1;
for _ in 0..shift {
r1.div2();
r2 = r2.double();
}
r2.shr(shift);
r2 = r2 >> shift;
assert_eq!(r1, r2);
}
assert_eq!(r >> P::NUM_BITS, P::zero());
}
}

View File

@ -1,6 +1,6 @@
//! Generated code for handling light client protobuf structs.
use ff::{PrimeField, PrimeFieldRepr};
use ff::PrimeField;
use pairing::bls12_381::{Bls12, Fr, FrRepr};
use zcash_primitives::{
block::{BlockHash, BlockHeader},
@ -67,8 +67,8 @@ impl compact_formats::CompactOutput {
/// [`CompactOutput.cmu`]: #structfield.cmu
pub fn cmu(&self) -> Result<Fr, ()> {
let mut repr = FrRepr::default();
repr.read_le(&self.cmu[..]).map_err(|_| ())?;
Fr::from_repr(repr).map_err(|_| ())
repr.as_mut().copy_from_slice(&self.cmu[..]);
Fr::from_repr(repr).ok_or(())
}
/// Returns the ephemeral public key for this output.

View File

@ -183,7 +183,7 @@ pub fn scan_block(
#[cfg(test)]
mod tests {
use ff::{Field, PrimeField, PrimeFieldRepr};
use ff::{Field, PrimeField};
use pairing::bls12_381::{Bls12, Fr};
use rand_core::{OsRng, RngCore};
use zcash_primitives::{
@ -207,9 +207,7 @@ mod tests {
};
let fake_cmu = {
let fake_cmu = Fr::random(rng);
let mut bytes = vec![];
fake_cmu.into_repr().write_le(&mut bytes).unwrap();
bytes
fake_cmu.into_repr().as_ref().to_owned()
};
let fake_epk = {
let mut buffer = vec![0; 64];
@ -264,8 +262,7 @@ mod tests {
Memo::default(),
&mut rng,
);
let mut cmu = vec![];
note.cm(&JUBJUB).into_repr().write_le(&mut cmu).unwrap();
let cmu = note.cm(&JUBJUB).into_repr().as_ref().to_owned();
let mut epk = vec![];
encryptor.epk().write(&mut epk).unwrap();
let enc_ciphertext = encryptor.encrypt_note_plaintext();

View File

@ -1,4 +1,4 @@
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use ff::{BitIterator, Field, PrimeField, SqrtField};
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
use subtle::CtOption;
@ -83,15 +83,15 @@ impl<E: JubjubEngine, Subgroup> PartialEq for Point<E, Subgroup> {
}
impl<E: JubjubEngine> Point<E, Unknown> {
pub fn read<R: Read>(reader: R, params: &E::Params) -> io::Result<Self> {
pub fn read<R: Read>(mut reader: R, params: &E::Params) -> io::Result<Self> {
let mut y_repr = <E::Fr as PrimeField>::Repr::default();
y_repr.read_le(reader)?;
reader.read_exact(y_repr.as_mut())?;
let x_sign = (y_repr.as_ref()[3] >> 63) == 1;
y_repr.as_mut()[3] &= 0x7fffffffffffffff;
let x_sign = (y_repr.as_ref()[31] >> 7) == 1;
y_repr.as_mut()[31] &= 0x7f;
match E::Fr::from_repr(y_repr) {
Ok(y) => {
Some(y) => {
let p = Self::get_for_y(y, x_sign, params);
if bool::from(p.is_some()) {
Ok(p.unwrap())
@ -99,7 +99,7 @@ impl<E: JubjubEngine> Point<E, Unknown> {
Err(io::Error::new(io::ErrorKind::InvalidInput, "not on curve"))
}
}
Err(_) => Err(io::Error::new(
None => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"y is not in field",
)),
@ -127,7 +127,7 @@ impl<E: JubjubEngine> Point<E, Unknown> {
tmp1.mul_assign(&tmp2);
tmp1.sqrt().map(|mut x| {
if x.into_repr().is_odd() != sign {
if x.is_odd() != sign {
x = x.neg();
}
@ -167,18 +167,17 @@ impl<E: JubjubEngine> Point<E, Unknown> {
}
impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
pub fn write<W: Write>(&self, writer: W) -> io::Result<()> {
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
let (x, y) = self.to_xy();
assert_eq!(E::Fr::NUM_BITS, 255);
let x_repr = x.into_repr();
let mut y_repr = y.into_repr();
if x_repr.is_odd() {
y_repr.as_mut()[3] |= 0x8000000000000000u64;
if x.is_odd() {
y_repr.as_mut()[31] |= 0x80;
}
y_repr.write_le(writer)
writer.write_all(y_repr.as_ref())
}
/// Convert from a Montgomery point
@ -468,7 +467,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
let mut res = Self::zero();
for b in BitIterator::new(scalar.into()) {
for b in BitIterator::<u8, _>::new(scalar.into()) {
res = res.double(params);
if b {

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField};
use ff::{BitIterator, Field, PrimeField, SqrtField};
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
use subtle::CtOption;
@ -60,7 +60,7 @@ impl<E: JubjubEngine> Point<E, Unknown> {
rhs.add_assign(&x2);
rhs.sqrt().map(|mut y| {
if y.into_repr().is_odd() != sign {
if y.is_odd() != sign {
y = y.neg();
}
@ -304,7 +304,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
let mut res = Self::zero();
for b in BitIterator::new(scalar.into()) {
for b in BitIterator::<u8, _>::new(scalar.into()) {
res = res.double(params);
if b {

View File

@ -1,6 +1,6 @@
use super::{edwards, montgomery, JubjubEngine, JubjubParams, PrimeOrder};
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
use ff::{Field, PrimeField, SqrtField};
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
use rand_core::{RngCore, SeedableRng};
@ -237,7 +237,7 @@ fn test_get_for<E: JubjubEngine>(params: &E::Params) {
let p = edwards::Point::<E, _>::get_for_y(y, sign, params);
if bool::from(p.is_some()) {
let mut p = p.unwrap();
assert!(p.to_xy().0.into_repr().is_odd() == sign);
assert!(p.to_xy().0.is_odd() == sign);
p = p.negate();
assert!(edwards::Point::<E, _>::get_for_y(y, !sign, params).unwrap() == p);
}
@ -370,32 +370,26 @@ fn test_jubjub_params<E: JubjubEngine>(params: &E::Params) {
// Check that the number of windows per generator
// in the Pedersen hash does not allow for collisions
let mut cur = E::Fs::one().into_repr();
let mut cur = E::Fs::one();
let mut max = E::Fs::char();
{
max.sub_noborrow(&E::Fs::one().into_repr());
max.div2();
}
let max = (-E::Fs::one()) >> 1;
let mut pacc = E::Fs::zero().into_repr();
let mut nacc = E::Fs::char();
let mut pacc = E::Fs::zero();
let mut nacc = E::Fs::zero();
for _ in 0..params.pedersen_hash_chunks_per_generator() {
// tmp = cur * 4
let mut tmp = cur;
tmp.mul2();
tmp.mul2();
let tmp = cur.double().double();
pacc.add_nocarry(&tmp);
nacc.sub_noborrow(&tmp);
pacc += &tmp;
nacc -= &tmp; // The first subtraction wraps intentionally.
assert!(pacc < max);
assert!(pacc < nacc);
// cur = cur * 16
for _ in 0..4 {
cur.mul2();
cur = cur.double();
}
}
}

View File

@ -9,7 +9,7 @@ use crate::{
primitives::{ProofGenerationKey, ViewingKey},
};
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
use ff::{PrimeField, PrimeFieldRepr};
use ff::PrimeField;
use std::io::{self, Read, Write};
pub const PRF_EXPAND_PERSONALIZATION: &[u8; 16] = b"Zcash_ExpandSeed";
@ -71,14 +71,14 @@ impl<E: JubjubEngine> ExpandedSpendingKey<E> {
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
let mut ask_repr = <E::Fs as PrimeField>::Repr::default();
ask_repr.read_le(&mut reader)?;
reader.read_exact(ask_repr.as_mut())?;
let ask = E::Fs::from_repr(ask_repr)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "ask not in field"))?;
let mut nsk_repr = <E::Fs as PrimeField>::Repr::default();
nsk_repr.read_le(&mut reader)?;
reader.read_exact(nsk_repr.as_mut())?;
let nsk = E::Fs::from_repr(nsk_repr)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "nsk not in field"))?;
let mut ovk = [0; 32];
reader.read_exact(&mut ovk)?;
@ -91,8 +91,8 @@ impl<E: JubjubEngine> ExpandedSpendingKey<E> {
}
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
self.ask.into_repr().write_le(&mut writer)?;
self.nsk.into_repr().write_le(&mut writer)?;
writer.write_all(self.ask.into_repr().as_ref())?;
writer.write_all(self.nsk.into_repr().as_ref())?;
writer.write_all(&self.ovk.0)?;
Ok(())

View File

@ -511,9 +511,9 @@ mod tests {
use super::{CommitmentTree, Hashable, IncrementalWitness, MerklePath, PathFiller};
use crate::sapling::Node;
use ff::PrimeFieldRepr;
use hex;
use pairing::bls12_381::FrRepr;
use std::convert::TryInto;
use std::io::{self, Read, Write};
const HEX_EMPTY_ROOTS: [&str; 33] = [
@ -1016,9 +1016,7 @@ mod tests {
let mut paths_i = 0;
let mut witness_ser_i = 0;
for i in 0..16 {
let mut cm = FrRepr::default();
cm.read_le(&hex::decode(commitments[i]).unwrap()[..])
.expect("length is 32 bytes");
let cm = FrRepr(hex::decode(commitments[i]).unwrap()[..].try_into().unwrap());
let cm = Node::new(cm);

View File

@ -11,9 +11,10 @@ use crate::{
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf};
use ff::{PrimeField, PrimeFieldRepr};
use ff::PrimeField;
use pairing::bls12_381::{Bls12, Fr};
use rand_core::{CryptoRng, RngCore};
use std::convert::TryInto;
use std::fmt;
use std::str;
@ -192,7 +193,7 @@ fn prf_ock(
let mut ock_input = [0u8; 128];
ock_input[0..32].copy_from_slice(&ovk.0);
cv.write(&mut ock_input[32..64]).unwrap();
cmu.into_repr().write_le(&mut ock_input[64..96]).unwrap();
ock_input[64..96].copy_from_slice(cmu.into_repr().as_ref());
epk.write(&mut ock_input[96..128]).unwrap();
Blake2bParams::new()
@ -302,11 +303,7 @@ impl SaplingNoteEncryption {
(&mut input[12..20])
.write_u64::<LittleEndian>(self.note.value)
.unwrap();
self.note
.r
.into_repr()
.write_le(&mut input[20..COMPACT_NOTE_SIZE])
.unwrap();
input[20..COMPACT_NOTE_SIZE].copy_from_slice(self.note.r.into_repr().as_ref());
input[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE].copy_from_slice(&self.memo.0);
let mut output = [0u8; ENC_CIPHERTEXT_SIZE];
@ -330,10 +327,7 @@ impl SaplingNoteEncryption {
let mut input = [0u8; OUT_PLAINTEXT_SIZE];
self.note.pk_d.write(&mut input[0..32]).unwrap();
self.esk
.into_repr()
.write_le(&mut input[32..OUT_PLAINTEXT_SIZE])
.unwrap();
input[32..OUT_PLAINTEXT_SIZE].copy_from_slice(self.esk.into_repr().as_ref());
let mut output = [0u8; OUT_CIPHERTEXT_SIZE];
assert_eq!(
@ -363,9 +357,11 @@ fn parse_note_plaintext_without_memo(
let v = (&plaintext[12..20]).read_u64::<LittleEndian>().ok()?;
let mut rcm = FsRepr::default();
rcm.read_le(&plaintext[20..COMPACT_NOTE_SIZE]).ok()?;
let rcm = Fs::from_repr(rcm).ok()?;
let rcm = Fs::from_repr(FsRepr(
plaintext[20..COMPACT_NOTE_SIZE]
.try_into()
.expect("slice is the correct length"),
))?;
let diversifier = Diversifier(d);
let pk_d = diversifier
@ -483,9 +479,11 @@ pub fn try_sapling_output_recovery(
.ok()?
.as_prime_order(&JUBJUB)?;
let mut esk = FsRepr::default();
esk.read_le(&op[32..OUT_PLAINTEXT_SIZE]).ok()?;
let esk = Fs::from_repr(esk).ok()?;
let esk = Fs::from_repr(FsRepr(
op[32..OUT_PLAINTEXT_SIZE]
.try_into()
.expect("slice is the correct length"),
))?;
let shared_secret = sapling_ka_agree(&esk, &pk_d);
let key = kdf_sapling(shared_secret, &epk);
@ -515,9 +513,11 @@ pub fn try_sapling_output_recovery(
let v = (&plaintext[12..20]).read_u64::<LittleEndian>().ok()?;
let mut rcm = FsRepr::default();
rcm.read_le(&plaintext[20..COMPACT_NOTE_SIZE]).ok()?;
let rcm = Fs::from_repr(rcm).ok()?;
let rcm = Fs::from_repr(FsRepr(
plaintext[20..COMPACT_NOTE_SIZE]
.try_into()
.expect("slice is the correct length"),
))?;
let mut memo = [0u8; 512];
memo.copy_from_slice(&plaintext[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]);
@ -554,10 +554,11 @@ mod tests {
primitives::{Diversifier, PaymentAddress, ValueCommitment},
};
use crypto_api_chachapoly::ChachaPolyIetf;
use ff::{Field, PrimeField, PrimeFieldRepr};
use ff::{Field, PrimeField};
use pairing::bls12_381::{Bls12, Fr, FrRepr};
use rand_core::OsRng;
use rand_core::{CryptoRng, RngCore};
use std::convert::TryInto;
use std::str::FromStr;
use super::{
@ -791,9 +792,7 @@ mod tests {
.as_prime_order(&JUBJUB)
.unwrap();
let mut esk = FsRepr::default();
esk.read_le(&op[32..OUT_PLAINTEXT_SIZE]).unwrap();
let esk = Fs::from_repr(esk).unwrap();
let esk = Fs::from_repr(FsRepr(op[32..OUT_PLAINTEXT_SIZE].try_into().unwrap())).unwrap();
let shared_secret = sapling_ka_agree(&esk, &pk_d);
let key = kdf_sapling(shared_secret, &epk);
@ -1292,17 +1291,13 @@ mod tests {
macro_rules! read_fr {
($field:expr) => {{
let mut repr = FrRepr::default();
repr.read_le(&$field[..]).unwrap();
Fr::from_repr(repr).unwrap()
Fr::from_repr(FrRepr($field[..].try_into().unwrap())).unwrap()
}};
}
macro_rules! read_fs {
($field:expr) => {{
let mut repr = FsRepr::default();
repr.read_le(&$field[..]).unwrap();
Fs::from_repr(repr).unwrap()
Fs::from_repr(FsRepr($field[..].try_into().unwrap())).unwrap()
}};
}

View File

@ -1,7 +1,7 @@
//! Implementation of the Pedersen hash function used in Sapling.
use crate::jubjub::*;
use ff::{Field, PrimeField, PrimeFieldRepr};
use ff::Field;
use std::ops::{AddAssign, Neg};
#[derive(Copy, Clone)]
@ -88,16 +88,14 @@ where
let window = JubjubBls12::pedersen_hash_exp_window_size();
let window_mask = (1 << window) - 1;
let mut acc = acc.into_repr();
let mut tmp = edwards::Point::zero();
while !acc.is_zero() {
let i = (acc.as_ref()[0] & window_mask) as usize;
let i = (acc & window_mask) as usize;
tmp = tmp.add(&table[0][i], params);
acc.shr(window);
acc = acc >> window;
table = &table[1..];
}

View File

@ -1,6 +1,6 @@
//! Structs for core Zcash primitives.
use ff::{Field, PrimeField, PrimeFieldRepr};
use ff::{Field, PrimeField};
use crate::constants;
@ -24,7 +24,7 @@ impl<E: JubjubEngine> ValueCommitment<E> {
pub fn cm(&self, params: &E::Params) -> edwards::Point<E, PrimeOrder> {
params
.generator(FixedGenerators::ValueCommitmentValue)
.mul(self.value, params)
.mul(E::Fs::from(self.value), params)
.add(
&params
.generator(FixedGenerators::ValueCommitmentRandomness)
@ -86,7 +86,7 @@ impl<E: JubjubEngine> ViewingKey<E> {
h[31] &= 0b0000_0111;
let mut e = <E::Fs as PrimeField>::Repr::default();
e.read_le(&h[..]).unwrap();
e.as_mut().copy_from_slice(&h[..]);
E::Fs::from_repr(e).expect("should be a valid scalar")
}
@ -291,7 +291,7 @@ impl<E: JubjubEngine> Note<E> {
let rho = self.cm_full_point(params).add(
&params
.generator(FixedGenerators::NullifierPosition)
.mul(position, params),
.mul(E::Fs::from(position), params),
params,
);

View File

@ -4,23 +4,23 @@
//! [RedJubjub]: https://zips.z.cash/protocol/protocol.pdf#concretereddsa
use crate::jubjub::{edwards::Point, FixedGenerators, JubjubEngine, JubjubParams, Unknown};
use ff::{Field, PrimeField, PrimeFieldRepr};
use ff::{Field, PrimeField};
use rand_core::RngCore;
use std::io::{self, Read, Write};
use std::ops::{AddAssign, MulAssign, Neg};
use crate::util::hash_to_scalar;
fn read_scalar<E: JubjubEngine, R: Read>(reader: R) -> io::Result<E::Fs> {
fn read_scalar<E: JubjubEngine, R: Read>(mut reader: R) -> io::Result<E::Fs> {
let mut s_repr = <E::Fs as PrimeField>::Repr::default();
s_repr.read_le(reader)?;
reader.read_exact(s_repr.as_mut())?;
E::Fs::from_repr(s_repr)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "scalar is not in field"))
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "scalar is not in field"))
}
fn write_scalar<E: JubjubEngine, W: Write>(s: &E::Fs, writer: W) -> io::Result<()> {
s.into_repr().write_le(writer)
fn write_scalar<E: JubjubEngine, W: Write>(s: &E::Fs, mut writer: W) -> io::Result<()> {
writer.write_all(s.into_repr().as_ref())
}
fn h_star<E: JubjubEngine>(a: &[u8], b: &[u8]) -> E::Fs {

View File

@ -5,7 +5,7 @@ use crate::{
pedersen_hash::{pedersen_hash, Personalization},
primitives::Note,
};
use ff::{BitIterator, PrimeField, PrimeFieldRepr};
use ff::{BitIterator, PrimeField};
use lazy_static::lazy_static;
use pairing::bls12_381::{Bls12, Fr, FrRepr};
use rand_core::{CryptoRng, RngCore};
@ -21,7 +21,7 @@ pub const SAPLING_COMMITMENT_TREE_DEPTH: usize = 32;
pub fn merkle_hash(depth: usize, lhs: &FrRepr, rhs: &FrRepr) -> FrRepr {
let lhs = {
let mut tmp = [false; 256];
for (a, b) in tmp.iter_mut().rev().zip(BitIterator::new(lhs)) {
for (a, b) in tmp.iter_mut().rev().zip(BitIterator::<u8, _>::new(lhs)) {
*a = b;
}
tmp
@ -29,7 +29,7 @@ pub fn merkle_hash(depth: usize, lhs: &FrRepr, rhs: &FrRepr) -> FrRepr {
let rhs = {
let mut tmp = [false; 256];
for (a, b) in tmp.iter_mut().rev().zip(BitIterator::new(rhs)) {
for (a, b) in tmp.iter_mut().rev().zip(BitIterator::<u8, _>::new(rhs)) {
*a = b;
}
tmp
@ -62,13 +62,13 @@ impl Node {
impl Hashable for Node {
fn read<R: Read>(mut reader: R) -> io::Result<Self> {
let mut repr = FrRepr::default();
repr.read_le(&mut reader)?;
let mut repr = FrRepr([0; 32]);
reader.read_exact(&mut repr.0)?;
Ok(Node::new(repr))
}
fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
self.repr.write_le(&mut writer)
writer.write_all(self.repr.as_ref())
}
fn combine(depth: usize, lhs: &Self, rhs: &Self) -> Self {

View File

@ -2,7 +2,7 @@
use crate::jubjub::{edwards, Unknown};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use ff::{PrimeField, PrimeFieldRepr};
use ff::PrimeField;
use pairing::bls12_381::{Bls12, Fr, FrRepr};
use std::io::{self, Read, Write};
@ -138,9 +138,10 @@ impl SpendDescription {
// Consensus rule (§7.3): Canonical encoding is enforced here
let anchor = {
let mut f = FrRepr::default();
f.read_le(&mut reader)?;
Fr::from_repr(f).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?
let mut f = FrRepr([0; 32]);
reader.read_exact(&mut f.0)?;
Fr::from_repr(f)
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "anchor not in field"))?
};
let mut nullifier = [0; 32];
@ -175,7 +176,7 @@ impl SpendDescription {
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
self.cv.write(&mut writer)?;
self.anchor.into_repr().write_le(&mut writer)?;
writer.write_all(self.anchor.into_repr().as_ref())?;
writer.write_all(&self.nullifier)?;
self.rk.write(&mut writer)?;
writer.write_all(&self.zkproof)?;
@ -218,9 +219,10 @@ impl OutputDescription {
// Consensus rule (§7.4): Canonical encoding is enforced here
let cmu = {
let mut f = FrRepr::default();
f.read_le(&mut reader)?;
Fr::from_repr(f).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?
let mut f = FrRepr([0; 32]);
reader.read_exact(&mut f.0)?;
Fr::from_repr(f)
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "cmu not in field"))?
};
// Consensus rules (§4.5):
@ -252,7 +254,7 @@ impl OutputDescription {
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
self.cv.write(&mut writer)?;
self.cmu.into_repr().write_le(&mut writer)?;
writer.write_all(self.cmu.into_repr().as_ref())?;
self.ephemeral_key.write(&mut writer)?;
writer.write_all(&self.enc_ciphertext)?;
writer.write_all(&self.out_ciphertext)?;

View File

@ -1,6 +1,6 @@
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
use byteorder::{LittleEndian, WriteBytesExt};
use ff::{PrimeField, PrimeFieldRepr};
use ff::PrimeField;
use super::{
components::{Amount, TxOut},
@ -128,7 +128,7 @@ fn shielded_spends_hash(tx: &TransactionData) -> Blake2bHash {
let mut data = Vec::with_capacity(tx.shielded_spends.len() * 384);
for s_spend in &tx.shielded_spends {
s_spend.cv.write(&mut data).unwrap();
s_spend.anchor.into_repr().write_le(&mut data).unwrap();
data.extend_from_slice(s_spend.anchor.into_repr().as_ref());
data.extend_from_slice(&s_spend.nullifier);
s_spend.rk.write(&mut data).unwrap();
data.extend_from_slice(&s_spend.zkproof);

View File

@ -453,7 +453,7 @@ impl ExtendedFullViewingKey {
mod tests {
use super::*;
use ff::{PrimeField, PrimeFieldRepr};
use ff::PrimeField;
#[test]
fn derive_nonhardened_child() {
@ -1014,11 +1014,8 @@ mod tests {
let xsk = &xsks[j];
let tv = &test_vectors[j];
let mut buf = [0; 32];
xsk.expsk.ask.into_repr().write_le(&mut buf[..]).unwrap();
assert_eq!(buf, tv.ask.unwrap());
xsk.expsk.nsk.into_repr().write_le(&mut buf[..]).unwrap();
assert_eq!(buf, tv.nsk.unwrap());
assert_eq!(xsk.expsk.ask.into_repr().as_ref(), tv.ask.unwrap());
assert_eq!(xsk.expsk.nsk.into_repr().as_ref(), tv.nsk.unwrap());
assert_eq!(xsk.expsk.ovk.0, tv.ovk);
assert_eq!(xsk.dk.0, tv.dk);
@ -1043,13 +1040,7 @@ mod tests {
assert_eq!(xfvk.dk.0, tv.dk);
assert_eq!(xfvk.chain_code.0, tv.c);
xfvk.fvk
.vk
.ivk()
.into_repr()
.write_le(&mut buf[..])
.unwrap();
assert_eq!(buf, tv.ivk);
assert_eq!(xfvk.fvk.vk.ivk().into_repr().as_ref(), tv.ivk);
let mut ser = vec![];
xfvk.write(&mut ser).unwrap();

View File

@ -769,7 +769,7 @@ mod test {
let q = p.mul(s, params);
let (x1, y1) = q.to_xy();
let mut s_bits = BitIterator::new(s.into_repr()).collect::<Vec<_>>();
let mut s_bits = BitIterator::<u8, _>::new(s.into_repr()).collect::<Vec<_>>();
s_bits.reverse();
s_bits.truncate(Fs::NUM_BITS as usize);
@ -822,7 +822,7 @@ mod test {
y: num_y0,
};
let mut s_bits = BitIterator::new(s.into_repr()).collect::<Vec<_>>();
let mut s_bits = BitIterator::<u8, _>::new(s.into_repr()).collect::<Vec<_>>();
s_bits.reverse();
s_bits.truncate(Fs::NUM_BITS as usize);

View File

@ -1,6 +1,6 @@
//! The Sapling circuits.
use ff::{Field, PrimeField, PrimeFieldRepr};
use ff::{Field, PrimeField};
use bellman::{Circuit, ConstraintSystem, SynthesisError};
@ -478,7 +478,7 @@ impl<'a, E: JubjubEngine> Circuit<E> for Output<'a, E> {
// Witness the sign bit
let sign_bit = boolean::Boolean::from(boolean::AllocatedBit::alloc(
cs.namespace(|| "pk_d bit of x"),
pk_d.map(|e| e.0.into_repr().is_odd()),
pk_d.map(|e| e.0.is_odd()),
)?);
// Extend the note with pk_d representation
@ -615,8 +615,8 @@ fn test_input_circuit_with_bls12_381() {
::std::mem::swap(&mut lhs, &mut rhs);
}
let mut lhs: Vec<bool> = BitIterator::new(lhs.into_repr()).collect();
let mut rhs: Vec<bool> = BitIterator::new(rhs.into_repr()).collect();
let mut lhs: Vec<bool> = BitIterator::<u8, _>::new(lhs.into_repr()).collect();
let mut rhs: Vec<bool> = BitIterator::<u8, _>::new(rhs.into_repr()).collect();
lhs.reverse();
rhs.reverse();
@ -799,8 +799,8 @@ fn test_input_circuit_with_bls12_381_external_test_vectors() {
::std::mem::swap(&mut lhs, &mut rhs);
}
let mut lhs: Vec<bool> = BitIterator::new(lhs.into_repr()).collect();
let mut rhs: Vec<bool> = BitIterator::new(rhs.into_repr()).collect();
let mut lhs: Vec<bool> = BitIterator::<u8, _>::new(lhs.into_repr()).collect();
let mut rhs: Vec<bool> = BitIterator::<u8, _>::new(rhs.into_repr()).collect();
lhs.reverse();
rhs.reverse();

View File

@ -2,7 +2,7 @@
use pairing::bls12_381::Bls12;
use zcash_primitives::jubjub::{
edwards, fs::FsRepr, FixedGenerators, JubjubBls12, JubjubParams, Unknown,
edwards, fs::Fs, FixedGenerators, JubjubBls12, JubjubParams, Unknown,
};
use zcash_primitives::transaction::components::Amount;
@ -30,7 +30,7 @@ fn compute_value_balance(
// Compute it in the exponent
let mut value_balance = params
.generator(FixedGenerators::ValueCommitmentValue)
.mul(FsRepr::from(abs), params);
.mul(Fs::from(abs), params);
// Negate if necessary
if is_negative {