ff: Remove PrimeFieldRepr trait

The ff::PrimeField::Repr associated type now has the minimal necessary
bounds, which can be satisfied by a newtype around a byte array.
This commit is contained in:
Jack Grigg 2020-04-23 17:32:04 +12:00
parent 1fe3e3784c
commit 49f119fb03
35 changed files with 1705 additions and 3634 deletions

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::<u64, _>::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::<u64, _>::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,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,11 +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::<u64, _>::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![];
@ -117,7 +114,7 @@ impl<E: ScalarEngine> AllocatedNum<E> {
let mut found_one = false;
let mut i = 0;
for b in BitIterator::<u64, _>::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
@ -560,7 +557,7 @@ mod test {
assert!(cs.is_satisfied());
for (b, a) in BitIterator::<u64, _>::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, PowVartime, 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

@ -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,6 +1,4 @@
use ff::{
Field, PowVartime, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, SqrtField,
};
use ff::{Field, PowVartime, PrimeField, ScalarEngine, SqrtField};
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
use pairing::{Engine, PairingCurveAffine};
@ -259,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])
}
}
@ -349,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)))
}
}
@ -464,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,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(

View File

@ -8,19 +8,105 @@ use num_integer::Integer;
use num_traits::{One, ToPrimitive, Zero};
use quote::quote;
use quote::TokenStreamExt;
use std::iter;
use std::str::FromStr;
mod pow_fixed;
#[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus, PrimeFieldGenerator))]
enum ReprEndianness {
Big,
Little,
}
impl FromStr for ReprEndianness {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"big" => Ok(ReprEndianness::Big),
"little" => Ok(ReprEndianness::Little),
_ => Err(()),
}
}
}
impl ReprEndianness {
fn from_repr(&self, name: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream {
let read_repr = match self {
ReprEndianness::Big => quote! {
::byteorder::BigEndian::read_u64_into(r.as_ref(), &mut inner[..]);
inner.reverse();
},
ReprEndianness::Little => quote! {
::byteorder::LittleEndian::read_u64_into(r.as_ref(), &mut inner[..]);
},
};
quote! {
use ::byteorder::ByteOrder;
let r = {
let mut inner = [0u64; #limbs];
#read_repr
#name(inner)
};
if r.is_valid() {
Some(r * R2)
} else {
None
}
}
}
fn into_repr(
&self,
repr: &syn::Ident,
mont_reduce_self_params: &proc_macro2::TokenStream,
limbs: usize,
) -> proc_macro2::TokenStream {
let bytes = limbs * 8;
let write_repr = match self {
ReprEndianness::Big => quote! {
r.0.reverse();
::byteorder::BigEndian::write_u64_into(&r.0, &mut repr[..]);
},
ReprEndianness::Little => quote! {
::byteorder::LittleEndian::write_u64_into(&r.0, &mut repr[..]);
},
};
quote! {
use ::byteorder::ByteOrder;
let mut r = *self;
r.mont_reduce(
#mont_reduce_self_params
);
let mut repr = [0u8; #bytes];
#write_repr
#repr(repr)
}
}
fn iter_be(&self) -> proc_macro2::TokenStream {
match self {
ReprEndianness::Big => quote! {self.0.iter()},
ReprEndianness::Little => quote! {self.0.iter().rev()},
}
}
}
#[proc_macro_derive(
PrimeField,
attributes(PrimeFieldModulus, PrimeFieldGenerator, PrimeFieldReprEndianness)
)]
pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
// Parse the type definition
let ast: syn::DeriveInput = syn::parse(input).unwrap();
// The struct we're deriving for is a wrapper around a "Repr" type we must construct.
let repr_ident = fetch_wrapped_ident(&ast.data)
.expect("PrimeField derive only operates over tuple structs of a single item");
// We're given the modulus p of the prime field
let modulus: BigUint = fetch_attr("PrimeFieldModulus", &ast.attrs)
.expect("Please supply a PrimeFieldModulus attribute")
@ -29,11 +115,18 @@ pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
// We may be provided with a generator of p - 1 order. It is required that this generator be quadratic
// nonresidue.
// TODO: Compute this ourselves.
let generator: BigUint = fetch_attr("PrimeFieldGenerator", &ast.attrs)
.expect("Please supply a PrimeFieldGenerator attribute")
.parse()
.expect("PrimeFieldGenerator should be a number");
// Field element representations may be in little-endian or big-endian.
let endianness = fetch_attr("PrimeFieldReprEndianness", &ast.attrs)
.expect("Please supply a PrimeFieldReprEndianness attribute")
.parse()
.expect("PrimeFieldReprEndianness should be 'big' or 'little'");
// The arithmetic in this library only works if the modulus*2 is smaller than the backing
// representation. Compute the number of limbs we need.
let mut limbs = 1;
@ -46,34 +139,146 @@ pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
}
}
// The struct we're deriving for must be a wrapper around `pub [u64; limbs]`.
if let Some(err) = validate_struct(&ast, limbs) {
return err.into();
}
// Generate the identifier for the "Repr" type we must construct.
let repr_ident = syn::Ident::new(
&format!("{}Repr", ast.ident),
proc_macro2::Span::call_site(),
);
let mut gen = proc_macro2::TokenStream::new();
let (constants_impl, sqrt_impl) =
prime_field_constants_and_sqrt(&ast.ident, &repr_ident, &modulus, limbs, generator);
gen.extend(constants_impl);
gen.extend(prime_field_repr_impl(&repr_ident, limbs));
gen.extend(prime_field_impl(&ast.ident, &repr_ident, &modulus, limbs));
gen.extend(prime_field_repr_impl(&repr_ident, &endianness, limbs * 8));
gen.extend(prime_field_impl(
&ast.ident,
&repr_ident,
&modulus,
&endianness,
limbs,
));
gen.extend(sqrt_impl);
// Return the generated impl
gen.into()
}
/// Fetches the ident being wrapped by the type we're deriving.
fn fetch_wrapped_ident(body: &syn::Data) -> Option<syn::Ident> {
if let syn::Data::Struct(ref variant_data) = body {
if let syn::Fields::Unnamed(ref fields) = variant_data.fields {
if fields.unnamed.len() == 1 {
if let syn::Type::Path(ref path) = fields.unnamed[0].ty {
if path.path.segments.len() == 1 {
return Some(path.path.segments[0].ident.clone());
}
}
}
/// Checks that `body` contains `pub [u64; limbs]`.
fn validate_struct(ast: &syn::DeriveInput, limbs: usize) -> Option<proc_macro2::TokenStream> {
// The body should be a struct.
let variant_data = match &ast.data {
syn::Data::Struct(x) => x,
_ => {
return Some(
syn::Error::new_spanned(ast, "PrimeField derive only works for structs.")
.to_compile_error(),
)
}
};
// The struct should contain a single unnamed field.
let fields = match &variant_data.fields {
syn::Fields::Unnamed(x) if x.unnamed.len() == 1 => x,
_ => {
return Some(
syn::Error::new_spanned(
&ast.ident,
format!(
"The struct must contain an array of limbs. Change this to `{}([u64; {}])`",
ast.ident, limbs,
),
)
.to_compile_error(),
)
}
};
let field = &fields.unnamed[0];
// The field should be an array.
let arr = match &field.ty {
syn::Type::Array(x) => x,
_ => {
return Some(
syn::Error::new_spanned(
field,
format!(
"The inner field must be an array of limbs. Change this to `[u64; {}]`",
limbs,
),
)
.to_compile_error(),
)
}
};
// The array's element type should be `u64`.
if match arr.elem.as_ref() {
syn::Type::Path(path) => path
.path
.get_ident()
.map(|x| x.to_string() != "u64")
.unwrap_or(true),
_ => true,
} {
return Some(
syn::Error::new_spanned(
arr,
format!(
"PrimeField derive requires 64-bit limbs. Change this to `[u64; {}]",
limbs
),
)
.to_compile_error(),
);
}
// The array's length should be a literal int equal to `limbs`.
let lit_int = match match &arr.len {
syn::Expr::Lit(expr_lit) => match &expr_lit.lit {
syn::Lit::Int(lit_int) => Some(lit_int),
_ => None,
},
_ => None,
} {
Some(x) => x,
_ => {
return Some(
syn::Error::new_spanned(
arr,
format!("To derive PrimeField, change this to `[u64; {}]`.", limbs),
)
.to_compile_error(),
)
}
};
if lit_int.base10_digits() != limbs.to_string() {
return Some(
syn::Error::new_spanned(
lit_int,
format!("The given modulus requires {} limbs.", limbs),
)
.to_compile_error(),
);
}
// The field should not be public.
match &field.vis {
syn::Visibility::Inherited => (),
_ => {
return Some(
syn::Error::new_spanned(&field.vis, "Field must not be public.").to_compile_error(),
)
}
}
// Valid!
None
}
@ -102,18 +307,49 @@ fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> {
None
}
// Implement PrimeFieldRepr for the wrapped ident `repr` with `limbs` limbs.
fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream {
// Implement the wrapped ident `repr` with `bytes` bytes.
fn prime_field_repr_impl(
repr: &syn::Ident,
endianness: &ReprEndianness,
bytes: usize,
) -> proc_macro2::TokenStream {
let repr_iter_be = endianness.iter_be();
quote! {
#[derive(Copy, Clone, PartialEq, Eq, Default)]
pub struct #repr(pub [u64; #limbs]);
#[derive(Copy, Clone)]
pub struct #repr(pub [u8; #bytes]);
impl ::subtle::ConstantTimeEq for #repr {
fn ct_eq(&self, other: &#repr) -> ::subtle::Choice {
self.0
.iter()
.zip(other.0.iter())
.map(|(a, b)| a.ct_eq(b))
.fold(1.into(), |acc, x| acc & x)
}
}
impl ::core::cmp::PartialEq for #repr {
fn eq(&self, other: &#repr) -> bool {
use ::subtle::ConstantTimeEq;
self.ct_eq(other).into()
}
}
impl ::core::cmp::Eq for #repr { }
impl ::core::default::Default for #repr {
fn default() -> #repr {
#repr([0u8; #bytes])
}
}
impl ::core::fmt::Debug for #repr
{
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "0x")?;
for i in self.0.iter().rev() {
write!(f, "{:016x}", *i)?;
for i in #repr_iter_be {
write!(f, "{:02x}", *i)?;
}
Ok(())
@ -123,183 +359,27 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS
impl ::core::fmt::Display for #repr {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "0x")?;
for i in self.0.iter().rev() {
write!(f, "{:016x}", *i)?;
for i in #repr_iter_be {
write!(f, "{:02x}", *i)?;
}
Ok(())
}
}
impl AsRef<[u64]> for #repr {
impl AsRef<[u8]> for #repr {
#[inline(always)]
fn as_ref(&self) -> &[u64] {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsMut<[u64]> for #repr {
impl AsMut<[u8]> for #repr {
#[inline(always)]
fn as_mut(&mut self) -> &mut [u64] {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl From<u64> for #repr {
#[inline(always)]
fn from(val: u64) -> #repr {
use core::default::Default;
let mut repr = Self::default();
repr.0[0] = val;
repr
}
}
impl Ord for #repr {
#[inline(always)]
fn cmp(&self, other: &#repr) -> ::core::cmp::Ordering {
for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
if a < b {
return ::core::cmp::Ordering::Less
} else if a > b {
return ::core::cmp::Ordering::Greater
}
}
::core::cmp::Ordering::Equal
}
}
impl PartialOrd for #repr {
#[inline(always)]
fn partial_cmp(&self, other: &#repr) -> Option<::core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl ::ff::PrimeFieldRepr for #repr {
#[inline(always)]
fn is_odd(&self) -> bool {
self.0[0] & 1 == 1
}
#[inline(always)]
fn is_even(&self) -> bool {
!self.is_odd()
}
#[inline(always)]
fn is_zero(&self) -> bool {
self.0.iter().all(|&e| e == 0)
}
#[inline(always)]
fn shr(&mut self, mut n: u32) {
if n as usize >= 64 * #limbs {
*self = Self::from(0);
return;
}
while n >= 64 {
let mut t = 0;
for i in self.0.iter_mut().rev() {
::core::mem::swap(&mut t, i);
}
n -= 64;
}
if n > 0 {
let mut t = 0;
for i in self.0.iter_mut().rev() {
let t2 = *i << (64 - n);
*i >>= n;
*i |= t;
t = t2;
}
}
}
#[inline(always)]
fn div2(&mut self) {
let mut t = 0;
for i in self.0.iter_mut().rev() {
let t2 = *i << 63;
*i >>= 1;
*i |= t;
t = t2;
}
}
#[inline(always)]
fn mul2(&mut self) {
let mut last = 0;
for i in &mut self.0 {
let tmp = *i >> 63;
*i <<= 1;
*i |= last;
last = tmp;
}
}
#[inline(always)]
fn shl(&mut self, mut n: u32) {
if n as usize >= 64 * #limbs {
*self = Self::from(0);
return;
}
while n >= 64 {
let mut t = 0;
for i in &mut self.0 {
::core::mem::swap(&mut t, i);
}
n -= 64;
}
if n > 0 {
let mut t = 0;
for i in &mut self.0 {
let t2 = *i >> (64 - n);
*i <<= n;
*i |= t;
t = t2;
}
}
}
#[inline(always)]
fn num_bits(&self) -> u32 {
let mut ret = (#limbs as u32) * 64;
for i in self.0.iter().rev() {
let leading = i.leading_zeros();
ret -= leading;
if leading != 64 {
break;
}
}
ret
}
#[inline(always)]
fn add_nocarry(&mut self, other: &#repr) {
let mut carry = 0;
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
*a = ::ff::adc(*a, *b, &mut carry);
}
}
#[inline(always)]
fn sub_noborrow(&mut self, other: &#repr) {
let mut borrow = 0;
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
*a = ::ff::sbb(*a, *b, &mut borrow);
}
}
}
}
}
@ -455,7 +535,7 @@ fn prime_field_constants_and_sqrt(
let mut b = x * &w;
// Initialize z as the 2^S root of unity.
let mut z = #name(ROOT_OF_UNITY);
let mut z = ROOT_OF_UNITY;
for max_v in (1..=S).rev() {
let mut k = 1;
@ -494,6 +574,11 @@ fn prime_field_constants_and_sqrt(
let r2 = biguint_to_u64_vec((&r * &r) % modulus, limbs);
let r = biguint_to_u64_vec(r, limbs);
let modulus_repr = {
let mut buf = modulus.to_bytes_le();
buf.extend(iter::repeat(0).take((limbs * 8) - buf.len()));
buf
};
let modulus = biguint_to_real_u64_vec(modulus.clone(), limbs);
// Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1
@ -507,7 +592,10 @@ fn prime_field_constants_and_sqrt(
(
quote! {
/// This is the modulus m of the prime field
const MODULUS: #repr = #repr([#(#modulus,)*]);
const MODULUS: #repr = #repr([#(#modulus_repr,)*]);
/// This is the modulus m of the prime field in limb form
const MODULUS_LIMBS: #name = #name([#(#modulus,)*]);
/// The number of bits needed to represent the modulus.
const MODULUS_BITS: u32 = #modulus_num_bits;
@ -517,23 +605,23 @@ fn prime_field_constants_and_sqrt(
const REPR_SHAVE_BITS: u32 = #repr_shave_bits;
/// 2^{limbs*64} mod m
const R: #repr = #repr(#r);
const R: #name = #name(#r);
/// 2^{limbs*64*2} mod m
const R2: #repr = #repr(#r2);
const R2: #name = #name(#r2);
/// -(m^{-1} mod m) mod m
const INV: u64 = #inv;
/// Multiplicative generator of `MODULUS` - 1 order, also quadratic
/// nonresidue.
const GENERATOR: #repr = #repr(#generator);
const GENERATOR: #name = #name(#generator);
/// 2^s * t = MODULUS - 1 with t odd
const S: u32 = #s;
/// 2^s root of unity computed by GENERATOR^t
const ROOT_OF_UNITY: #repr = #repr(#root_of_unity);
const ROOT_OF_UNITY: #name = #name(#root_of_unity);
},
sqrt_impl,
)
@ -544,6 +632,7 @@ fn prime_field_impl(
name: &syn::Ident,
repr: &syn::Ident,
modulus: &BigUint,
endianness: &ReprEndianness,
limbs: usize,
) -> proc_macro2::TokenStream {
// Returns r{n} as an ident.
@ -575,14 +664,14 @@ fn prime_field_impl(
gen.extend(quote! {
let k = #temp.wrapping_mul(INV);
let mut carry = 0;
::ff::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry);
::ff::mac_with_carry(#temp, k, MODULUS_LIMBS.0[0], &mut carry);
});
}
for j in 1..limbs {
let temp = get_temp(i + j);
gen.extend(quote! {
#temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry);
#temp = ::ff::mac_with_carry(#temp, k, MODULUS_LIMBS.0[#j], &mut carry);
});
}
@ -609,7 +698,7 @@ fn prime_field_impl(
let temp = get_temp(limbs + i);
gen.extend(quote! {
(self.0).0[#i] = #temp;
self.0[#i] = #temp;
});
}
@ -628,11 +717,11 @@ fn prime_field_impl(
let temp = get_temp(i + j);
if i == 0 {
gen.extend(quote! {
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#j], &mut carry);
let #temp = ::ff::mac_with_carry(0, #a.0[#i], #a.0[#j], &mut carry);
});
} else {
gen.extend(quote!{
let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#a.0).0[#j], &mut carry);
gen.extend(quote! {
let #temp = ::ff::mac_with_carry(#temp, #a.0[#i], #a.0[#j], &mut carry);
});
}
}
@ -672,11 +761,11 @@ fn prime_field_impl(
let temp1 = get_temp(i * 2 + 1);
if i == 0 {
gen.extend(quote! {
let #temp0 = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#i], &mut carry);
let #temp0 = ::ff::mac_with_carry(0, #a.0[#i], #a.0[#i], &mut carry);
});
} else {
gen.extend(quote!{
let #temp0 = ::ff::mac_with_carry(#temp0, (#a.0).0[#i], (#a.0).0[#i], &mut carry);
gen.extend(quote! {
let #temp0 = ::ff::mac_with_carry(#temp0, #a.0[#i], #a.0[#i], &mut carry);
});
}
@ -717,11 +806,11 @@ fn prime_field_impl(
if i == 0 {
gen.extend(quote! {
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
let #temp = ::ff::mac_with_carry(0, #a.0[#i], #b.0[#j], &mut carry);
});
} else {
gen.extend(quote!{
let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
gen.extend(quote! {
let #temp = ::ff::mac_with_carry(#temp, #a.0[#i], #b.0[#j], &mut carry);
});
}
}
@ -778,10 +867,10 @@ fn prime_field_impl(
let invert_impl = inv_impl(quote! {self}, name, modulus);
let montgomery_impl = mont_impl(limbs);
// (self.0).0[0].ct_eq(&(other.0).0[0]) & (self.0).0[1].ct_eq(&(other.0).0[1]) & ...
// self.0[0].ct_eq(&other.0[0]) & self.0[1].ct_eq(&other.0[1]) & ...
let mut ct_eq_impl = proc_macro2::TokenStream::new();
ct_eq_impl.append_separated(
(0..limbs).map(|i| quote! { (self.0).0[#i].ct_eq(&(other.0).0[#i]) }),
(0..limbs).map(|i| quote! { self.0[#i].ct_eq(&other.0[#i]) }),
proc_macro2::Punct::new('&', proc_macro2::Spacing::Alone),
);
@ -790,7 +879,7 @@ fn prime_field_impl(
let mut mont_reduce_params = proc_macro2::TokenStream::new();
mont_reduce_params.append_separated(
(0..limbs)
.map(|i| quote! { (#a.0).0[#i] })
.map(|i| quote! { #a.0[#i] })
.chain((0..limbs).map(|_| quote! {0})),
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
);
@ -798,6 +887,10 @@ fn prime_field_impl(
}
let mont_reduce_self_params = mont_reduce_params(quote! {self}, limbs);
let mont_reduce_other_params = mont_reduce_params(quote! {other}, limbs);
let from_repr_impl = endianness.from_repr(name, limbs);
let into_repr_impl = endianness.into_repr(repr, &mont_reduce_self_params, limbs);
let top_limb_index = limbs - 1;
@ -818,13 +911,14 @@ fn prime_field_impl(
impl ::subtle::ConstantTimeEq for #name {
fn ct_eq(&self, other: &#name) -> ::subtle::Choice {
#ct_eq_impl
self.into_repr().ct_eq(&other.into_repr())
}
}
impl ::core::cmp::PartialEq for #name {
fn eq(&self, other: &#name) -> bool {
self.0 == other.0
use ::subtle::ConstantTimeEq;
self.ct_eq(other).into()
}
}
@ -841,7 +935,17 @@ fn prime_field_impl(
impl Ord for #name {
#[inline(always)]
fn cmp(&self, other: &#name) -> ::core::cmp::Ordering {
self.into_repr().cmp(&other.into_repr())
let mut a = *self;
a.mont_reduce(
#mont_reduce_self_params
);
let mut b = *other;
b.mont_reduce(
#mont_reduce_other_params
);
a.cmp_native(&b)
}
}
@ -863,7 +967,7 @@ fn prime_field_impl(
fn from(val: u64) -> #name {
let mut raw = [0u64; #limbs];
raw[0] = val;
#name(#repr(raw)) * #name(R2)
#name(raw) * R2
}
}
@ -873,13 +977,19 @@ fn prime_field_impl(
}
}
impl<'a> From<&'a #name> for #repr {
fn from(e: &'a #name) -> #repr {
e.into_repr()
}
}
impl ::subtle::ConditionallySelectable for #name {
fn conditional_select(a: &#name, b: &#name, choice: ::subtle::Choice) -> #name {
let mut res = [0u64; #limbs];
for i in 0..#limbs {
res[i] = u64::conditional_select(&(a.0).0[i], &(b.0).0[i], choice);
res[i] = u64::conditional_select(&a.0[i], &b.0[i], choice);
}
#name(#repr(res))
#name(res)
}
}
@ -890,9 +1000,9 @@ fn prime_field_impl(
fn neg(self) -> #name {
let mut ret = self;
if !ret.is_zero() {
let mut tmp = MODULUS;
tmp.sub_noborrow(&ret.0);
ret.0 = tmp;
let mut tmp = MODULUS_LIMBS;
tmp.sub_noborrow(&ret);
ret = tmp;
}
ret
}
@ -922,7 +1032,7 @@ fn prime_field_impl(
#[inline]
fn add_assign(&mut self, other: &#name) {
// This cannot exceed the backing capacity.
self.0.add_nocarry(&other.0);
self.add_nocarry(other);
// However, it may need to be reduced.
self.reduce();
@ -960,11 +1070,11 @@ fn prime_field_impl(
#[inline]
fn sub_assign(&mut self, other: &#name) {
// If `other` is larger than `self`, we'll need to add the modulus to self first.
if other.0 > self.0 {
self.0.add_nocarry(&MODULUS);
if other.cmp_native(self) == ::core::cmp::Ordering::Greater {
self.add_nocarry(&MODULUS_LIMBS);
}
self.0.sub_noborrow(&other.0);
self.sub_noborrow(other);
}
}
@ -1020,7 +1130,7 @@ fn prime_field_impl(
#mont_reduce_self_params
);
(self.0).0[0] & rhs
self.0[0] & rhs
}
}
@ -1040,7 +1150,7 @@ fn prime_field_impl(
while n >= 64 {
let mut t = 0;
for i in (self.0).0.iter_mut().rev() {
for i in self.0.iter_mut().rev() {
::core::mem::swap(&mut t, i);
}
n -= 64;
@ -1048,7 +1158,7 @@ fn prime_field_impl(
if n > 0 {
let mut t = 0;
for i in (self.0).0.iter_mut().rev() {
for i in self.0.iter_mut().rev() {
let t2 = *i << (64 - n);
*i >>= n;
*i |= t;
@ -1057,39 +1167,32 @@ fn prime_field_impl(
}
// Convert back to Montgomery representation
self * #name(R2)
self * R2
}
}
impl ::ff::PrimeField for #name {
type Repr = #repr;
fn from_repr(r: #repr) -> Result<#name, PrimeFieldDecodingError> {
let mut r = #name(r);
if r.is_valid() {
r.mul_assign(&#name(R2));
Ok(r)
} else {
Err(PrimeFieldDecodingError::NotInField)
}
fn from_repr(r: #repr) -> Option<#name> {
#from_repr_impl
}
fn into_repr(&self) -> #repr {
#into_repr_impl
}
#[inline(always)]
fn is_odd(&self) -> bool {
let mut r = *self;
r.mont_reduce(
#mont_reduce_self_params
);
r.0
r.0[0] & 1 == 1
}
#[inline(always)]
fn is_odd(&self) -> bool {
self.into_repr().is_odd()
}
fn char() -> #repr {
fn char() -> Self::Repr {
MODULUS
}
@ -1098,13 +1201,13 @@ fn prime_field_impl(
const CAPACITY: u32 = Self::NUM_BITS - 1;
fn multiplicative_generator() -> Self {
#name(GENERATOR)
GENERATOR
}
const S: u32 = S;
fn root_of_unity() -> Self {
#name(ROOT_OF_UNITY)
ROOT_OF_UNITY
}
}
@ -1117,7 +1220,7 @@ fn prime_field_impl(
for i in 0..#limbs {
repr[i] = rng.next_u64();
}
#name(#repr(repr))
#name(repr)
};
// Mask away the unused most-significant bits.
@ -1131,17 +1234,17 @@ fn prime_field_impl(
#[inline]
fn zero() -> Self {
#name(#repr::from(0))
#name([0; #limbs])
}
#[inline]
fn one() -> Self {
#name(R)
R
}
#[inline]
fn is_zero(&self) -> bool {
self.0.is_zero()
self.0.iter().all(|&e| e == 0)
}
#[inline]
@ -1149,7 +1252,13 @@ fn prime_field_impl(
let mut ret = *self;
// This cannot exceed the backing capacity.
ret.0.mul2();
let mut last = 0;
for i in &mut ret.0 {
let tmp = *i >> 63;
*i <<= 1;
*i |= last;
last = tmp;
}
// However, it may need to be reduced.
ret.reduce();
@ -1174,11 +1283,46 @@ fn prime_field_impl(
}
impl #name {
/// Compares two elements in native representation. This is only used
/// internally.
#[inline(always)]
fn cmp_native(&self, other: &#name) -> ::core::cmp::Ordering {
for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
if a < b {
return ::core::cmp::Ordering::Less
} else if a > b {
return ::core::cmp::Ordering::Greater
}
}
::core::cmp::Ordering::Equal
}
/// Determines if the element is really in the field. This is only used
/// internally.
#[inline(always)]
fn is_valid(&self) -> bool {
self.0 < MODULUS
// The Ord impl calls `reduce`, which in turn calls `is_valid`, so we use
// this internal function to eliminate the cycle.
self.cmp_native(&MODULUS_LIMBS) == ::core::cmp::Ordering::Less
}
#[inline(always)]
fn add_nocarry(&mut self, other: &#name) {
let mut carry = 0;
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
*a = ::ff::adc(*a, *b, &mut carry);
}
}
#[inline(always)]
fn sub_noborrow(&mut self, other: &#name) {
let mut borrow = 0;
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
*a = ::ff::sbb(*a, *b, &mut borrow);
}
}
/// Subtracts the modulus from this element if this element is not in the
@ -1186,7 +1330,7 @@ fn prime_field_impl(
#[inline(always)]
fn reduce(&mut self) {
if !self.is_valid() {
self.0.sub_noborrow(&MODULUS);
self.sub_noborrow(&MODULUS_LIMBS);
}
}

View File

@ -12,6 +12,7 @@ extern crate std;
#[cfg(feature = "derive")]
pub use ff_derive::*;
use core::convert::TryFrom;
use core::fmt;
use core::marker::PhantomData;
use core::ops::{Add, AddAssign, BitAnd, Mul, MulAssign, Neg, Shr, Sub, SubAssign};
@ -130,139 +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 + Ord + From<u64> + BitAnd<u64, Output = u64> + Shr<u32, Output = Self>
{
/// The prime field can be converted back and forth into this biginteger
/// 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.
@ -304,11 +179,20 @@ pub trait PrimeField:
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.

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

@ -1,3 +1,4 @@
use byteorder::{ByteOrder, LittleEndian};
use ff::PrimeField;
use std::iter;
@ -19,7 +20,7 @@ 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 little-endian
/// scalar.
pub(crate) fn wnaf_form<S: AsRef<[u64]>>(wnaf: &mut Vec<i64>, c: S, window: usize) {
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
@ -27,11 +28,11 @@ pub(crate) fn wnaf_form<S: AsRef<[u64]>>(wnaf: &mut Vec<i64>, c: S, window: usiz
wnaf.truncate(0);
let u64_len = c.as_ref().len();
let bit_len = u64_len * 64;
let bit_len = c.as_ref().len() * 8;
let u64_len = (bit_len + 1) / 64;
let mut c_u64 = vec![0u64; u64_len + 1];
c_u64[0..u64_len].copy_from_slice(c.as_ref());
LittleEndian::read_u64_into(c.as_ref(), &mut c_u64[0..u64_len]);
let width = 1u64 << window;
let window_mask = width - 1;
@ -144,13 +145,11 @@ impl<G: CurveProjective> Wnaf<(), Vec<G>, Vec<i64>> {
&mut self,
scalar: &<G as CurveProjective>::Scalar,
) -> Wnaf<usize, &mut Vec<G>, &[i64]> {
let scalar = scalar.into_repr();
// Compute the appropriate window size for the 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.

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

@ -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(),
@ -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,10 +1,11 @@
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;
@ -15,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::from(0).is_valid());
assert!(Fr(FrRepr([
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([
@ -399,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
@ -511,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
]))
])
);
}
@ -602,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([
@ -672,80 +326,73 @@ fn test_fr_mul_assign() {
#[test]
fn test_fr_shr() {
let mut a = Fr::from_repr(FrRepr([
0xb33fbaec482a283f,
0x997de0d3a88cb3df,
0x9af62d2a9a0e5525,
0x36003ab08de70da1,
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([
0xb33fbaec482a283f,
0x997de0d3a88cb3df,
0x9af62d2a9a0e5525,
0x36003ab08de70da1,
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([
0xd99fdd762415141f,
0xccbef069d44659ef,
0xcd7b16954d072a92,
0x1b001d5846f386d0,
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([
0xbc1a7511967bf667,
0xc5a55341caa4b32f,
0x075611bce1b4335e,
0x00000000000006c0,
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([
0x01d5846f386d0cd7,
0x00000000000001b0,
0x0000000000000000,
0x0000000000000000,
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([
0x00000000000001b0,
0x0000000000000000,
0x0000000000000000,
0x0000000000000000,
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()
);
@ -883,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,
@ -937,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()
),
@ -1000,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()
),

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() {
// :)
@ -198,8 +200,8 @@ fn test_g1_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.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() {
// :)
@ -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")
@ -433,7 +439,7 @@ fn test_g1_compressed_invalid_vectors() {
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() {
@ -456,7 +462,7 @@ fn test_g1_compressed_invalid_vectors() {
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")
@ -565,8 +573,8 @@ fn test_g2_compressed_invalid_vectors() {
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() {
@ -595,8 +603,8 @@ fn test_g2_compressed_invalid_vectors() {
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

@ -2,7 +2,7 @@ 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,

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,71 +14,12 @@ 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 v = r.into_repr();
let rdecoded = P::from_repr(v).unwrap();
let mut v: Vec<u8> = vec![];
r.write_be(&mut v).unwrap();
rdecoded.read_be(&v[0..]).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);
}
assert_eq!(r, rdecoded);
}
}
@ -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",
)),
@ -167,17 +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 mut y_repr = y.into_repr();
if x.is_odd() {
y_repr.as_mut()[3] |= 0x8000000000000000u64;
y_repr.as_mut()[31] |= 0x80;
}
y_repr.write_le(writer)
writer.write_all(y_repr.as_ref())
}
/// Convert from a Montgomery point
@ -467,7 +467,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
let mut res = Self::zero();
for b in BitIterator::<u64, _>::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

@ -304,7 +304,7 @@ impl<E: JubjubEngine, Subgroup> Point<E, Subgroup> {
let mut res = Self::zero();
for b in BitIterator::<u64, _>::new(scalar.into()) {
for b in BitIterator::<u8, _>::new(scalar.into()) {
res = res.double(params);
if b {

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,6 +1,6 @@
//! Structs for core Zcash primitives.
use ff::{Field, PrimeField, PrimeFieldRepr};
use ff::{Field, PrimeField};
use crate::constants;
@ -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")
}

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::<u64, _>::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::<u64, _>::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::<u64, _>::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::<u64, _>::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

@ -615,8 +615,8 @@ fn test_input_circuit_with_bls12_381() {
::std::mem::swap(&mut lhs, &mut rhs);
}
let mut lhs: Vec<bool> = BitIterator::<u64, _>::new(lhs.into_repr()).collect();
let mut rhs: Vec<bool> = BitIterator::<u64, _>::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::<u64, _>::new(lhs.into_repr()).collect();
let mut rhs: Vec<bool> = BitIterator::<u64, _>::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();