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:
parent
1fe3e3784c
commit
49f119fb03
|
@ -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 {
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
148
ff/src/lib.rs
148
ff/src/lib.rs
|
@ -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.
|
||||
|
|
|
@ -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()),
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
@ -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(),
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
),
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
@ -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 {
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()
|
||||
}};
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue