From 755fc7aba8e5b3a2d26591989a52e6f52a7e9333 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 26 Jun 2018 10:48:27 -0400 Subject: [PATCH 01/11] cargo fmt --- ff_derive/src/lib.rs | 298 ++++++++++++++++++++----------------------- src/lib.rs | 59 ++++----- 2 files changed, 164 insertions(+), 193 deletions(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index e507cd736..9621548f9 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -1,4 +1,4 @@ -#![recursion_limit="1024"] +#![recursion_limit = "1024"] extern crate proc_macro; extern crate syn; @@ -6,39 +6,38 @@ extern crate syn; extern crate quote; extern crate num_bigint; -extern crate num_traits; extern crate num_integer; +extern crate num_traits; -use num_integer::Integer; -use num_traits::{Zero, One, ToPrimitive}; use num_bigint::BigUint; +use num_integer::Integer; +use num_traits::{One, ToPrimitive, Zero}; use std::str::FromStr; #[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus, PrimeFieldGenerator))] -pub fn prime_field( - input: proc_macro::TokenStream -) -> proc_macro::TokenStream -{ +pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream { // Construct a string representation of the type definition let s = input.to_string(); - + // Parse the string representation let ast = syn::parse_derive_input(&s).unwrap(); // The struct we're deriving for is a wrapper around a "Repr" type we must construct. let repr_ident = fetch_wrapped_ident(&ast.body) - .expect("PrimeField derive only operates over tuple structs of a single item"); + .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") - .parse().expect("PrimeFieldModulus should be a number"); + .expect("Please supply a PrimeFieldModulus attribute") + .parse() + .expect("PrimeFieldModulus should be a number"); // We may be provided with a generator of p - 1 order. It is required that this generator be quadratic // nonresidue. let generator: BigUint = fetch_attr("PrimeFieldGenerator", &ast.attrs) - .expect("Please supply a PrimeFieldGenerator attribute") - .parse().expect("PrimeFieldGenerator should be a number"); + .expect("Please supply a PrimeFieldGenerator attribute") + .parse() + .expect("PrimeFieldGenerator should be a number"); // The arithmetic in this library only works if the modulus*2 is smaller than the backing // representation. Compute the number of limbs we need. @@ -55,18 +54,21 @@ pub fn prime_field( let mut gen = quote::Tokens::new(); gen.append(prime_field_repr_impl(&repr_ident, limbs)); - gen.append(prime_field_constants_and_sqrt(&ast.ident, &repr_ident, modulus, limbs, generator)); + gen.append(prime_field_constants_and_sqrt( + &ast.ident, + &repr_ident, + modulus, + limbs, + generator, + )); gen.append(prime_field_impl(&ast.ident, &repr_ident, limbs)); - + // Return the generated impl gen.parse().unwrap() } /// Fetches the ident being wrapped by the type we're deriving. -fn fetch_wrapped_ident( - body: &syn::Body -) -> Option -{ +fn fetch_wrapped_ident(body: &syn::Body) -> Option { match body { &syn::Body::Struct(ref variant_data) => { let fields = variant_data.fields(); @@ -76,11 +78,11 @@ fn fetch_wrapped_ident( if path.segments.len() == 1 { return Some(path.segments[0].ident.clone()); } - }, + } _ => {} } } - }, + } _ => {} }; @@ -88,22 +90,14 @@ fn fetch_wrapped_ident( } /// Fetch an attribute string from the derived struct. -fn fetch_attr( - name: &str, - attrs: &[syn::Attribute] -) -> Option -{ +fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option { for attr in attrs { if attr.name() == name { match attr.value { - syn::MetaItem::NameValue(_, ref val) => { - match val { - &syn::Lit::Str(ref s, _) => { - return Some(s.clone()) - }, - _ => { - panic!("attribute {} should be a string", name); - } + syn::MetaItem::NameValue(_, ref val) => match val { + &syn::Lit::Str(ref s, _) => return Some(s.clone()), + _ => { + panic!("attribute {} should be a string", name); } }, _ => { @@ -117,11 +111,7 @@ fn fetch_attr( } // Implement PrimeFieldRepr for the wrapped ident `repr` with `limbs` limbs. -fn prime_field_repr_impl( - repr: &syn::Ident, - limbs: usize -) -> quote::Tokens -{ +fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> quote::Tokens { quote! { #[derive(Copy, Clone, PartialEq, Eq, Default)] pub struct #repr(pub [u64; #limbs]); @@ -263,11 +253,7 @@ fn prime_field_repr_impl( } /// Convert BigUint into a vector of 64-bit limbs. -fn biguint_to_u64_vec( - mut v: BigUint, - limbs: usize -) -> Vec -{ +fn biguint_to_u64_vec(mut v: BigUint, limbs: usize) -> Vec { let m = BigUint::one() << 64; let mut ret = vec![]; @@ -285,10 +271,7 @@ fn biguint_to_u64_vec( ret } -fn biguint_num_bits( - mut v: BigUint -) -> u32 -{ +fn biguint_num_bits(mut v: BigUint) -> u32 { let mut bits = 0; while v != BigUint::zero() { @@ -300,17 +283,12 @@ fn biguint_num_bits( } /// BigUint modular exponentiation by square-and-multiply. -fn exp( - base: BigUint, - exp: &BigUint, - modulus: &BigUint -) -> BigUint -{ +fn exp(base: BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint { let mut ret = BigUint::one(); for i in exp.to_bytes_be() - .into_iter() - .flat_map(|x| (0..8).rev().map(move |i| (x >> i).is_odd())) + .into_iter() + .flat_map(|x| (0..8).rev().map(move |i| (x >> i).is_odd())) { ret = (&ret * &ret) % modulus; if i { @@ -327,9 +305,13 @@ fn test_exp() { exp( BigUint::from_str("4398572349857239485729348572983472345").unwrap(), &BigUint::from_str("5489673498567349856734895").unwrap(), - &BigUint::from_str("52435875175126190479447740508185965837690552500527637822603658699938581184513").unwrap() + &BigUint::from_str( + "52435875175126190479447740508185965837690552500527637822603658699938581184513" + ).unwrap() ), - BigUint::from_str("4371221214068404307866768905142520595925044802278091865033317963560480051536").unwrap() + BigUint::from_str( + "4371221214068404307866768905142520595925044802278091865033317963560480051536" + ).unwrap() ); } @@ -338,14 +320,13 @@ fn prime_field_constants_and_sqrt( repr: &syn::Ident, modulus: BigUint, limbs: usize, - generator: BigUint -) -> quote::Tokens -{ + generator: BigUint, +) -> quote::Tokens { let modulus_num_bits = biguint_num_bits(modulus.clone()); // 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 - // 3 bits from the beginning of a randomly sampled 384 bit representation to + // 3 bits from the beginning of a randomly sampled 384 bit representation to // reduce the cost of rejection sampling. let repr_shave_bits = (64 * limbs as u32) - biguint_num_bits(modulus.clone()); @@ -361,91 +342,96 @@ fn prime_field_constants_and_sqrt( } // Compute 2^s root of unity given the generator - let root_of_unity = biguint_to_u64_vec((exp(generator.clone(), &t, &modulus) * &r) % &modulus, limbs); + let root_of_unity = biguint_to_u64_vec( + (exp(generator.clone(), &t, &modulus) * &r) % &modulus, + limbs, + ); let generator = biguint_to_u64_vec((generator.clone() * &r) % &modulus, limbs); let sqrt_impl = - if (&modulus % BigUint::from_str("4").unwrap()) == BigUint::from_str("3").unwrap() { - let mod_minus_3_over_4 = biguint_to_u64_vec((&modulus - BigUint::from_str("3").unwrap()) >> 2, limbs); + if (&modulus % BigUint::from_str("4").unwrap()) == BigUint::from_str("3").unwrap() { + let mod_minus_3_over_4 = + biguint_to_u64_vec((&modulus - BigUint::from_str("3").unwrap()) >> 2, limbs); - // Compute -R as (m - r) - let rneg = biguint_to_u64_vec(&modulus - &r, limbs); + // Compute -R as (m - r) + let rneg = biguint_to_u64_vec(&modulus - &r, limbs); - quote!{ - impl ::ff::SqrtField for #name { - fn sqrt(&self) -> Option { - // Shank's algorithm for q mod 4 = 3 - // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2) + quote!{ + impl ::ff::SqrtField for #name { + fn sqrt(&self) -> Option { + // Shank's algorithm for q mod 4 = 3 + // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2) - let mut a1 = self.pow(#mod_minus_3_over_4); + let mut a1 = self.pow(#mod_minus_3_over_4); - let mut a0 = a1; - a0.square(); - a0.mul_assign(self); + let mut a0 = a1; + a0.square(); + a0.mul_assign(self); - if a0.0 == #repr(#rneg) { - None - } else { - a1.mul_assign(self); - Some(a1) + if a0.0 == #repr(#rneg) { + None + } else { + a1.mul_assign(self); + Some(a1) + } } } } - } - } else if (&modulus % BigUint::from_str("16").unwrap()) == BigUint::from_str("1").unwrap() { - let mod_minus_1_over_2 = biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs); - let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1, limbs); - let t = biguint_to_u64_vec(t.clone(), limbs); + } else if (&modulus % BigUint::from_str("16").unwrap()) == BigUint::from_str("1").unwrap() { + let mod_minus_1_over_2 = + biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs); + let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1, limbs); + let t = biguint_to_u64_vec(t.clone(), limbs); - quote!{ - impl ::ff::SqrtField for #name { - fn sqrt(&self) -> Option { - // Tonelli-Shank's algorithm for q mod 16 = 1 - // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) + quote!{ + impl ::ff::SqrtField for #name { + fn sqrt(&self) -> Option { + // Tonelli-Shank's algorithm for q mod 16 = 1 + // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) - if self.is_zero() { - return Some(*self); - } - - if self.pow(#mod_minus_1_over_2) != Self::one() { - None - } else { - let mut c = #name(#repr(#root_of_unity)); - let mut r = self.pow(#t_plus_1_over_2); - let mut t = self.pow(#t); - let mut m = #s; - - while t != Self::one() { - let mut i = 1; - { - let mut t2i = t; - t2i.square(); - loop { - if t2i == Self::one() { - break; - } - t2i.square(); - i += 1; - } - } - - for _ in 0..(m - i - 1) { - c.square(); - } - r.mul_assign(&c); - c.square(); - t.mul_assign(&c); - m = i; + if self.is_zero() { + return Some(*self); } - Some(r) + if self.pow(#mod_minus_1_over_2) != Self::one() { + None + } else { + let mut c = #name(#repr(#root_of_unity)); + let mut r = self.pow(#t_plus_1_over_2); + let mut t = self.pow(#t); + let mut m = #s; + + while t != Self::one() { + let mut i = 1; + { + let mut t2i = t; + t2i.square(); + loop { + if t2i == Self::one() { + break; + } + t2i.square(); + i += 1; + } + } + + for _ in 0..(m - i - 1) { + c.square(); + } + r.mul_assign(&c); + c.square(); + t.mul_assign(&c); + m = i; + } + + Some(r) + } } } } - } - } else { - quote!{} - }; + } else { + quote!{} + }; // Compute R^2 mod m let r2 = biguint_to_u64_vec((&r * &r) % &modulus, limbs); @@ -496,12 +482,7 @@ fn prime_field_constants_and_sqrt( } /// Implement PrimeField for the derived type. -fn prime_field_impl( - name: &syn::Ident, - repr: &syn::Ident, - limbs: usize -) -> quote::Tokens -{ +fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote::Tokens { // Returns r{n} as an ident. fn get_temp(n: usize) -> syn::Ident { syn::Ident::from(format!("r{}", n)) @@ -511,20 +492,18 @@ fn prime_field_impl( // r0: u64, mut r1: u64, mut r2: u64, ... let mut mont_paramlist = quote::Tokens::new(); mont_paramlist.append_separated( - (0..(limbs*2)).map(|i| (i, get_temp(i))) - .map(|(i, x)| { - if i != 0 { - quote!{mut #x: u64} - } else { - quote!{#x: u64} - } - }), - "," + (0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| { + if i != 0 { + quote!{mut #x: u64} + } else { + quote!{#x: u64} + } + }), + ",", ); // Implement montgomery reduction for some number of limbs - fn mont_impl(limbs: usize) -> quote::Tokens - { + fn mont_impl(limbs: usize) -> quote::Tokens { let mut gen = quote::Tokens::new(); for i in 0..limbs { @@ -574,16 +553,15 @@ fn prime_field_impl( gen } - fn sqr_impl(a: quote::Tokens, limbs: usize) -> quote::Tokens - { + fn sqr_impl(a: quote::Tokens, limbs: usize) -> quote::Tokens { let mut gen = quote::Tokens::new(); - for i in 0..(limbs-1) { + for i in 0..(limbs - 1) { gen.append(quote!{ let mut carry = 0; }); - for j in (i+1)..limbs { + for j in (i + 1)..limbs { let temp = get_temp(i + j); if i == 0 { gen.append(quote!{ @@ -603,7 +581,7 @@ fn prime_field_impl( }); } - for i in 1..(limbs*2) { + for i in 1..(limbs * 2) { let k = get_temp(i); if i == 1 { @@ -611,7 +589,7 @@ fn prime_field_impl( let tmp0 = #k >> 63; let #k = #k << 1; }); - } else if i == (limbs*2 - 1) { + } else if i == (limbs * 2 - 1) { gen.append(quote!{ let #k = tmp0; }); @@ -648,7 +626,7 @@ fn prime_field_impl( } let mut mont_calling = quote::Tokens::new(); - mont_calling.append_separated((0..(limbs*2)).map(|i| get_temp(i)), ","); + mont_calling.append_separated((0..(limbs * 2)).map(|i| get_temp(i)), ","); gen.append(quote!{ self.mont_reduce(#mont_calling); @@ -657,8 +635,7 @@ fn prime_field_impl( gen } - fn mul_impl(a: quote::Tokens, b: quote::Tokens, limbs: usize) -> quote::Tokens - { + fn mul_impl(a: quote::Tokens, b: quote::Tokens, limbs: usize) -> quote::Tokens { let mut gen = quote::Tokens::new(); for i in 0..limbs { @@ -688,7 +665,7 @@ fn prime_field_impl( } let mut mont_calling = quote::Tokens::new(); - mont_calling.append_separated((0..(limbs*2)).map(|i| get_temp(i)), ","); + mont_calling.append_separated((0..(limbs * 2)).map(|i| get_temp(i)), ","); gen.append(quote!{ self.mont_reduce(#mont_calling); @@ -704,9 +681,10 @@ fn prime_field_impl( // (self.0).0[0], (self.0).0[1], ..., 0, 0, 0, 0, ... let mut into_repr_params = quote::Tokens::new(); into_repr_params.append_separated( - (0..limbs).map(|i| quote!{ (self.0).0[#i] }) - .chain((0..limbs).map(|_| quote!{0})), - "," + (0..limbs) + .map(|i| quote!{ (self.0).0[#i] }) + .chain((0..limbs).map(|_| quote!{0})), + ",", ); quote!{ diff --git a/src/lib.rs b/src/lib.rs index 99a7e7c34..88696aca8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,15 +11,8 @@ pub use ff_derive::*; use std::fmt; /// This trait represents an element of a field. -pub trait Field: Sized + - Eq + - Copy + - Clone + - Send + - Sync + - fmt::Debug + - 'static + - rand::Rand +pub trait Field: + Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + 'static + rand::Rand { /// Returns the zero element of the field, the additive identity. fn zero() -> Self; @@ -57,8 +50,7 @@ pub trait Field: Sized + /// Exponentiates this element by a number represented with `u64` limbs, /// least significant digit first. - fn pow>(&self, exp: S) -> Self - { + fn pow>(&self, exp: S) -> Self { let mut res = Self::one(); for i in BitIterator::new(exp) { @@ -73,8 +65,7 @@ pub trait Field: Sized + } /// This trait represents an element of a field that has a square root operation described for it. -pub trait SqrtField: Field -{ +pub trait SqrtField: Field { /// Returns the square root of the field element, if it is /// quadratic residue. fn sqrt(&self) -> Option; @@ -83,18 +74,19 @@ pub trait SqrtField: Field /// 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 + - fmt::Debug + - 'static + - rand::Rand + - AsRef<[u64]> + - From +pub trait PrimeFieldRepr: + Sized + + Copy + + Clone + + Eq + + Ord + + Send + + Sync + + fmt::Debug + + 'static + + rand::Rand + + AsRef<[u64]> + + From { /// Subtract another reprensetation from this one, returning the borrow bit. fn sub_noborrow(&mut self, other: &Self) -> bool; @@ -124,8 +116,7 @@ pub trait PrimeFieldRepr: Sized + } /// This represents an element of a prime field. -pub trait PrimeField: Field -{ +pub trait PrimeField: Field { /// The prime field can be converted back and forth into this biginteger /// representation. type Repr: PrimeFieldRepr; @@ -162,17 +153,14 @@ pub trait PrimeField: Field pub struct BitIterator { t: E, - n: usize + n: usize, } impl> BitIterator { fn new(t: E) -> Self { let n = t.as_ref().len() * 64; - BitIterator { - t: t, - n: n - } + BitIterator { t: t, n: n } } } @@ -205,7 +193,12 @@ fn test_bit_iterator() { let expected = "1010010101111110101010000101101011101000011101110101001000011001100100100011011010001011011011010001011011101100110100111011010010110001000011110100110001100110011101101000101100011100100100100100001010011101010111110011101011000011101000111011011101011001"; - let mut a = BitIterator::new([0x429d5f3ac3a3b759, 0xb10f4c66768b1c92, 0x92368b6d16ecd3b4, 0xa57ea85ae8775219]); + let mut a = BitIterator::new([ + 0x429d5f3ac3a3b759, + 0xb10f4c66768b1c92, + 0x92368b6d16ecd3b4, + 0xa57ea85ae8775219, + ]); for e in expected.chars() { assert!(a.next().unwrap() == (e == '1')); From 428f4635557a9f773a63318fd1ff459f610e117a Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 27 Jun 2018 07:33:17 -0400 Subject: [PATCH 02/11] Migrate ff_derive to syn 0.14 and quote 0.6 --- ff_derive/Cargo.toml | 5 +- ff_derive/src/lib.rs | 169 +++++++++++++++++++++++++------------------ 2 files changed, 100 insertions(+), 74 deletions(-) diff --git a/ff_derive/Cargo.toml b/ff_derive/Cargo.toml index baba38503..ab24be993 100644 --- a/ff_derive/Cargo.toml +++ b/ff_derive/Cargo.toml @@ -12,8 +12,9 @@ repository = "https://github.com/ebfull/ff" proc-macro = true [dependencies] -syn = "0.11" -quote = "0.3" num-bigint = "0.1" num-traits = "0.1" num-integer = "0.1" +proc-macro2 = "0.4" +quote = "0.6" +syn = "0.14" diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index 9621548f9..6913b655d 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -1,6 +1,7 @@ #![recursion_limit = "1024"] extern crate proc_macro; +extern crate proc_macro2; extern crate syn; #[macro_use] extern crate quote; @@ -12,18 +13,16 @@ extern crate num_traits; use num_bigint::BigUint; use num_integer::Integer; use num_traits::{One, ToPrimitive, Zero}; +use quote::TokenStreamExt; use std::str::FromStr; #[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus, PrimeFieldGenerator))] pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - // Construct a string representation of the type definition - let s = input.to_string(); - - // Parse the string representation - let ast = syn::parse_derive_input(&s).unwrap(); + // 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.body) + 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 @@ -51,38 +50,40 @@ pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream { } } - let mut gen = quote::Tokens::new(); + let mut gen = proc_macro2::TokenStream::new(); - gen.append(prime_field_repr_impl(&repr_ident, limbs)); - gen.append(prime_field_constants_and_sqrt( + gen.extend(prime_field_repr_impl(&repr_ident, limbs)); + gen.extend(prime_field_constants_and_sqrt( &ast.ident, &repr_ident, modulus, limbs, generator, )); - gen.append(prime_field_impl(&ast.ident, &repr_ident, limbs)); + gen.extend(prime_field_impl(&ast.ident, &repr_ident, limbs)); // Return the generated impl - gen.parse().unwrap() + gen.into() } /// Fetches the ident being wrapped by the type we're deriving. -fn fetch_wrapped_ident(body: &syn::Body) -> Option { +fn fetch_wrapped_ident(body: &syn::Data) -> Option { match body { - &syn::Body::Struct(ref variant_data) => { - let fields = variant_data.fields(); - if fields.len() == 1 { - match fields[0].ty { - syn::Ty::Path(_, ref path) => { - if path.segments.len() == 1 { - return Some(path.segments[0].ident.clone()); + &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()); + } } + _ => {} } - _ => {} } } - } + _ => {} + }, _ => {} }; @@ -92,14 +93,18 @@ fn fetch_wrapped_ident(body: &syn::Body) -> Option { /// Fetch an attribute string from the derived struct. fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option { for attr in attrs { - if attr.name() == name { - match attr.value { - syn::MetaItem::NameValue(_, ref val) => match val { - &syn::Lit::Str(ref s, _) => return Some(s.clone()), - _ => { - panic!("attribute {} should be a string", name); + if let Some(meta) = attr.interpret_meta() { + match meta { + syn::Meta::NameValue(nv) => { + if nv.ident.to_string() == name { + match nv.lit { + syn::Lit::Str(ref s) => return Some(s.value()), + _ => { + panic!("attribute {} should be a string", name); + } + } } - }, + } _ => { panic!("attribute {} should be a string", name); } @@ -111,7 +116,7 @@ fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option { } // Implement PrimeFieldRepr for the wrapped ident `repr` with `limbs` limbs. -fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> quote::Tokens { +fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream { quote! { #[derive(Copy, Clone, PartialEq, Eq, Default)] pub struct #repr(pub [u64; #limbs]); @@ -253,7 +258,7 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> quote::Tokens { } /// Convert BigUint into a vector of 64-bit limbs. -fn biguint_to_u64_vec(mut v: BigUint, limbs: usize) -> Vec { +fn biguint_to_real_u64_vec(mut v: BigUint, limbs: usize) -> Vec { let m = BigUint::one() << 64; let mut ret = vec![]; @@ -271,6 +276,12 @@ fn biguint_to_u64_vec(mut v: BigUint, limbs: usize) -> Vec { ret } +/// 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,)*]) +} + fn biguint_num_bits(mut v: BigUint) -> u32 { let mut bits = 0; @@ -321,7 +332,7 @@ fn prime_field_constants_and_sqrt( modulus: BigUint, limbs: usize, generator: BigUint, -) -> quote::Tokens { +) -> proc_macro2::TokenStream { let modulus_num_bits = biguint_num_bits(modulus.clone()); // The number of bits we should "shave" from a randomly sampled reputation, i.e., @@ -437,7 +448,7 @@ 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 = biguint_to_u64_vec(modulus, limbs); + let modulus = biguint_to_real_u64_vec(modulus, limbs); // Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1 let mut inv = 1u64; @@ -449,7 +460,7 @@ 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,)*]); /// The number of bits needed to represent the modulus. const MODULUS_BITS: u32 = #modulus_num_bits; @@ -482,15 +493,19 @@ fn prime_field_constants_and_sqrt( } /// Implement PrimeField for the derived type. -fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote::Tokens { +fn prime_field_impl( + name: &syn::Ident, + repr: &syn::Ident, + limbs: usize, +) -> proc_macro2::TokenStream { // Returns r{n} as an ident. fn get_temp(n: usize) -> syn::Ident { - syn::Ident::from(format!("r{}", n)) + syn::Ident::new(&format!("r{}", n), proc_macro2::Span::call_site()) } // The parameter list for the mont_reduce() internal method. // r0: u64, mut r1: u64, mut r2: u64, ... - let mut mont_paramlist = quote::Tokens::new(); + let mut mont_paramlist = proc_macro2::TokenStream::new(); mont_paramlist.append_separated( (0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| { if i != 0 { @@ -499,17 +514,17 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote quote!{#x: u64} } }), - ",", + proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), ); // Implement montgomery reduction for some number of limbs - fn mont_impl(limbs: usize) -> quote::Tokens { - let mut gen = quote::Tokens::new(); + fn mont_impl(limbs: usize) -> proc_macro2::TokenStream { + let mut gen = proc_macro2::TokenStream::new(); for i in 0..limbs { { let temp = get_temp(i); - gen.append(quote!{ + gen.extend(quote!{ let k = #temp.wrapping_mul(INV); let mut carry = 0; ::ff::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry); @@ -518,7 +533,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote for j in 1..limbs { let temp = get_temp(i + j); - gen.append(quote!{ + gen.extend(quote!{ #temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry); }); } @@ -526,17 +541,17 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote let temp = get_temp(i + limbs); if i == 0 { - gen.append(quote!{ + gen.extend(quote!{ #temp = ::ff::adc(#temp, 0, &mut carry); }); } else { - gen.append(quote!{ + gen.extend(quote!{ #temp = ::ff::adc(#temp, carry2, &mut carry); }); } if i != (limbs - 1) { - gen.append(quote!{ + gen.extend(quote!{ let carry2 = carry; }); } @@ -545,7 +560,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote for i in 0..limbs { let temp = get_temp(limbs + i); - gen.append(quote!{ + gen.extend(quote!{ (self.0).0[#i] = #temp; }); } @@ -553,22 +568,22 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote gen } - fn sqr_impl(a: quote::Tokens, limbs: usize) -> quote::Tokens { - let mut gen = quote::Tokens::new(); + fn sqr_impl(a: proc_macro2::TokenStream, limbs: usize) -> proc_macro2::TokenStream { + let mut gen = proc_macro2::TokenStream::new(); for i in 0..(limbs - 1) { - gen.append(quote!{ + gen.extend(quote!{ let mut carry = 0; }); for j in (i + 1)..limbs { let temp = get_temp(i + j); if i == 0 { - gen.append(quote!{ + gen.extend(quote!{ let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#j], &mut carry); }); } else { - gen.append(quote!{ + gen.extend(quote!{ let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#a.0).0[#j], &mut carry); }); } @@ -576,7 +591,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote let temp = get_temp(i + limbs); - gen.append(quote!{ + gen.extend(quote!{ let #temp = carry; }); } @@ -585,16 +600,16 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote let k = get_temp(i); if i == 1 { - gen.append(quote!{ + gen.extend(quote!{ let tmp0 = #k >> 63; let #k = #k << 1; }); } else if i == (limbs * 2 - 1) { - gen.append(quote!{ + gen.extend(quote!{ let #k = tmp0; }); } else { - gen.append(quote!{ + gen.extend(quote!{ let tmp1 = #k >> 63; let #k = #k << 1; let #k = #k | tmp0; @@ -603,7 +618,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote } } - gen.append(quote!{ + gen.extend(quote!{ let mut carry = 0; }); @@ -611,35 +626,42 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote let temp0 = get_temp(i * 2); let temp1 = get_temp(i * 2 + 1); if i == 0 { - gen.append(quote!{ + gen.extend(quote!{ let #temp0 = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); }); } else { - gen.append(quote!{ + gen.extend(quote!{ let #temp0 = ::ff::mac_with_carry(#temp0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); }); } - gen.append(quote!{ + gen.extend(quote!{ let #temp1 = ::ff::adc(#temp1, 0, &mut carry); }); } - let mut mont_calling = quote::Tokens::new(); - mont_calling.append_separated((0..(limbs * 2)).map(|i| get_temp(i)), ","); + 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), + ); - gen.append(quote!{ + gen.extend(quote!{ self.mont_reduce(#mont_calling); }); gen } - fn mul_impl(a: quote::Tokens, b: quote::Tokens, limbs: usize) -> quote::Tokens { - let mut gen = quote::Tokens::new(); + fn mul_impl( + a: proc_macro2::TokenStream, + b: proc_macro2::TokenStream, + limbs: usize, + ) -> proc_macro2::TokenStream { + let mut gen = proc_macro2::TokenStream::new(); for i in 0..limbs { - gen.append(quote!{ + gen.extend(quote!{ let mut carry = 0; }); @@ -647,11 +669,11 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote let temp = get_temp(i + j); if i == 0 { - gen.append(quote!{ + gen.extend(quote!{ let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry); }); } else { - gen.append(quote!{ + gen.extend(quote!{ let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#b.0).0[#j], &mut carry); }); } @@ -659,15 +681,18 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote let temp = get_temp(i + limbs); - gen.append(quote!{ + gen.extend(quote!{ let #temp = carry; }); } - let mut mont_calling = quote::Tokens::new(); - mont_calling.append_separated((0..(limbs * 2)).map(|i| get_temp(i)), ","); + 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), + ); - gen.append(quote!{ + gen.extend(quote!{ self.mont_reduce(#mont_calling); }); @@ -679,12 +704,12 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote let montgomery_impl = mont_impl(limbs); // (self.0).0[0], (self.0).0[1], ..., 0, 0, 0, 0, ... - let mut into_repr_params = quote::Tokens::new(); + let mut into_repr_params = proc_macro2::TokenStream::new(); into_repr_params.append_separated( (0..limbs) .map(|i| quote!{ (self.0).0[#i] }) .chain((0..limbs).map(|_| quote!{0})), - ",", + proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), ); quote!{ From 1a3a2bec741c58717aa4338e048ec98631f71d9e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 27 Jun 2018 07:37:25 -0400 Subject: [PATCH 03/11] Update other ff_derive dependencies --- ff_derive/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ff_derive/Cargo.toml b/ff_derive/Cargo.toml index ab24be993..65a233a61 100644 --- a/ff_derive/Cargo.toml +++ b/ff_derive/Cargo.toml @@ -12,8 +12,8 @@ repository = "https://github.com/ebfull/ff" proc-macro = true [dependencies] -num-bigint = "0.1" -num-traits = "0.1" +num-bigint = "0.2" +num-traits = "0.2" num-integer = "0.1" proc-macro2 = "0.4" quote = "0.6" From 8201a3933f89560d7f5c434b5668e002f1abecaa Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 27 Jun 2018 07:53:31 -0400 Subject: [PATCH 04/11] Pull in arith changes from pairing --- Cargo.toml | 4 ++ src/lib.rs | 134 +++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 113 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6e1fde770..4d8b37c3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,7 @@ repository = "https://github.com/ebfull/ff" [dependencies] rand = "0.3" ff_derive = { version = "0.2.0", path = "ff_derive" } + +[features] +u128-support = [] +default = [] diff --git a/src/lib.rs b/src/lib.rs index 88696aca8..8bdecc7e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -207,35 +207,119 @@ fn test_bit_iterator() { assert!(a.next().is_none()); } -/// Calculate a - b - borrow, returning the result and modifying -/// the borrow value. -#[inline(always)] -pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 { - let tmp = (1u128 << 64) + (a as u128) - (b as u128) - (*borrow as u128); +pub use self::arith_impl::*; - *borrow = if tmp >> 64 == 0 { 1 } else { 0 }; +#[cfg(feature = "u128-support")] +mod arith_impl { + /// Calculate a - b - borrow, returning the result and modifying + /// the borrow value. + #[inline(always)] + pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 { + let tmp = (1u128 << 64) + u128::from(a) - u128::from(b) - u128::from(*borrow); - tmp as u64 + *borrow = if tmp >> 64 == 0 { 1 } else { 0 }; + + tmp as u64 + } + + /// Calculate a + b + carry, returning the sum and modifying the + /// carry value. + #[inline(always)] + pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 { + let tmp = u128::from(a) + u128::from(b) + u128::from(*carry); + + *carry = (tmp >> 64) as u64; + + tmp as u64 + } + + /// Calculate a + (b * c) + carry, returning the least significant digit + /// and setting carry to the most significant digit. + #[inline(always)] + pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 { + let tmp = (u128::from(a)) + u128::from(b) * u128::from(c) + u128::from(*carry); + + *carry = (tmp >> 64) as u64; + + tmp as u64 + } } -/// Calculate a + b + carry, returning the sum and modifying the -/// carry value. -#[inline(always)] -pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 { - let tmp = (a as u128) + (b as u128) + (*carry as u128); +#[cfg(not(feature = "u128-support"))] +mod arith_impl { + #[inline(always)] + fn split_u64(i: u64) -> (u64, u64) { + (i >> 32, i & 0xFFFFFFFF) + } - *carry = (tmp >> 64) as u64; + #[inline(always)] + fn combine_u64(hi: u64, lo: u64) -> u64 { + (hi << 32) | lo + } - tmp as u64 -} - -/// Calculate a + (b * c) + carry, returning the least significant digit -/// and setting carry to the most significant digit. -#[inline(always)] -pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 { - let tmp = (a as u128) + (b as u128) * (c as u128) + (*carry as u128); - - *carry = (tmp >> 64) as u64; - - tmp as u64 + /// Calculate a - b - borrow, returning the result and modifying + /// the borrow value. + #[inline(always)] + pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 { + let (a_hi, a_lo) = split_u64(a); + let (b_hi, b_lo) = split_u64(b); + let (b, r0) = split_u64((1 << 32) + a_lo - b_lo - *borrow); + let (b, r1) = split_u64((1 << 32) + a_hi - b_hi - ((b == 0) as u64)); + + *borrow = (b == 0) as u64; + + combine_u64(r1, r0) + } + + /// Calculate a + b + carry, returning the sum and modifying the + /// carry value. + #[inline(always)] + pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 { + let (a_hi, a_lo) = split_u64(a); + let (b_hi, b_lo) = split_u64(b); + let (carry_hi, carry_lo) = split_u64(*carry); + + let (t, r0) = split_u64(a_lo + b_lo + carry_lo); + let (t, r1) = split_u64(t + a_hi + b_hi + carry_hi); + + *carry = t; + + combine_u64(r1, r0) + } + + /// Calculate a + (b * c) + carry, returning the least significant digit + /// and setting carry to the most significant digit. + #[inline(always)] + pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 { + /* + [ b_hi | b_lo ] + [ c_hi | c_lo ] * + ------------------------------------------- + [ b_lo * c_lo ] <-- w + [ b_hi * c_lo ] <-- x + [ b_lo * c_hi ] <-- y + [ b_hi * c_lo ] <-- z + [ a_hi | a_lo ] + [ C_hi | C_lo ] + */ + + let (a_hi, a_lo) = split_u64(a); + let (b_hi, b_lo) = split_u64(b); + let (c_hi, c_lo) = split_u64(c); + let (carry_hi, carry_lo) = split_u64(*carry); + + let (w_hi, w_lo) = split_u64(b_lo * c_lo); + let (x_hi, x_lo) = split_u64(b_hi * c_lo); + let (y_hi, y_lo) = split_u64(b_lo * c_hi); + let (z_hi, z_lo) = split_u64(b_hi * c_hi); + + let (t, r0) = split_u64(w_lo + a_lo + carry_lo); + let (t, r1) = split_u64(t + w_hi + x_lo + y_lo + a_hi + carry_hi); + let (t, r2) = split_u64(t + x_hi + y_hi + z_lo); + let (_, r3) = split_u64(t + z_hi); + + *carry = combine_u64(r3, r2); + + combine_u64(r1, r0) + } } From 58cb06ee92432f6f447227bfbfa1973305b03ffc Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 27 Jun 2018 08:03:36 -0400 Subject: [PATCH 05/11] Pull in trait changes from pairing --- Cargo.toml | 1 + src/lib.rs | 180 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 160 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4d8b37c3f..195b1078a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ license = "MIT/Apache-2.0" repository = "https://github.com/ebfull/ff" [dependencies] +byteorder = "1" rand = "0.3" ff_derive = { version = "0.2.0", path = "ff_derive" } diff --git a/src/lib.rs b/src/lib.rs index 8bdecc7e8..541fe76a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ -#![feature(i128_type)] #![allow(unused_imports)] +extern crate byteorder; extern crate rand; #[macro_use] @@ -8,11 +8,13 @@ extern crate ff_derive; pub use ff_derive::*; +use std::error::Error; use std::fmt; +use std::io::{self, Read, Write}; /// This trait represents an element of a field. pub trait Field: - Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + 'static + rand::Rand + Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static + rand::Rand { /// Returns the zero element of the field, the additive identity. fn zero() -> Self; @@ -53,8 +55,15 @@ pub trait Field: fn pow>(&self, exp: S) -> Self { let mut res = Self::one(); + let mut found_one = false; + for i in BitIterator::new(exp) { - res.square(); + if found_one { + res.square(); + } else { + found_one = i; + } + if i { res.mul_assign(self); } @@ -66,6 +75,9 @@ pub trait Field: /// This trait represents an element of a field that has a square root operation described for it. pub trait SqrtField: Field { + /// Returns the Legendre symbol of the field element. + fn legendre(&self) -> LegendreSymbol; + /// Returns the square root of the field element, if it is /// quadratic residue. fn sqrt(&self) -> Option; @@ -82,19 +94,23 @@ pub trait PrimeFieldRepr: + Ord + Send + Sync + + Default + fmt::Debug + + fmt::Display + 'static + rand::Rand + AsRef<[u64]> + + AsMut<[u64]> + From { - /// Subtract another reprensetation from this one, returning the borrow bit. - fn sub_noborrow(&mut self, other: &Self) -> bool; + /// Subtract another represetation from this one. + fn sub_noborrow(&mut self, other: &Self); - /// Add another representation to this one, returning the carry bit. - fn add_nocarry(&mut self, other: &Self) -> bool; + /// Add another representation to this one. + fn add_nocarry(&mut self, other: &Self); - /// Compute the number of bits needed to encode this number. + /// 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. @@ -110,57 +126,179 @@ pub trait PrimeFieldRepr: /// 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. + fn write_be(&self, mut writer: W) -> io::Result<()> { + use byteorder::{BigEndian, WriteBytesExt}; + + for digit in self.as_ref().iter().rev() { + writer.write_u64::(*digit)?; + } + + Ok(()) + } + + /// Reads a big endian integer into this representation. + fn read_be(&mut self, mut reader: R) -> io::Result<()> { + use byteorder::{BigEndian, ReadBytesExt}; + + for digit in self.as_mut().iter_mut().rev() { + *digit = reader.read_u64::()?; + } + + Ok(()) + } + + /// Writes this `PrimeFieldRepr` as a little endian integer. + fn write_le(&self, mut writer: W) -> io::Result<()> { + use byteorder::{LittleEndian, WriteBytesExt}; + + for digit in self.as_ref().iter() { + writer.write_u64::(*digit)?; + } + + Ok(()) + } + + /// Reads a little endian integer into this representation. + fn read_le(&mut self, mut reader: R) -> io::Result<()> { + use byteorder::{LittleEndian, ReadBytesExt}; + + for digit in self.as_mut().iter_mut() { + *digit = reader.read_u64::()?; + } + + Ok(()) + } +} + +#[derive(Debug, PartialEq)] +pub enum LegendreSymbol { + Zero = 0, + QuadraticResidue = 1, + QuadraticNonResidue = -1, +} + +/// 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(String), +} + +impl 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(ref repr) => { + write!(f, "{} is not an element of the field", repr) + } + } + } } /// This represents an element of a prime field. pub trait PrimeField: Field { /// The prime field can be converted back and forth into this biginteger /// representation. - type Repr: PrimeFieldRepr; + type Repr: PrimeFieldRepr + From; + + /// Interpret a string of numbers as a (congruent) prime field element. + /// Does not accept unnecessary leading zeroes or a blank string. + fn from_str(s: &str) -> Option { + if s.is_empty() { + return None; + } + + if s == "0" { + return Some(Self::zero()); + } + + let mut res = Self::zero(); + + let ten = Self::from_repr(Self::Repr::from(10)).unwrap(); + + let mut first_digit = true; + + for c in s.chars() { + match c.to_digit(10) { + Some(c) => { + if first_digit { + if c == 0 { + return None; + } + + first_digit = false; + } + + res.mul_assign(&ten); + res.add_assign(&Self::from_repr(Self::Repr::from(u64::from(c))).unwrap()); + } + None => { + return None; + } + } + } + + Some(res) + } /// Convert this prime field element into a biginteger representation. - fn from_repr(Self::Repr) -> Result; + fn from_repr(Self::Repr) -> Result; - /// Convert a biginteger reprensentation into a prime field element, if + /// Convert a biginteger representation into a prime field element, if /// the number is an element of the field. fn into_repr(&self) -> Self::Repr; /// Returns the field characteristic; the modulus. fn char() -> Self::Repr; - /// Returns how many bits are needed to represent an element of this - /// field. - fn num_bits() -> u32; + /// How many bits are needed to represent an element of this field. + const NUM_BITS: u32; - /// Returns how many bits of information can be reliably stored in the - /// field element. - fn capacity() -> u32; + /// How many bits of information can be reliably stored in the field element. + const CAPACITY: u32; /// Returns the multiplicative generator of `char()` - 1 order. This element /// must also be quadratic nonresidue. fn multiplicative_generator() -> Self; - /// Returns s such that 2^s * t = `char()` - 1 with t odd. - fn s() -> usize; + /// 2^s * t = `char()` - 1 with t odd. + const S: u32; /// Returns the 2^s root of unity computed by exponentiating the `multiplicative_generator()` /// by t. fn root_of_unity() -> Self; } +#[derive(Debug)] pub struct BitIterator { t: E, n: usize, } impl> BitIterator { - fn new(t: E) -> Self { + pub fn new(t: E) -> Self { let n = t.as_ref().len() * 64; - BitIterator { t: t, n: n } + BitIterator { t, n } } } From 29a9161981ff7eef49aacca5844ce1723e053403 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 28 Jun 2018 15:07:35 -0400 Subject: [PATCH 06/11] Implement changes to traits in ff_derive --- ff_derive/src/lib.rs | 147 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 126 insertions(+), 21 deletions(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index 6913b655d..90e6a4bad 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -140,6 +140,17 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS } } + impl ::std::fmt::Display for #repr { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + try!(write!(f, "0x")); + for i in self.0.iter().rev() { + try!(write!(f, "{:016x}", *i)); + } + + Ok(()) + } + } + impl AsRef<[u64]> for #repr { #[inline(always)] fn as_ref(&self) -> &[u64] { @@ -147,6 +158,13 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS } } + impl AsMut<[u64]> for #repr { + #[inline(always)] + fn as_mut(&mut self) -> &mut [u64] { + &mut self.0 + } + } + impl From for #repr { #[inline(always)] fn from(val: u64) -> #repr { @@ -207,6 +225,32 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS } } + #[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; + } + } + } + #[inline(always)] fn mul2(&mut self) { let mut last = 0; @@ -218,6 +262,32 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS } } + #[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; + } + } + } + #[inline(always)] fn num_bits(&self) -> u32 { let mut ret = (#limbs as u32) * 64; @@ -233,25 +303,21 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS } #[inline(always)] - fn add_nocarry(&mut self, other: &#repr) -> bool { + 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); } - - carry != 0 } #[inline(always)] - fn sub_noborrow(&mut self, other: &#repr) -> bool { + 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); } - - borrow != 0 } } } @@ -345,7 +411,7 @@ fn prime_field_constants_and_sqrt( let r = (BigUint::one() << (limbs * 64)) % &modulus; // modulus - 1 = 2^s * t - let mut s: usize = 0; + let mut s: u32 = 0; let mut t = &modulus - BigUint::from_str("1").unwrap(); while t.is_even() { t = t >> 1; @@ -359,6 +425,22 @@ fn prime_field_constants_and_sqrt( ); let generator = biguint_to_u64_vec((generator.clone() * &r) % &modulus, limbs); + let mod_minus_1_over_2 = + biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs); + let legendre_impl = quote!{ + fn legendre(&self) -> ::ff::LegendreSymbol { + // s = self^((modulus - 1) // 2) + let s = self.pow(#mod_minus_1_over_2); + if s == Self::zero() { + ::ff::LegendreSymbol::Zero + } else if s == Self::one() { + ::ff::LegendreSymbol::QuadraticResidue + } else { + ::ff::LegendreSymbol::QuadraticNonResidue + } + } + }; + let sqrt_impl = if (&modulus % BigUint::from_str("4").unwrap()) == BigUint::from_str("3").unwrap() { let mod_minus_3_over_4 = @@ -369,6 +451,8 @@ fn prime_field_constants_and_sqrt( quote!{ impl ::ff::SqrtField for #name { + #legendre_impl + fn sqrt(&self) -> Option { // Shank's algorithm for q mod 4 = 3 // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2) @@ -389,13 +473,13 @@ fn prime_field_constants_and_sqrt( } } } else if (&modulus % BigUint::from_str("16").unwrap()) == BigUint::from_str("1").unwrap() { - let mod_minus_1_over_2 = - biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs); let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1, limbs); let t = biguint_to_u64_vec(t.clone(), limbs); quote!{ impl ::ff::SqrtField for #name { + #legendre_impl + fn sqrt(&self) -> Option { // Tonelli-Shank's algorithm for q mod 16 = 1 // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) @@ -483,7 +567,7 @@ fn prime_field_constants_and_sqrt( const GENERATOR: #repr = #repr(#generator); /// 2^s * t = MODULUS - 1 with t odd - const S: usize = #s; + const S: u32 = #s; /// 2^s root of unity computed by GENERATOR^t const ROOT_OF_UNITY: #repr = #repr(#root_of_unity); @@ -736,6 +820,27 @@ fn prime_field_impl( } } + /// 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 ::rand::Rand for #name { /// Computes a uniformly random element using rejection sampling. fn rand(rng: &mut R) -> Self { @@ -751,17 +856,23 @@ fn prime_field_impl( } } + impl From<#name> for #repr { + fn from(e: #name) -> #repr { + e.into_repr() + } + } + impl ::ff::PrimeField for #name { type Repr = #repr; - fn from_repr(r: #repr) -> Result<#name, ()> { + 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(()) + Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0))) } } @@ -778,21 +889,15 @@ fn prime_field_impl( MODULUS } - fn num_bits() -> u32 { - MODULUS_BITS - } + const NUM_BITS: u32 = MODULUS_BITS; - fn capacity() -> u32 { - Self::num_bits() - 1 - } + const CAPACITY: u32 = Self::NUM_BITS - 1; fn multiplicative_generator() -> Self { #name(GENERATOR) } - fn s() -> usize { - S - } + const S: u32 = S; fn root_of_unity() -> Self { #name(ROOT_OF_UNITY) From 5a48059a14ec82371c61935869b001f1200936c2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 1 Jul 2018 00:05:56 -0400 Subject: [PATCH 07/11] Integrate changes to trait impls from pairing into ff_derive --- ff_derive/src/lib.rs | 80 +++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index 90e6a4bad..16c4604d3 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -254,7 +254,7 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS #[inline(always)] fn mul2(&mut self) { let mut last = 0; - for i in self.0.iter_mut() { + for i in &mut self.0 { let tmp = *i >> 63; *i <<= 1; *i |= last; @@ -484,42 +484,40 @@ fn prime_field_constants_and_sqrt( // Tonelli-Shank's algorithm for q mod 16 = 1 // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) - if self.is_zero() { - return Some(*self); - } + match self.legendre() { + ::ff::LegendreSymbol::Zero => Some(*self), + ::ff::LegendreSymbol::QuadraticNonResidue => None, + ::ff::LegendreSymbol::QuadraticResidue => { + let mut c = #name(ROOT_OF_UNITY); + let mut r = self.pow(#t_plus_1_over_2); + let mut t = self.pow(#t); + let mut m = S; - if self.pow(#mod_minus_1_over_2) != Self::one() { - None - } else { - let mut c = #name(#repr(#root_of_unity)); - let mut r = self.pow(#t_plus_1_over_2); - let mut t = self.pow(#t); - let mut m = #s; - - while t != Self::one() { - let mut i = 1; - { - let mut t2i = t; - t2i.square(); - loop { - if t2i == Self::one() { - break; - } + while t != Self::one() { + let mut i = 1; + { + let mut t2i = t; t2i.square(); - i += 1; + loop { + if t2i == Self::one() { + break; + } + t2i.square(); + i += 1; + } } - } - for _ in 0..(m - i - 1) { + for _ in 0..(m - i - 1) { + c.square(); + } + r.mul_assign(&c); c.square(); + t.mul_assign(&c); + m = i; } - r.mul_assign(&c); - c.square(); - t.mul_assign(&c); - m = i; - } - Some(r) + Some(r) + } } } } @@ -681,23 +679,20 @@ fn prime_field_impl( } for i in 1..(limbs * 2) { - let k = get_temp(i); + let temp0 = get_temp(limbs * 2 - i); + let temp1 = get_temp(limbs * 2 - i - 1); if i == 1 { gen.extend(quote!{ - let tmp0 = #k >> 63; - let #k = #k << 1; + let #temp0 = #temp1 >> 63; }); } else if i == (limbs * 2 - 1) { gen.extend(quote!{ - let #k = tmp0; + let #temp0 = #temp0 << 1; }); } else { gen.extend(quote!{ - let tmp1 = #k >> 63; - let #k = #k << 1; - let #k = #k | tmp0; - let tmp0 = tmp1; + let #temp0 = (#temp0 << 1) | (#temp1 >> 63); }); } } @@ -796,6 +791,8 @@ fn prime_field_impl( proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), ); + let top_limb_index = limbs - 1; + quote!{ impl Copy for #name { } @@ -846,9 +843,10 @@ fn prime_field_impl( fn rand(rng: &mut R) -> Self { loop { let mut tmp = #name(#repr::rand(rng)); - for _ in 0..REPR_SHAVE_BITS { - tmp.0.div2(); - } + + // Mask away the unused bits at the beginning. + tmp.0.as_mut()[#top_limb_index] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; + if tmp.is_valid() { return tmp } From b0b754ba040dd8086b75d44f5826b0649aa4db27 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 1 Jul 2018 22:43:22 +0100 Subject: [PATCH 08/11] Return constants and sqrt impls separately for individual rendering --- ff_derive/src/lib.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index 16c4604d3..86ecf4adc 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -52,14 +52,17 @@ pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let mut gen = proc_macro2::TokenStream::new(); - gen.extend(prime_field_repr_impl(&repr_ident, limbs)); - gen.extend(prime_field_constants_and_sqrt( + let (constants_impl, sqrt_impl) = prime_field_constants_and_sqrt( &ast.ident, &repr_ident, modulus, limbs, generator, - )); + ); + + gen.extend(prime_field_repr_impl(&repr_ident, limbs)); + gen.extend(constants_impl); + gen.extend(sqrt_impl); gen.extend(prime_field_impl(&ast.ident, &repr_ident, limbs)); // Return the generated impl @@ -398,7 +401,7 @@ fn prime_field_constants_and_sqrt( modulus: BigUint, limbs: usize, generator: BigUint, -) -> proc_macro2::TokenStream { +) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { let modulus_num_bits = biguint_num_bits(modulus.clone()); // The number of bits we should "shave" from a randomly sampled reputation, i.e., @@ -540,7 +543,7 @@ fn prime_field_constants_and_sqrt( } inv = inv.wrapping_neg(); - quote! { + (quote! { /// This is the modulus m of the prime field const MODULUS: #repr = #repr([#(#modulus,)*]); @@ -569,9 +572,7 @@ fn prime_field_constants_and_sqrt( /// 2^s root of unity computed by GENERATOR^t const ROOT_OF_UNITY: #repr = #repr(#root_of_unity); - - #sqrt_impl - } + }, sqrt_impl) } /// Implement PrimeField for the derived type. From 623dbd0d74504d6b5d598ef83c654a1091670222 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 1 Jul 2018 22:49:10 +0100 Subject: [PATCH 09/11] [MOVEONLY] Move generated code around slightly in ff_derive This reduces the differences in the generated code between the current implementations of Fq and Fr in pairing, and their derived versions. --- ff_derive/src/lib.rs | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index 86ecf4adc..e792cd84d 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -60,10 +60,10 @@ pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream { generator, ); - gen.extend(prime_field_repr_impl(&repr_ident, limbs)); gen.extend(constants_impl); - gen.extend(sqrt_impl); + gen.extend(prime_field_repr_impl(&repr_ident, limbs)); gen.extend(prime_field_impl(&ast.ident, &repr_ident, limbs)); + gen.extend(sqrt_impl); // Return the generated impl gen.into() @@ -124,13 +124,6 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS #[derive(Copy, Clone, PartialEq, Eq, Default)] pub struct #repr(pub [u64; #limbs]); - impl ::rand::Rand for #repr { - #[inline(always)] - fn rand(rng: &mut R) -> Self { - #repr(rng.gen()) - } - } - impl ::std::fmt::Debug for #repr { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { @@ -143,6 +136,13 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS } } + impl ::rand::Rand for #repr { + #[inline(always)] + fn rand(rng: &mut R) -> Self { + #repr(rng.gen()) + } + } + impl ::std::fmt::Display for #repr { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { try!(write!(f, "0x")); @@ -217,17 +217,6 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS self.0.iter().all(|&e| e == 0) } - #[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 shr(&mut self, mut n: u32) { if n as usize >= 64 * #limbs { @@ -254,6 +243,17 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS } } + #[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; From 4c984595e51fd746f68bea5339c771f70bff3a8d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 06:54:59 +0100 Subject: [PATCH 10/11] Add full paths for some manually-implemented derives This further reduces the difference between pairing's manual and derived implementations. --- ff_derive/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index e792cd84d..45d344537 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -795,21 +795,21 @@ fn prime_field_impl( let top_limb_index = limbs - 1; quote!{ - impl Copy for #name { } + impl ::std::marker::Copy for #name { } - impl Clone for #name { + impl ::std::clone::Clone for #name { fn clone(&self) -> #name { *self } } - impl PartialEq for #name { + impl ::std::cmp::PartialEq for #name { fn eq(&self, other: &#name) -> bool { self.0 == other.0 } } - impl Eq for #name { } + impl ::std::cmp::Eq for #name { } impl ::std::fmt::Debug for #name { From 91a8dc8284a09c456b36da44ca7de36f8b50550d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 09:18:34 +0100 Subject: [PATCH 11/11] Update rand crate --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 195b1078a..ef9a54f52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/ebfull/ff" [dependencies] byteorder = "1" -rand = "0.3" +rand = "0.4" ff_derive = { version = "0.2.0", path = "ff_derive" } [features]