mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-07-30 20:11:23 +00:00
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:
@@ -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.
|
||||
|
Reference in New Issue
Block a user