2018-06-26 07:48:27 -07:00
|
|
|
#![recursion_limit = "1024"]
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2017-06-25 22:09:43 -07:00
|
|
|
extern crate proc_macro;
|
2018-06-27 04:33:17 -07:00
|
|
|
extern crate proc_macro2;
|
2017-06-25 22:09:43 -07:00
|
|
|
|
2017-06-26 10:47:35 -07:00
|
|
|
use num_bigint::BigUint;
|
2018-06-26 07:48:27 -07:00
|
|
|
use num_integer::Integer;
|
|
|
|
use num_traits::{One, ToPrimitive, Zero};
|
2019-10-08 06:06:02 -07:00
|
|
|
use quote::quote;
|
2018-06-27 04:33:17 -07:00
|
|
|
use quote::TokenStreamExt;
|
2017-06-26 10:47:35 -07:00
|
|
|
use std::str::FromStr;
|
2017-06-25 22:09:43 -07:00
|
|
|
|
2017-06-26 22:22:41 -07:00
|
|
|
#[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus, PrimeFieldGenerator))]
|
2018-06-26 07:48:27 -07:00
|
|
|
pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
2018-06-27 04:33:17 -07:00
|
|
|
// Parse the type definition
|
|
|
|
let ast: syn::DeriveInput = syn::parse(input).unwrap();
|
2017-06-25 22:09:43 -07:00
|
|
|
|
|
|
|
// The struct we're deriving for is a wrapper around a "Repr" type we must construct.
|
2018-06-27 04:33:17 -07:00
|
|
|
let repr_ident = fetch_wrapped_ident(&ast.data)
|
2018-06-26 07:48:27 -07:00
|
|
|
.expect("PrimeField derive only operates over tuple structs of a single item");
|
2017-06-25 22:09:43 -07:00
|
|
|
|
|
|
|
// We're given the modulus p of the prime field
|
|
|
|
let modulus: BigUint = fetch_attr("PrimeFieldModulus", &ast.attrs)
|
2018-06-26 07:48:27 -07:00
|
|
|
.expect("Please supply a PrimeFieldModulus attribute")
|
|
|
|
.parse()
|
|
|
|
.expect("PrimeFieldModulus should be a number");
|
2017-06-25 22:09:43 -07:00
|
|
|
|
2017-06-26 22:22:41 -07:00
|
|
|
// We may be provided with a generator of p - 1 order. It is required that this generator be quadratic
|
|
|
|
// nonresidue.
|
2017-06-27 08:14:24 -07:00
|
|
|
let generator: BigUint = fetch_attr("PrimeFieldGenerator", &ast.attrs)
|
2018-06-26 07:48:27 -07:00
|
|
|
.expect("Please supply a PrimeFieldGenerator attribute")
|
|
|
|
.parse()
|
|
|
|
.expect("PrimeFieldGenerator should be a number");
|
2017-06-26 22:22:41 -07:00
|
|
|
|
2017-06-25 22:09:43 -07:00
|
|
|
// 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;
|
|
|
|
{
|
|
|
|
let mod2 = (&modulus) << 1; // modulus * 2
|
2017-06-27 08:40:58 -07:00
|
|
|
let mut cur = BigUint::one() << 64; // always 64-bit limbs for now
|
2017-06-25 22:09:43 -07:00
|
|
|
while cur < mod2 {
|
|
|
|
limbs += 1;
|
|
|
|
cur = cur << 64;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-27 04:33:17 -07:00
|
|
|
let mut gen = proc_macro2::TokenStream::new();
|
2017-06-25 22:09:43 -07:00
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
let (constants_impl, sqrt_impl) =
|
|
|
|
prime_field_constants_and_sqrt(&ast.ident, &repr_ident, modulus, limbs, generator);
|
2018-07-01 14:43:22 -07:00
|
|
|
|
|
|
|
gen.extend(constants_impl);
|
2018-07-01 14:49:10 -07:00
|
|
|
gen.extend(prime_field_repr_impl(&repr_ident, limbs));
|
2018-06-27 04:33:17 -07:00
|
|
|
gen.extend(prime_field_impl(&ast.ident, &repr_ident, limbs));
|
2018-07-01 14:49:10 -07:00
|
|
|
gen.extend(sqrt_impl);
|
2018-06-26 07:48:27 -07:00
|
|
|
|
2017-06-25 22:09:43 -07:00
|
|
|
// Return the generated impl
|
2018-06-27 04:33:17 -07:00
|
|
|
gen.into()
|
2017-06-25 22:09:43 -07:00
|
|
|
}
|
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
/// Fetches the ident being wrapped by the type we're deriving.
|
2018-06-27 04:33:17 -07:00
|
|
|
fn fetch_wrapped_ident(body: &syn::Data) -> Option<syn::Ident> {
|
2017-06-25 22:09:43 -07:00
|
|
|
match body {
|
2018-06-27 04:33:17 -07:00
|
|
|
&syn::Data::Struct(ref variant_data) => match variant_data.fields {
|
|
|
|
syn::Fields::Unnamed(ref fields) => {
|
|
|
|
if fields.unnamed.len() == 1 {
|
|
|
|
match fields.unnamed[0].ty {
|
|
|
|
syn::Type::Path(ref path) => {
|
|
|
|
if path.path.segments.len() == 1 {
|
|
|
|
return Some(path.path.segments[0].ident.clone());
|
|
|
|
}
|
2017-06-25 22:09:43 -07:00
|
|
|
}
|
2018-06-27 04:33:17 -07:00
|
|
|
_ => {}
|
2018-06-26 07:48:27 -07:00
|
|
|
}
|
2017-06-25 22:09:43 -07:00
|
|
|
}
|
|
|
|
}
|
2018-06-27 04:33:17 -07:00
|
|
|
_ => {}
|
|
|
|
},
|
2017-06-25 22:09:43 -07:00
|
|
|
_ => {}
|
|
|
|
};
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Fetch an attribute string from the derived struct.
|
2018-06-26 07:48:27 -07:00
|
|
|
fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> {
|
2017-06-25 22:09:43 -07:00
|
|
|
for attr in attrs {
|
2019-09-06 16:03:12 -07:00
|
|
|
if let Ok(meta) = attr.parse_meta() {
|
2018-06-27 04:33:17 -07:00
|
|
|
match meta {
|
|
|
|
syn::Meta::NameValue(nv) => {
|
2019-09-06 16:03:12 -07:00
|
|
|
if nv.path.get_ident().map(|i| i.to_string()) == Some(name.to_string()) {
|
2018-06-27 04:33:17 -07:00
|
|
|
match nv.lit {
|
|
|
|
syn::Lit::Str(ref s) => return Some(s.value()),
|
|
|
|
_ => {
|
|
|
|
panic!("attribute {} should be a string", name);
|
|
|
|
}
|
|
|
|
}
|
2017-06-25 22:09:43 -07:00
|
|
|
}
|
2018-06-27 04:33:17 -07:00
|
|
|
}
|
2017-06-25 22:09:43 -07:00
|
|
|
_ => {
|
|
|
|
panic!("attribute {} should be a string", name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
// Implement PrimeFieldRepr for the wrapped ident `repr` with `limbs` limbs.
|
2018-06-27 04:33:17 -07:00
|
|
|
fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream {
|
2017-06-26 10:47:35 -07:00
|
|
|
quote! {
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Default)]
|
|
|
|
pub struct #repr(pub [u64; #limbs]);
|
|
|
|
|
|
|
|
impl ::std::fmt::Debug for #repr
|
|
|
|
{
|
|
|
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
2019-08-20 17:24:47 -07:00
|
|
|
write!(f, "0x")?;
|
2017-06-26 10:47:35 -07:00
|
|
|
for i in self.0.iter().rev() {
|
2019-08-20 17:24:47 -07:00
|
|
|
write!(f, "{:016x}", *i)?;
|
2017-06-26 10:47:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 12:07:35 -07:00
|
|
|
impl ::std::fmt::Display for #repr {
|
|
|
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
2019-08-20 17:24:47 -07:00
|
|
|
write!(f, "0x")?;
|
2018-06-28 12:07:35 -07:00
|
|
|
for i in self.0.iter().rev() {
|
2019-08-20 17:24:47 -07:00
|
|
|
write!(f, "{:016x}", *i)?;
|
2018-06-28 12:07:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-26 10:47:35 -07:00
|
|
|
impl AsRef<[u64]> for #repr {
|
2017-06-27 08:40:58 -07:00
|
|
|
#[inline(always)]
|
2017-06-26 10:47:35 -07:00
|
|
|
fn as_ref(&self) -> &[u64] {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 12:07:35 -07:00
|
|
|
impl AsMut<[u64]> for #repr {
|
|
|
|
#[inline(always)]
|
|
|
|
fn as_mut(&mut self) -> &mut [u64] {
|
|
|
|
&mut self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-26 10:47:35 -07:00
|
|
|
impl From<u64> for #repr {
|
|
|
|
#[inline(always)]
|
|
|
|
fn from(val: u64) -> #repr {
|
|
|
|
use std::default::Default;
|
|
|
|
|
|
|
|
let mut repr = Self::default();
|
|
|
|
repr.0[0] = val;
|
|
|
|
repr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Ord for #repr {
|
2017-06-27 08:40:58 -07:00
|
|
|
#[inline(always)]
|
2017-06-26 10:47:35 -07:00
|
|
|
fn cmp(&self, other: &#repr) -> ::std::cmp::Ordering {
|
|
|
|
for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
|
|
|
|
if a < b {
|
|
|
|
return ::std::cmp::Ordering::Less
|
|
|
|
} else if a > b {
|
|
|
|
return ::std::cmp::Ordering::Greater
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
::std::cmp::Ordering::Equal
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd for #repr {
|
2017-06-27 08:40:58 -07:00
|
|
|
#[inline(always)]
|
2017-06-26 10:47:35 -07:00
|
|
|
fn partial_cmp(&self, other: &#repr) -> Option<::std::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)
|
|
|
|
}
|
|
|
|
|
2018-06-28 12:07:35 -07:00
|
|
|
#[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() {
|
|
|
|
::std::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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-01 14:49:10 -07:00
|
|
|
#[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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-26 10:47:35 -07:00
|
|
|
#[inline(always)]
|
|
|
|
fn mul2(&mut self) {
|
|
|
|
let mut last = 0;
|
2018-06-30 21:05:56 -07:00
|
|
|
for i in &mut self.0 {
|
2017-06-26 10:47:35 -07:00
|
|
|
let tmp = *i >> 63;
|
|
|
|
*i <<= 1;
|
|
|
|
*i |= last;
|
|
|
|
last = tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 12:07:35 -07:00
|
|
|
#[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 {
|
|
|
|
::std::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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-26 10:47:35 -07:00
|
|
|
#[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)]
|
2018-06-28 12:07:35 -07:00
|
|
|
fn add_nocarry(&mut self, other: &#repr) {
|
2017-06-26 10:47:35 -07:00
|
|
|
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)]
|
2018-06-28 12:07:35 -07:00
|
|
|
fn sub_noborrow(&mut self, other: &#repr) {
|
2017-06-26 10:47:35 -07:00
|
|
|
let mut borrow = 0;
|
|
|
|
|
|
|
|
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
|
|
|
|
*a = ::ff::sbb(*a, *b, &mut borrow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
/// Convert BigUint into a vector of 64-bit limbs.
|
2018-06-27 04:33:17 -07:00
|
|
|
fn biguint_to_real_u64_vec(mut v: BigUint, limbs: usize) -> Vec<u64> {
|
2017-06-26 10:47:35 -07:00
|
|
|
let m = BigUint::one() << 64;
|
|
|
|
let mut ret = vec![];
|
|
|
|
|
|
|
|
while v > BigUint::zero() {
|
|
|
|
ret.push((&v % &m).to_u64().unwrap());
|
|
|
|
v = v >> 64;
|
|
|
|
}
|
|
|
|
|
2017-06-27 08:14:24 -07:00
|
|
|
while ret.len() < limbs {
|
|
|
|
ret.push(0);
|
|
|
|
}
|
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
assert!(ret.len() == limbs);
|
|
|
|
|
2017-06-26 10:47:35 -07:00
|
|
|
ret
|
|
|
|
}
|
|
|
|
|
2018-06-27 04:33:17 -07:00
|
|
|
/// Convert BigUint into a tokenized vector of 64-bit limbs.
|
|
|
|
fn biguint_to_u64_vec(v: BigUint, limbs: usize) -> proc_macro2::TokenStream {
|
|
|
|
let ret = biguint_to_real_u64_vec(v, limbs);
|
|
|
|
quote!([#(#ret,)*])
|
|
|
|
}
|
|
|
|
|
2018-06-26 07:48:27 -07:00
|
|
|
fn biguint_num_bits(mut v: BigUint) -> u32 {
|
2017-06-26 10:47:35 -07:00
|
|
|
let mut bits = 0;
|
|
|
|
|
|
|
|
while v != BigUint::zero() {
|
|
|
|
v = v >> 1;
|
|
|
|
bits += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bits
|
|
|
|
}
|
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
/// BigUint modular exponentiation by square-and-multiply.
|
2018-06-26 07:48:27 -07:00
|
|
|
fn exp(base: BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
|
2017-06-26 22:22:41 -07:00
|
|
|
let mut ret = BigUint::one();
|
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
for i in exp
|
|
|
|
.to_bytes_be()
|
2018-06-26 07:48:27 -07:00
|
|
|
.into_iter()
|
|
|
|
.flat_map(|x| (0..8).rev().map(move |i| (x >> i).is_odd()))
|
2017-06-26 22:22:41 -07:00
|
|
|
{
|
|
|
|
ret = (&ret * &ret) % modulus;
|
|
|
|
if i {
|
|
|
|
ret = (ret * &base) % modulus;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_exp() {
|
|
|
|
assert_eq!(
|
|
|
|
exp(
|
|
|
|
BigUint::from_str("4398572349857239485729348572983472345").unwrap(),
|
|
|
|
&BigUint::from_str("5489673498567349856734895").unwrap(),
|
2018-06-26 07:48:27 -07:00
|
|
|
&BigUint::from_str(
|
|
|
|
"52435875175126190479447740508185965837690552500527637822603658699938581184513"
|
2019-08-15 09:41:48 -07:00
|
|
|
)
|
|
|
|
.unwrap()
|
2017-06-26 22:22:41 -07:00
|
|
|
),
|
2018-06-26 07:48:27 -07:00
|
|
|
BigUint::from_str(
|
|
|
|
"4371221214068404307866768905142520595925044802278091865033317963560480051536"
|
2019-08-15 09:41:48 -07:00
|
|
|
)
|
|
|
|
.unwrap()
|
2017-06-26 22:22:41 -07:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-06-26 10:47:35 -07:00
|
|
|
fn prime_field_constants_and_sqrt(
|
|
|
|
name: &syn::Ident,
|
|
|
|
repr: &syn::Ident,
|
|
|
|
modulus: BigUint,
|
2017-06-26 22:22:41 -07:00
|
|
|
limbs: usize,
|
2018-06-26 07:48:27 -07:00
|
|
|
generator: BigUint,
|
2018-07-01 14:43:22 -07:00
|
|
|
) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) {
|
2017-06-26 10:47:35 -07:00
|
|
|
let modulus_num_bits = biguint_num_bits(modulus.clone());
|
2017-06-27 08:40:58 -07:00
|
|
|
|
|
|
|
// The number of bits we should "shave" from a randomly sampled reputation, i.e.,
|
|
|
|
// if our modulus is 381 bits and our representation is 384 bits, we should shave
|
2018-06-26 07:48:27 -07:00
|
|
|
// 3 bits from the beginning of a randomly sampled 384 bit representation to
|
2017-06-27 08:40:58 -07:00
|
|
|
// reduce the cost of rejection sampling.
|
2017-06-26 10:47:35 -07:00
|
|
|
let repr_shave_bits = (64 * limbs as u32) - biguint_num_bits(modulus.clone());
|
|
|
|
|
|
|
|
// Compute R = 2**(64 * limbs) mod m
|
|
|
|
let r = (BigUint::one() << (limbs * 64)) % &modulus;
|
|
|
|
|
2017-06-26 22:22:41 -07:00
|
|
|
// modulus - 1 = 2^s * t
|
2018-06-28 12:07:35 -07:00
|
|
|
let mut s: u32 = 0;
|
2017-06-26 22:22:41 -07:00
|
|
|
let mut t = &modulus - BigUint::from_str("1").unwrap();
|
|
|
|
while t.is_even() {
|
|
|
|
t = t >> 1;
|
|
|
|
s += 1;
|
|
|
|
}
|
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
// Compute 2^s root of unity given the generator
|
2018-06-26 07:48:27 -07:00
|
|
|
let root_of_unity = biguint_to_u64_vec(
|
|
|
|
(exp(generator.clone(), &t, &modulus) * &r) % &modulus,
|
|
|
|
limbs,
|
|
|
|
);
|
2017-06-27 08:14:24 -07:00
|
|
|
let generator = biguint_to_u64_vec((generator.clone() * &r) % &modulus, limbs);
|
|
|
|
|
2019-05-15 02:35:14 -07:00
|
|
|
let sqrt_impl = if (&modulus % BigUint::from_str("4").unwrap())
|
|
|
|
== BigUint::from_str("3").unwrap()
|
|
|
|
{
|
|
|
|
let mod_plus_1_over_4 =
|
|
|
|
biguint_to_u64_vec((&modulus + BigUint::from_str("1").unwrap()) >> 2, limbs);
|
2018-06-26 07:48:27 -07:00
|
|
|
|
2019-05-15 02:35:14 -07:00
|
|
|
quote! {
|
|
|
|
impl ::ff::SqrtField for #name {
|
|
|
|
fn sqrt(&self) -> ::subtle::CtOption<Self> {
|
|
|
|
use ::subtle::ConstantTimeEq;
|
|
|
|
|
|
|
|
// Because r = 3 (mod 4)
|
|
|
|
// sqrt can be done with only one exponentiation,
|
|
|
|
// via the computation of self^((r + 1) // 4) (mod r)
|
2019-05-15 03:24:00 -07:00
|
|
|
let sqrt = self.pow_vartime(#mod_plus_1_over_4);
|
2019-05-15 02:35:14 -07:00
|
|
|
|
|
|
|
::subtle::CtOption::new(
|
|
|
|
sqrt,
|
|
|
|
(sqrt * &sqrt).ct_eq(self), // Only return Some if it's the square root.
|
|
|
|
)
|
2017-06-26 10:47:35 -07:00
|
|
|
}
|
|
|
|
}
|
2019-05-15 02:35:14 -07:00
|
|
|
}
|
|
|
|
} else if (&modulus % BigUint::from_str("16").unwrap()) == BigUint::from_str("1").unwrap() {
|
|
|
|
let t_minus_1_over_2 = biguint_to_u64_vec((&t - BigUint::one()) >> 1, limbs);
|
|
|
|
|
|
|
|
quote! {
|
|
|
|
impl ::ff::SqrtField for #name {
|
|
|
|
fn sqrt(&self) -> ::subtle::CtOption<Self> {
|
|
|
|
// Tonelli-Shank's algorithm for q mod 16 = 1
|
|
|
|
// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
|
|
|
|
use ::subtle::{ConditionallySelectable, ConstantTimeEq};
|
|
|
|
|
|
|
|
// w = self^((t - 1) // 2)
|
2019-05-15 03:24:00 -07:00
|
|
|
let w = self.pow_vartime(#t_minus_1_over_2);
|
2019-05-15 02:35:14 -07:00
|
|
|
|
|
|
|
let mut v = S;
|
|
|
|
let mut x = *self * &w;
|
|
|
|
let mut b = x * &w;
|
|
|
|
|
|
|
|
// Initialize z as the 2^S root of unity.
|
|
|
|
let mut z = #name(ROOT_OF_UNITY);
|
|
|
|
|
|
|
|
for max_v in (1..=S).rev() {
|
|
|
|
let mut k = 1;
|
|
|
|
let mut tmp = b.square();
|
|
|
|
let mut j_less_than_v: ::subtle::Choice = 1.into();
|
|
|
|
|
|
|
|
for j in 2..max_v {
|
|
|
|
let tmp_is_one = tmp.ct_eq(&#name::one());
|
|
|
|
let squared = #name::conditional_select(&tmp, &z, tmp_is_one).square();
|
|
|
|
tmp = #name::conditional_select(&squared, &tmp, tmp_is_one);
|
|
|
|
let new_z = #name::conditional_select(&z, &squared, tmp_is_one);
|
|
|
|
j_less_than_v &= !j.ct_eq(&v);
|
|
|
|
k = u32::conditional_select(&j, &k, tmp_is_one);
|
|
|
|
z = #name::conditional_select(&z, &new_z, j_less_than_v);
|
2018-06-26 07:48:27 -07:00
|
|
|
}
|
2019-05-15 02:35:14 -07:00
|
|
|
|
|
|
|
let result = x * &z;
|
|
|
|
x = #name::conditional_select(&result, &x, b.ct_eq(&#name::one()));
|
|
|
|
z = z.square();
|
|
|
|
b = b * &z;
|
|
|
|
v = k;
|
2017-06-26 22:22:41 -07:00
|
|
|
}
|
2019-05-15 02:35:14 -07:00
|
|
|
|
|
|
|
::subtle::CtOption::new(
|
|
|
|
x,
|
|
|
|
(x * &x).ct_eq(self), // Only return Some if it's the square root.
|
|
|
|
)
|
2017-06-26 22:22:41 -07:00
|
|
|
}
|
|
|
|
}
|
2019-05-15 02:35:14 -07:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
quote! {}
|
|
|
|
};
|
2017-06-26 10:47:35 -07:00
|
|
|
|
|
|
|
// Compute R^2 mod m
|
2017-06-27 08:14:24 -07:00
|
|
|
let r2 = biguint_to_u64_vec((&r * &r) % &modulus, limbs);
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2017-06-27 08:14:24 -07:00
|
|
|
let r = biguint_to_u64_vec(r, limbs);
|
2018-06-27 04:33:17 -07:00
|
|
|
let modulus = biguint_to_real_u64_vec(modulus, limbs);
|
2017-06-26 10:47:35 -07:00
|
|
|
|
|
|
|
// Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1
|
|
|
|
let mut inv = 1u64;
|
|
|
|
for _ in 0..63 {
|
|
|
|
inv = inv.wrapping_mul(inv);
|
|
|
|
inv = inv.wrapping_mul(modulus[0]);
|
|
|
|
}
|
|
|
|
inv = inv.wrapping_neg();
|
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
(
|
|
|
|
quote! {
|
|
|
|
/// This is the modulus m of the prime field
|
|
|
|
const MODULUS: #repr = #repr([#(#modulus,)*]);
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
/// The number of bits needed to represent the modulus.
|
|
|
|
const MODULUS_BITS: u32 = #modulus_num_bits;
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
/// The number of bits that must be shaved from the beginning of
|
|
|
|
/// the representation when randomly sampling.
|
|
|
|
const REPR_SHAVE_BITS: u32 = #repr_shave_bits;
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
/// 2^{limbs*64} mod m
|
|
|
|
const R: #repr = #repr(#r);
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
/// 2^{limbs*64*2} mod m
|
|
|
|
const R2: #repr = #repr(#r2);
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
/// -(m^{-1} mod m) mod m
|
|
|
|
const INV: u64 = #inv;
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
/// Multiplicative generator of `MODULUS` - 1 order, also quadratic
|
|
|
|
/// nonresidue.
|
|
|
|
const GENERATOR: #repr = #repr(#generator);
|
2017-06-27 08:14:24 -07:00
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
/// 2^s * t = MODULUS - 1 with t odd
|
|
|
|
const S: u32 = #s;
|
2017-06-27 08:14:24 -07:00
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
/// 2^s root of unity computed by GENERATOR^t
|
|
|
|
const ROOT_OF_UNITY: #repr = #repr(#root_of_unity);
|
|
|
|
},
|
|
|
|
sqrt_impl,
|
|
|
|
)
|
2017-06-26 10:47:35 -07:00
|
|
|
}
|
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
/// Implement PrimeField for the derived type.
|
2018-06-27 04:33:17 -07:00
|
|
|
fn prime_field_impl(
|
|
|
|
name: &syn::Ident,
|
|
|
|
repr: &syn::Ident,
|
|
|
|
limbs: usize,
|
|
|
|
) -> proc_macro2::TokenStream {
|
2017-06-27 08:40:58 -07:00
|
|
|
// Returns r{n} as an ident.
|
2017-06-26 10:47:35 -07:00
|
|
|
fn get_temp(n: usize) -> syn::Ident {
|
2018-06-27 04:33:17 -07:00
|
|
|
syn::Ident::new(&format!("r{}", n), proc_macro2::Span::call_site())
|
2017-06-26 10:47:35 -07:00
|
|
|
}
|
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
// The parameter list for the mont_reduce() internal method.
|
|
|
|
// r0: u64, mut r1: u64, mut r2: u64, ...
|
2018-06-27 04:33:17 -07:00
|
|
|
let mut mont_paramlist = proc_macro2::TokenStream::new();
|
2017-06-26 10:47:35 -07:00
|
|
|
mont_paramlist.append_separated(
|
2018-06-26 07:48:27 -07:00
|
|
|
(0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| {
|
|
|
|
if i != 0 {
|
2019-08-15 09:41:48 -07:00
|
|
|
quote! {mut #x: u64}
|
2018-06-26 07:48:27 -07:00
|
|
|
} else {
|
2019-08-15 09:41:48 -07:00
|
|
|
quote! {#x: u64}
|
2018-06-26 07:48:27 -07:00
|
|
|
}
|
|
|
|
}),
|
2018-06-27 04:33:17 -07:00
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
2017-06-27 08:40:58 -07:00
|
|
|
);
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
// Implement montgomery reduction for some number of limbs
|
2018-06-27 04:33:17 -07:00
|
|
|
fn mont_impl(limbs: usize) -> proc_macro2::TokenStream {
|
|
|
|
let mut gen = proc_macro2::TokenStream::new();
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
for i in 0..limbs {
|
|
|
|
{
|
|
|
|
let temp = get_temp(i);
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-27 08:40:58 -07:00
|
|
|
let k = #temp.wrapping_mul(INV);
|
|
|
|
let mut carry = 0;
|
|
|
|
::ff::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
for j in 1..limbs {
|
|
|
|
let temp = get_temp(i + j);
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-27 08:40:58 -07:00
|
|
|
#temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry);
|
|
|
|
});
|
|
|
|
}
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
let temp = get_temp(i + limbs);
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
if i == 0 {
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-27 08:40:58 -07:00
|
|
|
#temp = ::ff::adc(#temp, 0, &mut carry);
|
|
|
|
});
|
|
|
|
} else {
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-27 08:40:58 -07:00
|
|
|
#temp = ::ff::adc(#temp, carry2, &mut carry);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if i != (limbs - 1) {
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-27 08:40:58 -07:00
|
|
|
let carry2 = carry;
|
|
|
|
});
|
|
|
|
}
|
2017-06-26 10:47:35 -07:00
|
|
|
}
|
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
for i in 0..limbs {
|
|
|
|
let temp = get_temp(limbs + i);
|
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-27 08:40:58 -07:00
|
|
|
(self.0).0[#i] = #temp;
|
2017-06-26 10:47:35 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
gen
|
2017-06-26 10:47:35 -07:00
|
|
|
}
|
|
|
|
|
2018-06-27 04:33:17 -07:00
|
|
|
fn sqr_impl(a: proc_macro2::TokenStream, limbs: usize) -> proc_macro2::TokenStream {
|
|
|
|
let mut gen = proc_macro2::TokenStream::new();
|
2017-06-26 13:42:47 -07:00
|
|
|
|
2018-06-26 07:48:27 -07:00
|
|
|
for i in 0..(limbs - 1) {
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-26 13:42:47 -07:00
|
|
|
let mut carry = 0;
|
|
|
|
});
|
|
|
|
|
2018-06-26 07:48:27 -07:00
|
|
|
for j in (i + 1)..limbs {
|
2017-06-26 13:42:47 -07:00
|
|
|
let temp = get_temp(i + j);
|
|
|
|
if i == 0 {
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-26 13:42:47 -07:00
|
|
|
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#j], &mut carry);
|
|
|
|
});
|
|
|
|
} else {
|
2018-06-27 04:33:17 -07:00
|
|
|
gen.extend(quote!{
|
2017-06-26 13:42:47 -07:00
|
|
|
let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#a.0).0[#j], &mut carry);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let temp = get_temp(i + limbs);
|
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-26 13:42:47 -07:00
|
|
|
let #temp = carry;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-06-26 07:48:27 -07:00
|
|
|
for i in 1..(limbs * 2) {
|
2018-06-30 21:05:56 -07:00
|
|
|
let temp0 = get_temp(limbs * 2 - i);
|
|
|
|
let temp1 = get_temp(limbs * 2 - i - 1);
|
2017-06-26 13:42:47 -07:00
|
|
|
|
|
|
|
if i == 1 {
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2018-06-30 21:05:56 -07:00
|
|
|
let #temp0 = #temp1 >> 63;
|
2017-06-26 13:42:47 -07:00
|
|
|
});
|
2018-06-26 07:48:27 -07:00
|
|
|
} else if i == (limbs * 2 - 1) {
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2018-06-30 21:05:56 -07:00
|
|
|
let #temp0 = #temp0 << 1;
|
2017-06-26 13:42:47 -07:00
|
|
|
});
|
|
|
|
} else {
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2018-06-30 21:05:56 -07:00
|
|
|
let #temp0 = (#temp0 << 1) | (#temp1 >> 63);
|
2017-06-26 13:42:47 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-26 13:42:47 -07:00
|
|
|
let mut carry = 0;
|
|
|
|
});
|
|
|
|
|
|
|
|
for i in 0..limbs {
|
|
|
|
let temp0 = get_temp(i * 2);
|
|
|
|
let temp1 = get_temp(i * 2 + 1);
|
|
|
|
if i == 0 {
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-26 13:42:47 -07:00
|
|
|
let #temp0 = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#i], &mut carry);
|
|
|
|
});
|
|
|
|
} else {
|
2018-06-27 04:33:17 -07:00
|
|
|
gen.extend(quote!{
|
2017-06-26 13:42:47 -07:00
|
|
|
let #temp0 = ::ff::mac_with_carry(#temp0, (#a.0).0[#i], (#a.0).0[#i], &mut carry);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-26 13:42:47 -07:00
|
|
|
let #temp1 = ::ff::adc(#temp1, 0, &mut carry);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-06-27 04:33:17 -07:00
|
|
|
let mut mont_calling = proc_macro2::TokenStream::new();
|
|
|
|
mont_calling.append_separated(
|
|
|
|
(0..(limbs * 2)).map(|i| get_temp(i)),
|
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
|
|
|
);
|
2017-06-26 13:42:47 -07:00
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2019-12-12 15:09:28 -08:00
|
|
|
let mut ret = *self;
|
|
|
|
ret.mont_reduce(#mont_calling);
|
|
|
|
ret
|
2017-06-26 13:42:47 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
gen
|
|
|
|
}
|
|
|
|
|
2018-06-27 04:33:17 -07:00
|
|
|
fn mul_impl(
|
|
|
|
a: proc_macro2::TokenStream,
|
|
|
|
b: proc_macro2::TokenStream,
|
|
|
|
limbs: usize,
|
|
|
|
) -> proc_macro2::TokenStream {
|
|
|
|
let mut gen = proc_macro2::TokenStream::new();
|
2017-06-26 10:47:35 -07:00
|
|
|
|
|
|
|
for i in 0..limbs {
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-26 10:47:35 -07:00
|
|
|
let mut carry = 0;
|
|
|
|
});
|
|
|
|
|
|
|
|
for j in 0..limbs {
|
|
|
|
let temp = get_temp(i + j);
|
|
|
|
|
|
|
|
if i == 0 {
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-26 10:47:35 -07:00
|
|
|
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
|
|
|
|
});
|
|
|
|
} else {
|
2018-06-27 04:33:17 -07:00
|
|
|
gen.extend(quote!{
|
2017-06-26 10:47:35 -07:00
|
|
|
let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let temp = get_temp(i + limbs);
|
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-26 10:47:35 -07:00
|
|
|
let #temp = carry;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-06-27 04:33:17 -07:00
|
|
|
let mut mont_calling = proc_macro2::TokenStream::new();
|
|
|
|
mont_calling.append_separated(
|
|
|
|
(0..(limbs * 2)).map(|i| get_temp(i)),
|
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
|
|
|
);
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
gen.extend(quote! {
|
2017-06-26 10:47:35 -07:00
|
|
|
self.mont_reduce(#mont_calling);
|
|
|
|
});
|
|
|
|
|
|
|
|
gen
|
|
|
|
}
|
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
let squaring_impl = sqr_impl(quote! {self}, limbs);
|
|
|
|
let multiply_impl = mul_impl(quote! {self}, quote! {other}, limbs);
|
2017-06-27 08:40:58 -07:00
|
|
|
let montgomery_impl = mont_impl(limbs);
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2019-05-15 02:35:14 -07:00
|
|
|
// (self.0).0[0].ct_eq(&(other.0).0[0]) & (self.0).0[1].ct_eq(&(other.0).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]) }),
|
|
|
|
proc_macro2::Punct::new('&', proc_macro2::Spacing::Alone),
|
|
|
|
);
|
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
// (self.0).0[0], (self.0).0[1], ..., 0, 0, 0, 0, ...
|
2018-06-27 04:33:17 -07:00
|
|
|
let mut into_repr_params = proc_macro2::TokenStream::new();
|
2017-06-26 10:47:35 -07:00
|
|
|
into_repr_params.append_separated(
|
2018-06-26 07:48:27 -07:00
|
|
|
(0..limbs)
|
2019-08-15 09:41:48 -07:00
|
|
|
.map(|i| quote! { (self.0).0[#i] })
|
|
|
|
.chain((0..limbs).map(|_| quote! {0})),
|
2018-06-27 04:33:17 -07:00
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
2017-06-26 10:47:35 -07:00
|
|
|
);
|
|
|
|
|
2018-06-30 21:05:56 -07:00
|
|
|
let top_limb_index = limbs - 1;
|
|
|
|
|
2019-08-15 09:41:48 -07:00
|
|
|
quote! {
|
2018-07-01 22:54:59 -07:00
|
|
|
impl ::std::marker::Copy for #name { }
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2018-07-01 22:54:59 -07:00
|
|
|
impl ::std::clone::Clone for #name {
|
2017-06-26 10:47:35 -07:00
|
|
|
fn clone(&self) -> #name {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-14 06:18:37 -07:00
|
|
|
impl ::std::default::Default for #name {
|
|
|
|
fn default() -> #name {
|
|
|
|
#name::zero()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-15 02:35:14 -07:00
|
|
|
impl ::subtle::ConstantTimeEq for #name {
|
|
|
|
fn ct_eq(&self, other: &#name) -> ::subtle::Choice {
|
|
|
|
#ct_eq_impl
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-01 22:54:59 -07:00
|
|
|
impl ::std::cmp::PartialEq for #name {
|
2017-06-26 10:47:35 -07:00
|
|
|
fn eq(&self, other: &#name) -> bool {
|
|
|
|
self.0 == other.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-01 22:54:59 -07:00
|
|
|
impl ::std::cmp::Eq for #name { }
|
2017-06-26 10:47:35 -07:00
|
|
|
|
|
|
|
impl ::std::fmt::Debug for #name
|
|
|
|
{
|
|
|
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
|
|
|
write!(f, "{}({:?})", stringify!(#name), self.into_repr())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 12:07:35 -07:00
|
|
|
/// Elements are ordered lexicographically.
|
|
|
|
impl Ord for #name {
|
|
|
|
#[inline(always)]
|
|
|
|
fn cmp(&self, other: &#name) -> ::std::cmp::Ordering {
|
|
|
|
self.into_repr().cmp(&other.into_repr())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd for #name {
|
|
|
|
#[inline(always)]
|
|
|
|
fn partial_cmp(&self, other: &#name) -> Option<::std::cmp::Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::std::fmt::Display for #name {
|
|
|
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
|
|
|
write!(f, "{}({})", stringify!(#name), self.into_repr())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<#name> for #repr {
|
|
|
|
fn from(e: #name) -> #repr {
|
|
|
|
e.into_repr()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-12 15:15:48 -08:00
|
|
|
impl ::subtle::ConditionallySelectable for #name {
|
|
|
|
fn conditional_select(a: &#name, b: &#name, choice: ::subtle::Choice) -> #name {
|
|
|
|
let mut res = [0u64; #limbs];
|
|
|
|
for i in 0..#limbs {
|
|
|
|
res[i] = u64::conditional_select(&(a.0).0[i], &(b.0).0[i], choice);
|
|
|
|
}
|
|
|
|
#name(#repr(res))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-12 14:52:17 -08:00
|
|
|
impl ::std::ops::Neg for #name {
|
|
|
|
type Output = #name;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn neg(self) -> #name {
|
|
|
|
let mut ret = self;
|
|
|
|
if !ret.is_zero() {
|
|
|
|
let mut tmp = MODULUS;
|
|
|
|
tmp.sub_noborrow(&ret.0);
|
|
|
|
ret.0 = tmp;
|
|
|
|
}
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-12 12:57:06 -08:00
|
|
|
impl<'r> ::std::ops::Add<&'r #name> for #name {
|
|
|
|
type Output = #name;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn add(self, other: &#name) -> #name {
|
|
|
|
let mut ret = self;
|
|
|
|
ret.add_assign(other);
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::std::ops::Add for #name {
|
|
|
|
type Output = #name;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn add(self, other: #name) -> Self {
|
|
|
|
self + &other
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'r> ::std::ops::AddAssign<&'r #name> for #name {
|
|
|
|
#[inline]
|
|
|
|
fn add_assign(&mut self, other: &#name) {
|
|
|
|
// This cannot exceed the backing capacity.
|
|
|
|
self.0.add_nocarry(&other.0);
|
|
|
|
|
|
|
|
// However, it may need to be reduced.
|
|
|
|
self.reduce();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::std::ops::AddAssign for #name {
|
|
|
|
#[inline]
|
|
|
|
fn add_assign(&mut self, other: #name) {
|
|
|
|
self.add_assign(&other);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'r> ::std::ops::Sub<&'r #name> for #name {
|
|
|
|
type Output = #name;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn sub(self, other: &#name) -> Self {
|
|
|
|
let mut ret = self;
|
|
|
|
ret.sub_assign(other);
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::std::ops::Sub for #name {
|
|
|
|
type Output = #name;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn sub(self, other: #name) -> Self {
|
|
|
|
self - &other
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'r> ::std::ops::SubAssign<&'r #name> for #name {
|
|
|
|
#[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);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.0.sub_noborrow(&other.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::std::ops::SubAssign for #name {
|
|
|
|
#[inline]
|
|
|
|
fn sub_assign(&mut self, other: #name) {
|
|
|
|
self.sub_assign(&other);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'r> ::std::ops::Mul<&'r #name> for #name {
|
|
|
|
type Output = #name;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn mul(self, other: &#name) -> Self {
|
|
|
|
let mut ret = self;
|
|
|
|
ret.mul_assign(other);
|
|
|
|
ret
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::std::ops::Mul for #name {
|
|
|
|
type Output = #name;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn mul(self, other: #name) -> Self {
|
|
|
|
self * &other
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'r> ::std::ops::MulAssign<&'r #name> for #name {
|
|
|
|
#[inline]
|
|
|
|
fn mul_assign(&mut self, other: &#name)
|
|
|
|
{
|
|
|
|
#multiply_impl
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ::std::ops::MulAssign for #name {
|
|
|
|
#[inline]
|
|
|
|
fn mul_assign(&mut self, other: #name)
|
|
|
|
{
|
|
|
|
self.mul_assign(&other);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-26 10:47:35 -07:00
|
|
|
impl ::ff::PrimeField for #name {
|
|
|
|
type Repr = #repr;
|
|
|
|
|
2018-06-28 12:07:35 -07:00
|
|
|
fn from_repr(r: #repr) -> Result<#name, PrimeFieldDecodingError> {
|
2017-06-26 10:47:35 -07:00
|
|
|
let mut r = #name(r);
|
|
|
|
if r.is_valid() {
|
|
|
|
r.mul_assign(&#name(R2));
|
|
|
|
|
|
|
|
Ok(r)
|
|
|
|
} else {
|
2018-06-28 12:07:35 -07:00
|
|
|
Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0)))
|
2017-06-26 10:47:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn into_repr(&self) -> #repr {
|
|
|
|
let mut r = *self;
|
|
|
|
r.mont_reduce(
|
|
|
|
#into_repr_params
|
|
|
|
);
|
|
|
|
|
|
|
|
r.0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn char() -> #repr {
|
|
|
|
MODULUS
|
|
|
|
}
|
|
|
|
|
2018-06-28 12:07:35 -07:00
|
|
|
const NUM_BITS: u32 = MODULUS_BITS;
|
2017-06-26 10:47:35 -07:00
|
|
|
|
2018-06-28 12:07:35 -07:00
|
|
|
const CAPACITY: u32 = Self::NUM_BITS - 1;
|
2017-06-27 08:14:24 -07:00
|
|
|
|
|
|
|
fn multiplicative_generator() -> Self {
|
|
|
|
#name(GENERATOR)
|
|
|
|
}
|
|
|
|
|
2018-06-28 12:07:35 -07:00
|
|
|
const S: u32 = S;
|
2017-06-27 08:14:24 -07:00
|
|
|
|
|
|
|
fn root_of_unity() -> Self {
|
|
|
|
#name(ROOT_OF_UNITY)
|
|
|
|
}
|
2017-06-26 10:47:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ::ff::Field for #name {
|
2019-07-10 15:35:05 -07:00
|
|
|
/// Computes a uniformly random element using rejection sampling.
|
|
|
|
fn random<R: ::rand_core::RngCore>(rng: &mut R) -> Self {
|
|
|
|
loop {
|
|
|
|
let mut tmp = {
|
|
|
|
let mut repr = [0u64; #limbs];
|
|
|
|
for i in 0..#limbs {
|
|
|
|
repr[i] = rng.next_u64();
|
|
|
|
}
|
|
|
|
#name(#repr(repr))
|
|
|
|
};
|
|
|
|
|
2019-07-26 11:43:42 -07:00
|
|
|
// Mask away the unused most-significant bits.
|
2019-07-10 15:35:05 -07:00
|
|
|
tmp.0.as_mut()[#top_limb_index] &= 0xffffffffffffffff >> REPR_SHAVE_BITS;
|
|
|
|
|
|
|
|
if tmp.is_valid() {
|
|
|
|
return tmp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-26 10:47:35 -07:00
|
|
|
#[inline]
|
|
|
|
fn zero() -> Self {
|
|
|
|
#name(#repr::from(0))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn one() -> Self {
|
|
|
|
#name(R)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn is_zero(&self) -> bool {
|
|
|
|
self.0.is_zero()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-12-12 14:59:18 -08:00
|
|
|
fn double(&self) -> Self {
|
|
|
|
let mut ret = *self;
|
|
|
|
|
2017-06-26 10:47:35 -07:00
|
|
|
// This cannot exceed the backing capacity.
|
2019-12-12 14:59:18 -08:00
|
|
|
ret.0.mul2();
|
2017-06-26 10:47:35 -07:00
|
|
|
|
|
|
|
// However, it may need to be reduced.
|
2019-12-12 14:59:18 -08:00
|
|
|
ret.reduce();
|
|
|
|
|
|
|
|
ret
|
2017-06-26 10:47:35 -07:00
|
|
|
}
|
|
|
|
|
2019-05-14 06:18:37 -07:00
|
|
|
/// WARNING: THIS IS NOT ACTUALLY CONSTANT TIME YET!
|
|
|
|
/// TODO: Make this constant-time.
|
|
|
|
fn invert(&self) -> ::subtle::CtOption<Self> {
|
2017-06-26 10:47:35 -07:00
|
|
|
if self.is_zero() {
|
2019-05-14 06:18:37 -07:00
|
|
|
::subtle::CtOption::new(#name::zero(), ::subtle::Choice::from(0))
|
2017-06-26 10:47:35 -07:00
|
|
|
} else {
|
|
|
|
// Guajardo Kumar Paar Pelzl
|
|
|
|
// Efficient Software-Implementation of Finite Fields with Applications to Cryptography
|
|
|
|
// Algorithm 16 (BEA for Inversion in Fp)
|
|
|
|
|
|
|
|
let one = #repr::from(1);
|
|
|
|
|
|
|
|
let mut u = self.0;
|
|
|
|
let mut v = MODULUS;
|
|
|
|
let mut b = #name(R2); // Avoids unnecessary reduction step.
|
|
|
|
let mut c = Self::zero();
|
|
|
|
|
|
|
|
while u != one && v != one {
|
|
|
|
while u.is_even() {
|
|
|
|
u.div2();
|
|
|
|
|
|
|
|
if b.0.is_even() {
|
|
|
|
b.0.div2();
|
|
|
|
} else {
|
|
|
|
b.0.add_nocarry(&MODULUS);
|
|
|
|
b.0.div2();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while v.is_even() {
|
|
|
|
v.div2();
|
|
|
|
|
|
|
|
if c.0.is_even() {
|
|
|
|
c.0.div2();
|
|
|
|
} else {
|
|
|
|
c.0.add_nocarry(&MODULUS);
|
|
|
|
c.0.div2();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if v < u {
|
|
|
|
u.sub_noborrow(&v);
|
|
|
|
b.sub_assign(&c);
|
|
|
|
} else {
|
|
|
|
v.sub_noborrow(&u);
|
|
|
|
c.sub_assign(&b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if u == one {
|
2019-05-14 06:18:37 -07:00
|
|
|
::subtle::CtOption::new(b, ::subtle::Choice::from(1))
|
2017-06-26 10:47:35 -07:00
|
|
|
} else {
|
2019-05-14 06:18:37 -07:00
|
|
|
::subtle::CtOption::new(c, ::subtle::Choice::from(1))
|
2017-06-26 10:47:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
fn frobenius_map(&mut self, _: usize) {
|
|
|
|
// This has no effect in a prime field.
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-12-12 15:09:28 -08:00
|
|
|
fn square(&self) -> Self
|
2017-06-26 10:47:35 -07:00
|
|
|
{
|
|
|
|
#squaring_impl
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl #name {
|
|
|
|
/// Determines if the element is really in the field. This is only used
|
|
|
|
/// internally.
|
|
|
|
#[inline(always)]
|
|
|
|
fn is_valid(&self) -> bool {
|
|
|
|
self.0 < MODULUS
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Subtracts the modulus from this element if this element is not in the
|
|
|
|
/// field. Only used interally.
|
|
|
|
#[inline(always)]
|
|
|
|
fn reduce(&mut self) {
|
|
|
|
if !self.is_valid() {
|
|
|
|
self.0.sub_noborrow(&MODULUS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
fn mont_reduce(
|
|
|
|
&mut self,
|
|
|
|
#mont_paramlist
|
|
|
|
)
|
|
|
|
{
|
|
|
|
// The Montgomery reduction here is based on Algorithm 14.32 in
|
|
|
|
// Handbook of Applied Cryptography
|
|
|
|
// <http://cacr.uwaterloo.ca/hac/about/chap14.pdf>.
|
|
|
|
|
2017-06-27 08:40:58 -07:00
|
|
|
#montgomery_impl
|
2017-06-26 10:47:35 -07:00
|
|
|
|
|
|
|
self.reduce();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|