From b11ea2db258b7e8a432866eba5f677e99fa4d747 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 25 Jun 2017 23:09:43 -0600 Subject: [PATCH 01/60] Initial commit. --- .gitignore | 3 + Cargo.toml | 8 ++ LICENSE-APACHE | 202 +++++++++++++++++++++++++++++++++++++ LICENSE-MIT | 21 ++++ README.md | 51 ++++++++++ ff_derive/Cargo.toml | 13 +++ ff_derive/src/lib.rs | 111 ++++++++++++++++++++ src/lib.rs | 235 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 644 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT create mode 100644 README.md create mode 100644 ff_derive/Cargo.toml create mode 100644 ff_derive/src/lib.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4308d82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +target/ +**/*.rs.bk +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e687109 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ff" +version = "0.1.0" +authors = ["Sean Bowe "] + +[dependencies] +rand = "0.3" +ff_derive = { version = "0.1.0", path = "ff_derive" } diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..1e5006d --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..ed3a13f --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Sean Bowe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d9dfc76 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# ff + +`ff` is a finite field library written in pure Rust, with no `unsafe{}` code. This library relies on Rust's `i128_type` feature, which is currently only available in the nightly compiler. + +## Disclaimers + +* This library does not provide constant-time guarantees. +* This library relies on Rust's `i128_type` feature, which is currently only available in the nightly compiler. + +## Usage + +Add the `ff` crate to your `Cargo.toml`: + +```toml +[dependencies] +ff = "0.1" +``` + +The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` traits. See the **[documentation](http)** for more. + +### #![derive(PrimeField)] + +If you need an implementation of a prime field, this library also provides a procedural macro that will expand into an efficient implementation of a prime field when supplied with the modulus. It's very easy to use, after you've added it to your `Cargo.toml`. + +```rust +extern crate rand; +#[macro_use] +extern crate ff; + +#[derive(PrimeField)] +#[PrimeFieldModulus = "57896044618658097711785492504343953926634992332820282019728792003956564819949"] +struct Fp(FpRepr); +``` + +And that's it! `Fp` now implements `Field` and `PrimeField`. `Fp` will also implement `SqrtField` if supported. The library implements `FpRepr` itself and derives `PrimeFieldRepr` for it. + +## License + +Licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. diff --git a/ff_derive/Cargo.toml b/ff_derive/Cargo.toml new file mode 100644 index 0000000..c61953a --- /dev/null +++ b/ff_derive/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "ff_derive" +version = "0.1.0" +authors = ["Sean Bowe "] + +[lib] +proc-macro = true + +[dependencies] +syn = "0.11" +quote = "0.3" +num-bigint = "0.1" +num-traits = "0.1" diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs new file mode 100644 index 0000000..740cda2 --- /dev/null +++ b/ff_derive/src/lib.rs @@ -0,0 +1,111 @@ +extern crate proc_macro; +//extern crate syn; +//#[macro_use] +extern crate quote; + +//extern crate num_bigint; +//extern crate num_traits; + +//use num_traits::{Zero, One, ToPrimitive}; +//use num_bigint::BigUint; + +#[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus))] +pub fn prime_field( + _: 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"); + + // 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"); + + // 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 + let mut cur = BigUint::one() << 64; + while cur < mod2 { + limbs += 1; + cur = cur << 64; + } + } + */ + + let gen = quote::Tokens::new(); + + //gen.append(prime_field_repr_impl(&repr_ident, limbs)); + //gen.append(prime_field_constants(&repr_ident, modulus, limbs)); + //gen.append(prime_field_impl(&ast.ident, &repr_ident)); + //gen.append(prime_field_arith_impl(&ast.ident, &repr_ident, limbs)); + + // Return the generated impl + gen.parse().unwrap() +} + +/* +fn fetch_wrapped_ident( + body: &syn::Body +) -> 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()); + } + }, + _ => {} + } + } + }, + _ => {} + }; + + None +} + +/// 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); + } + } + }, + _ => { + panic!("attribute {} should be a string", name); + } + } + } + } + + None +} +*/ diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..bd76b93 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,235 @@ +#![feature(i128_type)] + +extern crate rand; + +//#[macro_use] +//extern crate ff_derive; + +//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 +{ + /// Returns the zero element of the field, the additive identity. + fn zero() -> Self; + + /// Returns the one element of the field, the multiplicative identity. + fn one() -> Self; + + /// Returns true iff this element is zero. + fn is_zero(&self) -> bool; + + /// Squares this element. + fn square(&mut self); + + /// Doubles this element. + fn double(&mut self); + + /// Negates this element. + fn negate(&mut self); + + /// Adds another element to this element. + fn add_assign(&mut self, other: &Self); + + /// Subtracts another element from this element. + fn sub_assign(&mut self, other: &Self); + + /// Multiplies another element by this element. + fn mul_assign(&mut self, other: &Self); + + /// Computes the multiplicative inverse of this element, if nonzero. + fn inverse(&self) -> Option; + + /// Exponentiates this element by a power of the modulus. + fn frobenius_map(&mut self, power: usize); + + /// Exponentiates this element by a number represented with `u64` limbs, + /// least significant digit first. + fn pow>(&self, exp: S) -> Self + { + let mut res = Self::one(); + + for i in BitIterator::new(exp) { + res.square(); + if i { + res.mul_assign(self); + } + } + + res + } +} + +/// This trait represents an element of a field that has a square root operation described for it. +pub trait SqrtField: Field +{ + /// Returns the square root of the field element, if it is + /// quadratic residue. + fn sqrt(&self) -> Option; +} + +/// 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 +{ + /// Subtract another reprensetation from this one. Underflow is ignored. + fn sub_noborrow(&mut self, other: &Self); + + /// Add another representation to this one. Overflow is ignored. + fn add_nocarry(&mut self, other: &Self); + + /// Compute the number of bits needed to encode this number. + fn num_bits(&self) -> usize; + + /// Returns true iff this number is zero. + fn is_zero(&self) -> bool; + + /// Returns true iff this number is odd. + fn is_odd(&self) -> bool; + + /// Returns true iff this number is even. + fn is_even(&self) -> bool; + + /// Performs a rightwise bitshift of this number, effectively dividing + /// it by 2. + fn div2(&mut self); + + /// Performs a leftwise bitshift of this number, effectively multiplying + /// it by 2. Overflow is ignored. + fn mul2(&mut self); +} + +/// This represents an element of a prime field. +pub trait PrimeField: SqrtField +{ + /// The prime field can be converted back and forth into this biginteger + /// representation. + type Repr: PrimeFieldRepr; + + /// Convert this prime field element into a biginteger representation. + fn from_repr(Self::Repr) -> Result; + + /// Convert a biginteger reprensentation 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() -> usize; + + /// Returns how many bits of information can be reliably stored in the + /// field element. + fn capacity() -> usize; +} + +pub struct BitIterator { + t: E, + n: usize +} + +impl> BitIterator { + fn new(t: E) -> Self { + let n = t.as_ref().len() * 64; + + BitIterator { + t: t, + n: n + } + } +} + +impl> Iterator for BitIterator { + type Item = bool; + + fn next(&mut self) -> Option { + if self.n == 0 { + None + } else { + self.n -= 1; + let part = self.n / 64; + let bit = self.n - (64 * part); + + Some(self.t.as_ref()[part] & (1 << bit) > 0) + } + } +} + +#[test] +fn test_bit_iterator() { + let mut a = BitIterator::new([0xa953d79b83f6ab59, 0x6dea2059e200bd39]); + let expected = "01101101111010100010000001011001111000100000000010111101001110011010100101010011110101111001101110000011111101101010101101011001"; + + for e in expected.chars() { + assert!(a.next().unwrap() == (e == '1')); + } + + assert!(a.next().is_none()); + + let expected = "1010010101111110101010000101101011101000011101110101001000011001100100100011011010001011011011010001011011101100110100111011010010110001000011110100110001100110011101101000101100011100100100100100001010011101010111110011101011000011101000111011011101011001"; + + let mut a = BitIterator::new([0x429d5f3ac3a3b759, 0xb10f4c66768b1c92, 0x92368b6d16ecd3b4, 0xa57ea85ae8775219]); + + for e in expected.chars() { + assert!(a.next().unwrap() == (e == '1')); + } + + 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); + + *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 = (a as u128) + (b as u128) + (*carry as u128); + + *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 = (a as u128) + (b as u128) * (c as u128) + (*carry as u128); + + *carry = (tmp >> 64) as u64; + + tmp as u64 +} From cf7d7e823b6f5b8e78ee87310b42ead716b7f14a Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 25 Jun 2017 23:12:40 -0600 Subject: [PATCH 02/60] Add more stuff to the Cargo.toml files. --- Cargo.toml | 5 +++++ ff_derive/Cargo.toml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index e687109..a90e446 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,11 @@ name = "ff" version = "0.1.0" authors = ["Sean Bowe "] +description = "Procedural macro library used to build custom prime field implementations" +documentation = "https://github.com/ebfull/ff" +homepage = "https://github.com/ebfull/ff" +license = "MIT/Apache-2.0" +repository = "https://github.com/ebfull/ff" [dependencies] rand = "0.3" diff --git a/ff_derive/Cargo.toml b/ff_derive/Cargo.toml index c61953a..57750b1 100644 --- a/ff_derive/Cargo.toml +++ b/ff_derive/Cargo.toml @@ -2,6 +2,11 @@ name = "ff_derive" version = "0.1.0" authors = ["Sean Bowe "] +description = "Procedural macro library used to build custom prime field implementations" +documentation = "https://github.com/ebfull/ff" +homepage = "https://github.com/ebfull/ff" +license = "MIT/Apache-2.0" +repository = "https://github.com/ebfull/ff" [lib] proc-macro = true From cb0c8f1e07e004a9ed89c464655f63b8b9bda9b2 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 25 Jun 2017 23:13:56 -0600 Subject: [PATCH 03/60] Fix description of `ff`. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a90e446..294a204 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "ff" version = "0.1.0" authors = ["Sean Bowe "] -description = "Procedural macro library used to build custom prime field implementations" +description = "Library for building and interfacing with finite fields" documentation = "https://github.com/ebfull/ff" homepage = "https://github.com/ebfull/ff" license = "MIT/Apache-2.0" From 6402b74741770ecc65ae4b1407ff695bf3a04ce3 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 25 Jun 2017 23:16:08 -0600 Subject: [PATCH 04/60] Fix comment. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d9dfc76..02d6c1e 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` ### #![derive(PrimeField)] -If you need an implementation of a prime field, this library also provides a procedural macro that will expand into an efficient implementation of a prime field when supplied with the modulus. It's very easy to use, after you've added it to your `Cargo.toml`. +If you need an implementation of a prime field, this library also provides a procedural macro that will expand into an efficient implementation of a prime field when supplied with the modulus. ```rust extern crate rand; From e97f0df3dfbd538a7c2a266df9e9753cc6db1279 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 25 Jun 2017 23:18:32 -0600 Subject: [PATCH 05/60] Fix another comment. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 02d6c1e..ec7a7a6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ff -`ff` is a finite field library written in pure Rust, with no `unsafe{}` code. This library relies on Rust's `i128_type` feature, which is currently only available in the nightly compiler. +`ff` is a finite field library written in pure Rust, with no `unsafe{}` code. ## Disclaimers From 13a822f994e1d9c13218c79a3a2ba8fb4cc5cf68 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 26 Jun 2017 11:47:35 -0600 Subject: [PATCH 06/60] Add auto-derivation of prime fields, and modify the traits a little bit. --- ff_derive/src/lib.rs | 637 +++++++++++++++++++++++++++++++++++++++++-- src/lib.rs | 26 +- 2 files changed, 635 insertions(+), 28 deletions(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index 740cda2..02234d4 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -1,20 +1,22 @@ +#![recursion_limit="1024"] + extern crate proc_macro; -//extern crate syn; -//#[macro_use] +extern crate syn; +#[macro_use] extern crate quote; -//extern crate num_bigint; -//extern crate num_traits; +extern crate num_bigint; +extern crate num_traits; -//use num_traits::{Zero, One, ToPrimitive}; -//use num_bigint::BigUint; +use num_traits::{Zero, One, ToPrimitive}; +use num_bigint::BigUint; +use std::str::FromStr; #[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus))] pub fn prime_field( - _: proc_macro::TokenStream + input: proc_macro::TokenStream ) -> proc_macro::TokenStream { - /* // Construct a string representation of the type definition let s = input.to_string(); @@ -32,7 +34,6 @@ pub fn prime_field( // 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 @@ -42,20 +43,18 @@ pub fn prime_field( cur = cur << 64; } } - */ - let gen = quote::Tokens::new(); + let mut gen = quote::Tokens::new(); - //gen.append(prime_field_repr_impl(&repr_ident, limbs)); - //gen.append(prime_field_constants(&repr_ident, modulus, limbs)); - //gen.append(prime_field_impl(&ast.ident, &repr_ident)); + gen.append(prime_field_repr_impl(&repr_ident, limbs)); + gen.append(prime_field_constants_and_sqrt(&ast.ident, &repr_ident, modulus, limbs)); + gen.append(prime_field_impl(&ast.ident, &repr_ident, limbs)); //gen.append(prime_field_arith_impl(&ast.ident, &repr_ident, limbs)); // Return the generated impl gen.parse().unwrap() } -/* fn fetch_wrapped_ident( body: &syn::Body ) -> Option @@ -108,4 +107,610 @@ fn fetch_attr( None } -*/ + +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]); + + impl ::rand::Rand for #repr { + 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 { + try!(write!(f, "0x")); + for i in self.0.iter().rev() { + try!(write!(f, "{:016x}", *i)); + } + + Ok(()) + } + } + + impl AsRef<[u64]> for #repr { + fn as_ref(&self) -> &[u64] { + &self.0 + } + } + + impl From 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 { + 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 { + 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) + } + + #[inline(always)] + fn div2(&mut self) { + let mut t = 0; + for i in self.0.iter_mut().rev() { + let t2 = *i << 63; + *i >>= 1; + *i |= t; + t = t2; + } + } + + #[inline(always)] + fn mul2(&mut self) { + let mut last = 0; + for i in self.0.iter_mut() { + let tmp = *i >> 63; + *i <<= 1; + *i |= last; + last = tmp; + } + } + + #[inline(always)] + fn num_bits(&self) -> u32 { + let mut ret = (#limbs as u32) * 64; + for i in self.0.iter().rev() { + let leading = i.leading_zeros(); + ret -= leading; + if leading != 64 { + break; + } + } + + ret + } + + #[inline(always)] + fn add_nocarry(&mut self, other: &#repr) -> bool { + 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 { + 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 + } + } + } +} + +fn biguint_to_u64_vec( + mut v: BigUint +) -> Vec +{ + let m = BigUint::one() << 64; + let mut ret = vec![]; + + while v > BigUint::zero() { + ret.push((&v % &m).to_u64().unwrap()); + v = v >> 64; + } + + ret +} + +fn biguint_num_bits( + mut v: BigUint +) -> u32 +{ + let mut bits = 0; + + while v != BigUint::zero() { + v = v >> 1; + bits += 1; + } + + bits +} + +fn prime_field_constants_and_sqrt( + name: &syn::Ident, + repr: &syn::Ident, + modulus: BigUint, + limbs: usize +) -> quote::Tokens +{ + let modulus_num_bits = biguint_num_bits(modulus.clone()); + 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; + + 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); + + // Compute -R as (m - r) + let rneg = biguint_to_u64_vec(&modulus - &r); + + 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 a0 = a1; + a0.square(); + a0.mul_assign(self); + + if a0.0 == #repr(#rneg) { + None + } else { + a1.mul_assign(self); + Some(a1) + } + } + } + } + } else { + quote!{} + }; + + // Compute R^2 mod m + let r2 = biguint_to_u64_vec((&r * &r) % &modulus); + + let r = biguint_to_u64_vec(r); + let modulus = biguint_to_u64_vec(modulus); + + // 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(); + + quote! { + /// This is the modulus m of the prime field + const MODULUS: #repr = #repr(#modulus); + + /// The number of bits needed to represent the modulus. + const MODULUS_BITS: u32 = #modulus_num_bits; + + /// 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; + + /// 2^{limbs*64} mod m + const R: #repr = #repr(#r); + + /// 2^{limbs*64*2} mod m + const R2: #repr = #repr(#r2); + + /// -(m^{-1} mod m) mod m + const INV: u64 = #inv; + + #sqrt_impl + } +} + +fn prime_field_impl( + name: &syn::Ident, + repr: &syn::Ident, + limbs: usize +) -> quote::Tokens +{ + fn get_temp(n: usize) -> syn::Ident { + syn::Ident::from(format!("r{}", n)) + } + + 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} + } + }), + "," + ); // r0: u64, mut r1: u64, mut r2: u64, ... + + let mut mont_impl = quote::Tokens::new(); + for i in 0..limbs { + { + let temp = get_temp(i); + mont_impl.append(quote!{ + 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); + mont_impl.append(quote!{ + #temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry); + }); + } + + let temp = get_temp(i + limbs); + + if i == 0 { + mont_impl.append(quote!{ + #temp = ::ff::adc(#temp, 0, &mut carry); + }); + } else { + mont_impl.append(quote!{ + #temp = ::ff::adc(#temp, carry2, &mut carry); + }); + } + + if i != (limbs - 1) { + mont_impl.append(quote!{ + let carry2 = carry; + }); + } + } + + for i in 0..limbs { + let temp = get_temp(limbs + i); + + mont_impl.append(quote!{ + (self.0).0[#i] = #temp; + }); + } + + fn mul_impl(a: quote::Tokens, b: quote::Tokens, limbs: usize) -> quote::Tokens + { + let mut gen = quote::Tokens::new(); + + for i in 0..limbs { + gen.append(quote!{ + let mut carry = 0; + }); + + for j in 0..limbs { + let temp = get_temp(i + j); + + if i == 0 { + gen.append(quote!{ + let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry); + }); + } else { + gen.append(quote!{ + let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#b.0).0[#j], &mut carry); + }); + } + } + + let temp = get_temp(i + limbs); + + gen.append(quote!{ + let #temp = carry; + }); + } + + let mut mont_calling = quote::Tokens::new(); + mont_calling.append_separated((0..(limbs*2)).map(|i| get_temp(i)), ","); + + gen.append(quote!{ + self.mont_reduce(#mont_calling); + }); + + gen + } + + let squaring_impl = mul_impl(quote!{self}, quote!{self}, limbs); + let multiply_impl = mul_impl(quote!{self}, quote!{other}, limbs); + + 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})), + "," + ); + + quote!{ + impl Copy for #name { } + + impl Clone for #name { + fn clone(&self) -> #name { + *self + } + } + + impl PartialEq for #name { + fn eq(&self, other: &#name) -> bool { + self.0 == other.0 + } + } + + impl Eq for #name { } + + impl ::std::fmt::Debug for #name + { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}({:?})", stringify!(#name), self.into_repr()) + } + } + + impl Rand for #name { + /// Computes a uniformly random element using rejection sampling. + fn rand(rng: &mut R) -> Self { + loop { + let mut tmp = #name(#repr::rand(rng)); + for _ in 0..REPR_SHAVE_BITS { + tmp.0.div2(); + } + if tmp.is_valid() { + return tmp + } + } + } + } + + impl ::ff::PrimeField for #name { + type Repr = #repr; + + fn from_repr(r: #repr) -> Result<#name, ()> { + let mut r = #name(r); + if r.is_valid() { + r.mul_assign(&#name(R2)); + + Ok(r) + } else { + Err(()) + } + } + + fn into_repr(&self) -> #repr { + let mut r = *self; + r.mont_reduce( + #into_repr_params + ); + + r.0 + } + + fn char() -> #repr { + MODULUS + } + + fn num_bits() -> u32 { + MODULUS_BITS + } + + fn capacity() -> u32 { + Self::num_bits() - 1 + } + } + + impl ::ff::Field for #name { + #[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] + 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(); + } + + #[inline] + fn double(&mut self) { + // This cannot exceed the backing capacity. + self.0.mul2(); + + // However, it may need to be reduced. + self.reduce(); + } + + #[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); + } + + #[inline] + fn negate(&mut self) { + if !self.is_zero() { + let mut tmp = MODULUS; + tmp.sub_noborrow(&self.0); + self.0 = tmp; + } + } + + fn inverse(&self) -> Option { + if self.is_zero() { + None + } 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 { + Some(b) + } else { + Some(c) + } + } + } + + #[inline(always)] + fn frobenius_map(&mut self, _: usize) { + // This has no effect in a prime field. + } + + #[inline] + fn mul_assign(&mut self, other: &#name) + { + #multiply_impl + } + + #[inline] + fn square(&mut self) + { + #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 + // . + + #mont_impl + + self.reduce(); + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index bd76b93..c29117f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,12 @@ #![feature(i128_type)] +#![allow(unused_imports)] extern crate rand; -//#[macro_use] -//extern crate ff_derive; +#[macro_use] +extern crate ff_derive; -//pub use ff_derive::*; +pub use ff_derive::*; use std::fmt; @@ -50,7 +51,8 @@ pub trait Field: Sized + /// Computes the multiplicative inverse of this element, if nonzero. fn inverse(&self) -> Option; - /// Exponentiates this element by a power of the modulus. + /// Exponentiates this element by a power of the base prime modulus via + /// the Frobenius automorphism. fn frobenius_map(&mut self, power: usize); /// Exponentiates this element by a number represented with `u64` limbs, @@ -94,14 +96,14 @@ pub trait PrimeFieldRepr: Sized + AsRef<[u64]> + From { - /// Subtract another reprensetation from this one. Underflow is ignored. - fn sub_noborrow(&mut self, other: &Self); + /// Subtract another reprensetation from this one, returning the borrow bit. + fn sub_noborrow(&mut self, other: &Self) -> bool; - /// Add another representation to this one. Overflow is ignored. - fn add_nocarry(&mut self, other: &Self); + /// Add another representation to this one, returning the carry bit. + fn add_nocarry(&mut self, other: &Self) -> bool; /// Compute the number of bits needed to encode this number. - fn num_bits(&self) -> usize; + fn num_bits(&self) -> u32; /// Returns true iff this number is zero. fn is_zero(&self) -> bool; @@ -122,7 +124,7 @@ pub trait PrimeFieldRepr: Sized + } /// This represents an element of a prime field. -pub trait PrimeField: SqrtField +pub trait PrimeField: Field { /// The prime field can be converted back and forth into this biginteger /// representation. @@ -140,11 +142,11 @@ pub trait PrimeField: SqrtField /// Returns how many bits are needed to represent an element of this /// field. - fn num_bits() -> usize; + fn num_bits() -> u32; /// Returns how many bits of information can be reliably stored in the /// field element. - fn capacity() -> usize; + fn capacity() -> u32; } pub struct BitIterator { From 03952704b70f5b1e374d94de2dfe51f0218dbd2b Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 26 Jun 2017 12:07:23 -0600 Subject: [PATCH 07/60] Absolute path to rand. --- ff_derive/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index 02234d4..9485567 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -503,9 +503,9 @@ fn prime_field_impl( } } - impl Rand for #name { + impl ::rand::Rand for #name { /// Computes a uniformly random element using rejection sampling. - fn rand(rng: &mut R) -> Self { + fn rand(rng: &mut R) -> Self { loop { let mut tmp = #name(#repr::rand(rng)); for _ in 0..REPR_SHAVE_BITS { From e6ad371dd74ca2c454c88682a5eb1402b60d81b5 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 26 Jun 2017 13:53:55 -0600 Subject: [PATCH 08/60] Remove dead code. --- ff_derive/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index 9485567..1e74a62 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -49,7 +49,6 @@ pub fn prime_field( gen.append(prime_field_repr_impl(&repr_ident, limbs)); gen.append(prime_field_constants_and_sqrt(&ast.ident, &repr_ident, modulus, limbs)); gen.append(prime_field_impl(&ast.ident, &repr_ident, limbs)); - //gen.append(prime_field_arith_impl(&ast.ident, &repr_ident, limbs)); // Return the generated impl gen.parse().unwrap() From bbbd397b80df647aa1f96c8dbc2a6049f83cbabc Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 26 Jun 2017 14:42:47 -0600 Subject: [PATCH 09/60] Add more efficient squaring implementation. --- ff_derive/src/lib.rs | 85 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index 1e74a62..aa68d27 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -428,6 +428,89 @@ fn prime_field_impl( }); } + fn sqr_impl(a: quote::Tokens, limbs: usize) -> quote::Tokens + { + let mut gen = quote::Tokens::new(); + + for i in 0..(limbs-1) { + gen.append(quote!{ + let mut carry = 0; + }); + + for j in (i+1)..limbs { + let temp = get_temp(i + j); + if i == 0 { + gen.append(quote!{ + let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#j], &mut carry); + }); + } else { + gen.append(quote!{ + let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#a.0).0[#j], &mut carry); + }); + } + } + + let temp = get_temp(i + limbs); + + gen.append(quote!{ + let #temp = carry; + }); + } + + for i in 1..(limbs*2) { + let k = get_temp(i); + + if i == 1 { + gen.append(quote!{ + let tmp0 = #k >> 63; + let #k = #k << 1; + }); + } else if i == (limbs*2 - 1) { + gen.append(quote!{ + let #k = tmp0; + }); + } else { + gen.append(quote!{ + let tmp1 = #k >> 63; + let #k = #k << 1; + let #k = #k | tmp0; + let tmp0 = tmp1; + }); + } + } + + gen.append(quote!{ + 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 { + gen.append(quote!{ + let #temp0 = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); + }); + } else { + gen.append(quote!{ + let #temp0 = ::ff::mac_with_carry(#temp0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); + }); + } + + gen.append(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)), ","); + + gen.append(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(); @@ -468,7 +551,7 @@ fn prime_field_impl( gen } - let squaring_impl = mul_impl(quote!{self}, quote!{self}, limbs); + let squaring_impl = sqr_impl(quote!{self}, limbs); let multiply_impl = mul_impl(quote!{self}, quote!{other}, limbs); let mut into_repr_params = quote::Tokens::new(); From 9aceb63e7e8e0380b2ed26d1c7ae8e1a5dd5a206 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 26 Jun 2017 23:22:41 -0600 Subject: [PATCH 10/60] Add Tonelli-Shanks sqrt for 1 mod 16 primes. --- ff_derive/Cargo.toml | 1 + ff_derive/src/lib.rs | 108 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 3 deletions(-) diff --git a/ff_derive/Cargo.toml b/ff_derive/Cargo.toml index 57750b1..54ab98f 100644 --- a/ff_derive/Cargo.toml +++ b/ff_derive/Cargo.toml @@ -16,3 +16,4 @@ syn = "0.11" quote = "0.3" num-bigint = "0.1" num-traits = "0.1" +num-integer = "0.1" diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index aa68d27..3d7775e 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -7,12 +7,14 @@ extern crate quote; extern crate num_bigint; extern crate num_traits; +extern crate num_integer; +use num_integer::Integer; use num_traits::{Zero, One, ToPrimitive}; use num_bigint::BigUint; use std::str::FromStr; -#[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus))] +#[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus, PrimeFieldGenerator))] pub fn prime_field( input: proc_macro::TokenStream ) -> proc_macro::TokenStream @@ -32,6 +34,11 @@ pub fn prime_field( .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: Option = fetch_attr("PrimeFieldGenerator", &ast.attrs) + .map(|i| i.parse().expect("PrimeFieldGenerator must 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. let mut limbs = 1; @@ -47,7 +54,7 @@ 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)); + 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 @@ -277,11 +284,45 @@ fn biguint_num_bits( bits } +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())) + { + 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(), + &BigUint::from_str("52435875175126190479447740508185965837690552500527637822603658699938581184513").unwrap() + ), + BigUint::from_str("4371221214068404307866768905142520595925044802278091865033317963560480051536").unwrap() + ); +} + fn prime_field_constants_and_sqrt( name: &syn::Ident, repr: &syn::Ident, modulus: BigUint, - limbs: usize + limbs: usize, + generator: Option ) -> quote::Tokens { let modulus_num_bits = biguint_num_bits(modulus.clone()); @@ -290,6 +331,14 @@ fn prime_field_constants_and_sqrt( // Compute R = 2**(64 * limbs) mod m let r = (BigUint::one() << (limbs * 64)) % &modulus; + // modulus - 1 = 2^s * t + let mut s = 0; + let mut t = &modulus - BigUint::from_str("1").unwrap(); + while t.is_even() { + t = t >> 1; + s += 1; + } + 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); @@ -318,6 +367,59 @@ 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); + let generator = generator.expect("PrimeFieldGenerator attribute should be provided; should be a generator of order p - 1 and quadratic nonresidue."); + let root_of_unity = biguint_to_u64_vec((exp(generator.clone(), &t, &modulus) * &r) % &modulus); + let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1); + let t = biguint_to_u64_vec(t.clone()); + + 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; + } + + Some(r) + } + } + } + } } else { quote!{} }; From b1f392ac995ef60e6bdfcd50a6794f80669a8594 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 27 Jun 2017 09:14:24 -0600 Subject: [PATCH 11/60] Add multiplicative generator and other useful constants. --- ff_derive/src/lib.rs | 60 +++++++++++++++++++++++++++++++++----------- src/lib.rs | 11 ++++++++ 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index 3d7775e..b4a498f 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -36,8 +36,9 @@ pub fn prime_field( // We may be provided with a generator of p - 1 order. It is required that this generator be quadratic // nonresidue. - let generator: Option = fetch_attr("PrimeFieldGenerator", &ast.attrs) - .map(|i| i.parse().expect("PrimeFieldGenerator must be a number.")); + let generator: BigUint = fetch_attr("PrimeFieldGenerator", &ast.attrs) + .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. @@ -256,7 +257,8 @@ fn prime_field_repr_impl( } fn biguint_to_u64_vec( - mut v: BigUint + mut v: BigUint, + limbs: usize ) -> Vec { let m = BigUint::one() << 64; @@ -267,6 +269,10 @@ fn biguint_to_u64_vec( v = v >> 64; } + while ret.len() < limbs { + ret.push(0); + } + ret } @@ -322,7 +328,7 @@ fn prime_field_constants_and_sqrt( repr: &syn::Ident, modulus: BigUint, limbs: usize, - generator: Option + generator: BigUint ) -> quote::Tokens { let modulus_num_bits = biguint_num_bits(modulus.clone()); @@ -332,19 +338,23 @@ fn prime_field_constants_and_sqrt( let r = (BigUint::one() << (limbs * 64)) % &modulus; // modulus - 1 = 2^s * t - let mut s = 0; + let mut s: usize = 0; let mut t = &modulus - BigUint::from_str("1").unwrap(); while t.is_even() { t = t >> 1; s += 1; } + // Compute root of unity given the generator + 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); + 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); + let rneg = biguint_to_u64_vec(&modulus - &r, limbs); quote!{ impl ::ff::SqrtField for #name { @@ -368,11 +378,9 @@ 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); - let generator = generator.expect("PrimeFieldGenerator attribute should be provided; should be a generator of order p - 1 and quadratic nonresidue."); - let root_of_unity = biguint_to_u64_vec((exp(generator.clone(), &t, &modulus) * &r) % &modulus); - let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1); - let t = biguint_to_u64_vec(t.clone()); + 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 { @@ -425,10 +433,10 @@ fn prime_field_constants_and_sqrt( }; // Compute R^2 mod m - let r2 = biguint_to_u64_vec((&r * &r) % &modulus); + let r2 = biguint_to_u64_vec((&r * &r) % &modulus, limbs); - let r = biguint_to_u64_vec(r); - let modulus = biguint_to_u64_vec(modulus); + let r = biguint_to_u64_vec(r, limbs); + let modulus = biguint_to_u64_vec(modulus, limbs); // Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1 let mut inv = 1u64; @@ -458,6 +466,16 @@ fn prime_field_constants_and_sqrt( /// -(m^{-1} mod m) mod m const INV: u64 = #inv; + /// Multiplicative generator of `MODULUS` - 1 order, also quadratic + /// nonresidue. + const GENERATOR: #repr = #repr(#generator); + + /// 2^s * t = MODULUS - 1 with t odd + const S: usize = #s; + + /// 2^s root of unity computed by GENERATOR^t + const ROOT_OF_UNITY: #repr = #repr(#root_of_unity); + #sqrt_impl } } @@ -736,6 +754,18 @@ fn prime_field_impl( fn capacity() -> u32 { Self::num_bits() - 1 } + + fn multiplicative_generator() -> Self { + #name(GENERATOR) + } + + fn s() -> usize { + S + } + + fn root_of_unity() -> Self { + #name(ROOT_OF_UNITY) + } } impl ::ff::Field for #name { diff --git a/src/lib.rs b/src/lib.rs index c29117f..99a7e7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -147,6 +147,17 @@ pub trait PrimeField: Field /// Returns how many bits of information can be reliably stored in the /// field element. fn 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; + + /// Returns the 2^s root of unity computed by exponentiating the `multiplicative_generator()` + /// by t. + fn root_of_unity() -> Self; } pub struct BitIterator { From 02f503c74d5196e0259c9f94ce63b46347ffdac8 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 27 Jun 2017 09:27:29 -0600 Subject: [PATCH 12/60] Modify README. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ec7a7a6..1bfcce4 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` ### #![derive(PrimeField)] -If you need an implementation of a prime field, this library also provides a procedural macro that will expand into an efficient implementation of a prime field when supplied with the modulus. +If you need an implementation of a prime field, this library also provides a procedural macro that will expand into an efficient implementation of a prime field when supplied with the modulus. `PrimeFieldGenerator` must be an element of Fp of p-1 order, that is also quadratic nonresidue. ```rust extern crate rand; @@ -28,7 +28,8 @@ extern crate rand; extern crate ff; #[derive(PrimeField)] -#[PrimeFieldModulus = "57896044618658097711785492504343953926634992332820282019728792003956564819949"] +#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"] +#[PrimeFieldGenerator = "7"] struct Fp(FpRepr); ``` From bbc7b44f88471669fcdc34b3dc2950ef410bde06 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 27 Jun 2017 09:40:58 -0600 Subject: [PATCH 13/60] Comments and slight refactoring. --- ff_derive/src/lib.rs | 116 +++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 44 deletions(-) diff --git a/ff_derive/src/lib.rs b/ff_derive/src/lib.rs index b4a498f..e507cd7 100644 --- a/ff_derive/src/lib.rs +++ b/ff_derive/src/lib.rs @@ -45,7 +45,7 @@ pub fn prime_field( let mut limbs = 1; { let mod2 = (&modulus) << 1; // modulus * 2 - let mut cur = BigUint::one() << 64; + let mut cur = BigUint::one() << 64; // always 64-bit limbs for now while cur < mod2 { limbs += 1; cur = cur << 64; @@ -62,6 +62,7 @@ pub fn prime_field( gen.parse().unwrap() } +/// Fetches the ident being wrapped by the type we're deriving. fn fetch_wrapped_ident( body: &syn::Body ) -> Option @@ -115,6 +116,7 @@ fn fetch_attr( None } +// Implement PrimeFieldRepr for the wrapped ident `repr` with `limbs` limbs. fn prime_field_repr_impl( repr: &syn::Ident, limbs: usize @@ -125,6 +127,7 @@ fn prime_field_repr_impl( pub struct #repr(pub [u64; #limbs]); impl ::rand::Rand for #repr { + #[inline(always)] fn rand(rng: &mut R) -> Self { #repr(rng.gen()) } @@ -143,6 +146,7 @@ fn prime_field_repr_impl( } impl AsRef<[u64]> for #repr { + #[inline(always)] fn as_ref(&self) -> &[u64] { &self.0 } @@ -160,6 +164,7 @@ fn prime_field_repr_impl( } impl Ord for #repr { + #[inline(always)] fn cmp(&self, other: &#repr) -> ::std::cmp::Ordering { for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) { if a < b { @@ -174,6 +179,7 @@ fn prime_field_repr_impl( } impl PartialOrd for #repr { + #[inline(always)] fn partial_cmp(&self, other: &#repr) -> Option<::std::cmp::Ordering> { Some(self.cmp(other)) } @@ -256,6 +262,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 @@ -273,6 +280,8 @@ fn biguint_to_u64_vec( ret.push(0); } + assert!(ret.len() == limbs); + ret } @@ -290,6 +299,7 @@ fn biguint_num_bits( bits } +/// BigUint modular exponentiation by square-and-multiply. fn exp( base: BigUint, exp: &BigUint, @@ -332,6 +342,11 @@ fn prime_field_constants_and_sqrt( ) -> 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 + // reduce the cost of rejection sampling. let repr_shave_bits = (64 * limbs as u32) - biguint_num_bits(modulus.clone()); // Compute R = 2**(64 * limbs) mod m @@ -345,7 +360,7 @@ fn prime_field_constants_and_sqrt( s += 1; } - // Compute root of unity given the generator + // 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 generator = biguint_to_u64_vec((generator.clone() * &r) % &modulus, limbs); @@ -480,16 +495,20 @@ 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 { + // Returns r{n} as an ident. fn get_temp(n: usize) -> syn::Ident { syn::Ident::from(format!("r{}", n)) } + // The parameter list for the mont_reduce() internal method. + // 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))) @@ -501,51 +520,58 @@ fn prime_field_impl( } }), "," - ); // r0: u64, mut r1: u64, mut r2: u64, ... + ); - let mut mont_impl = quote::Tokens::new(); - for i in 0..limbs { - { - let temp = get_temp(i); - mont_impl.append(quote!{ - let k = #temp.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry); + // Implement montgomery reduction for some number of limbs + fn mont_impl(limbs: usize) -> quote::Tokens + { + let mut gen = quote::Tokens::new(); + + for i in 0..limbs { + { + let temp = get_temp(i); + gen.append(quote!{ + 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); + gen.append(quote!{ + #temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry); + }); + } + + let temp = get_temp(i + limbs); + + if i == 0 { + gen.append(quote!{ + #temp = ::ff::adc(#temp, 0, &mut carry); + }); + } else { + gen.append(quote!{ + #temp = ::ff::adc(#temp, carry2, &mut carry); + }); + } + + if i != (limbs - 1) { + gen.append(quote!{ + let carry2 = carry; + }); + } + } + + for i in 0..limbs { + let temp = get_temp(limbs + i); + + gen.append(quote!{ + (self.0).0[#i] = #temp; }); } - for j in 1..limbs { - let temp = get_temp(i + j); - mont_impl.append(quote!{ - #temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry); - }); - } - - let temp = get_temp(i + limbs); - - if i == 0 { - mont_impl.append(quote!{ - #temp = ::ff::adc(#temp, 0, &mut carry); - }); - } else { - mont_impl.append(quote!{ - #temp = ::ff::adc(#temp, carry2, &mut carry); - }); - } - - if i != (limbs - 1) { - mont_impl.append(quote!{ - let carry2 = carry; - }); - } - } - - for i in 0..limbs { - let temp = get_temp(limbs + i); - - mont_impl.append(quote!{ - (self.0).0[#i] = #temp; - }); + gen } fn sqr_impl(a: quote::Tokens, limbs: usize) -> quote::Tokens @@ -673,7 +699,9 @@ fn prime_field_impl( let squaring_impl = sqr_impl(quote!{self}, limbs); let multiply_impl = mul_impl(quote!{self}, quote!{other}, limbs); + 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(); into_repr_params.append_separated( (0..limbs).map(|i| quote!{ (self.0).0[#i] }) @@ -921,7 +949,7 @@ fn prime_field_impl( // Handbook of Applied Cryptography // . - #mont_impl + #montgomery_impl self.reduce(); } From 134b53e812d6c5d7601dff23e9a24ef30be89fb1 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 27 Jun 2017 09:41:33 -0600 Subject: [PATCH 14/60] Version bump. --- Cargo.toml | 4 ++-- README.md | 2 +- ff_derive/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 294a204..c0418b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ff" -version = "0.1.0" +version = "0.2.0" authors = ["Sean Bowe "] description = "Library for building and interfacing with finite fields" documentation = "https://github.com/ebfull/ff" @@ -10,4 +10,4 @@ repository = "https://github.com/ebfull/ff" [dependencies] rand = "0.3" -ff_derive = { version = "0.1.0", path = "ff_derive" } +ff_derive = { version = "0.2.0", path = "ff_derive" } diff --git a/README.md b/README.md index 1bfcce4..df4bf03 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Add the `ff` crate to your `Cargo.toml`: ```toml [dependencies] -ff = "0.1" +ff = "0.2" ``` The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` traits. See the **[documentation](http)** for more. diff --git a/ff_derive/Cargo.toml b/ff_derive/Cargo.toml index 54ab98f..baba385 100644 --- a/ff_derive/Cargo.toml +++ b/ff_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ff_derive" -version = "0.1.0" +version = "0.2.0" authors = ["Sean Bowe "] description = "Procedural macro library used to build custom prime field implementations" documentation = "https://github.com/ebfull/ff" From c7252a43bff52b1477347594b0ee3b1f4429e717 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 27 Jun 2017 10:35:14 -0600 Subject: [PATCH 15/60] Update README/Cargo.toml with correct documentation links. --- Cargo.toml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c0418b2..6e1fde7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "ff" version = "0.2.0" authors = ["Sean Bowe "] description = "Library for building and interfacing with finite fields" -documentation = "https://github.com/ebfull/ff" +documentation = "https://docs.rs/ff/0.2.0/ff/" homepage = "https://github.com/ebfull/ff" license = "MIT/Apache-2.0" repository = "https://github.com/ebfull/ff" diff --git a/README.md b/README.md index df4bf03..4bd82ad 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Add the `ff` crate to your `Cargo.toml`: ff = "0.2" ``` -The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` traits. See the **[documentation](http)** for more. +The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` traits. See the **[documentation](https://docs.rs/ff/0.2.0/ff/)** for more. ### #![derive(PrimeField)] From 755fc7aba8e5b3a2d26591989a52e6f52a7e9333 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 26 Jun 2018 10:48:27 -0400 Subject: [PATCH 16/60] 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 e507cd7..9621548 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 99a7e7c..88696ac 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 17/60] 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 baba385..ab24be9 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 9621548..6913b65 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 18/60] 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 ab24be9..65a233a 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 19/60] 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 6e1fde7..4d8b37c 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 88696ac..8bdecc7 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 20/60] 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 4d8b37c..195b107 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 8bdecc7..541fe76 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 21/60] 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 6913b65..90e6a4b 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 22/60] 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 90e6a4b..16c4604 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 23/60] 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 16c4604..86ecf4a 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 24/60] [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 86ecf4a..e792cd8 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 25/60] 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 e792cd8..45d3445 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 26/60] Update rand crate --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 195b107..ef9a54f 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] From f6d9ec8faf96e5fd8a74ec95bbb4e707be3ad7b5 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 2 Jul 2018 07:59:33 -0600 Subject: [PATCH 27/60] Initial commit --- .gitignore | 3 + COPYRIGHT | 14 ++++ Cargo.toml | 12 +++ LICENSE-APACHE | 201 +++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE-MIT | 23 ++++++ README.md | 17 +++++ src/lib.rs | 0 7 files changed, 270 insertions(+) create mode 100644 .gitignore create mode 100644 COPYRIGHT create mode 100644 Cargo.toml create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT create mode 100644 README.md create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6936990 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..849e327 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,14 @@ +Copyrights in the "group" library are retained by their contributors. No +copyright assignment is required to contribute to the "group" library. + +The "group" library is licensed under either of + + * Apache License, Version 2.0, (see ./LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license (see ./LICENSE-MIT or http://opensource.org/licenses/MIT) + +at your option. + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..3bde5ae --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "group" +version = "0.0.0" +authors = ["Sean Bowe "] +license = "MIT/Apache-2.0" + +description = "Elliptic curve group traits and utilities" +documentation = "https://docs.rs/group/" +homepage = "https://github.com/ebfull/group" +repository = "https://github.com/ebfull/group" + +[dependencies] diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7fadc0b --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# group [![Crates.io](https://img.shields.io/crates/v/group.svg)](https://crates.io/crates/group) # + +## License + +Licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally +submitted for inclusion in the work by you, as defined in the Apache-2.0 +license, shall be dual licensed as above, without any additional terms or +conditions. diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..e69de29 From 44b601b0a9244fe062093cdc6d718301d9203d25 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 2 Jul 2018 08:34:26 -0600 Subject: [PATCH 28/60] Adjust versions --- Cargo.toml | 9 +++++---- ff_derive/Cargo.toml | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ef9a54f..d2af3de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "ff" -version = "0.2.0" +version = "0.3.0" authors = ["Sean Bowe "] description = "Library for building and interfacing with finite fields" -documentation = "https://docs.rs/ff/0.2.0/ff/" +documentation = "https://docs.rs/ff/" homepage = "https://github.com/ebfull/ff" license = "MIT/Apache-2.0" repository = "https://github.com/ebfull/ff" @@ -11,8 +11,9 @@ repository = "https://github.com/ebfull/ff" [dependencies] byteorder = "1" rand = "0.4" -ff_derive = { version = "0.2.0", path = "ff_derive" } +ff_derive = { version = "0.3.0", path = "ff_derive", optional = true } [features] +default = ["derive"] u128-support = [] -default = [] +derive = ["ff_derive"] diff --git a/ff_derive/Cargo.toml b/ff_derive/Cargo.toml index 65a233a..914e392 100644 --- a/ff_derive/Cargo.toml +++ b/ff_derive/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "ff_derive" -version = "0.2.0" +version = "0.3.0" authors = ["Sean Bowe "] description = "Procedural macro library used to build custom prime field implementations" -documentation = "https://github.com/ebfull/ff" +documentation = "https://docs.rs/ff/" homepage = "https://github.com/ebfull/ff" license = "MIT/Apache-2.0" repository = "https://github.com/ebfull/ff" From 1db099f1cc9b341286394a145780ef0af41cf866 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 30 Jun 2018 21:56:49 -0400 Subject: [PATCH 29/60] Use ff crate for Field traits --- Cargo.toml | 1 + benches/bls12_381/fq.rs | 2 +- benches/bls12_381/fq12.rs | 2 +- benches/bls12_381/fq2.rs | 2 +- benches/bls12_381/fr.rs | 2 +- benches/pairing_benches.rs | 1 + src/lib.rs | 457 +------------------------------------ 7 files changed, 8 insertions(+), 459 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 98725aa..dcf7c32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ repository = "https://github.com/ebfull/pairing" rand = "0.4" byteorder = "1" clippy = { version = "0.0.200", optional = true } +ff = "0.3" [features] unstable-features = ["expose-arith"] diff --git a/benches/bls12_381/fq.rs b/benches/bls12_381/fq.rs index af4dba4..053a10c 100644 --- a/benches/bls12_381/fq.rs +++ b/benches/bls12_381/fq.rs @@ -1,7 +1,7 @@ use rand::{Rand, SeedableRng, XorShiftRng}; +use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; use pairing::bls12_381::*; -use pairing::{Field, PrimeField, PrimeFieldRepr, SqrtField}; #[bench] fn bench_fq_repr_add_nocarry(b: &mut ::test::Bencher) { diff --git a/benches/bls12_381/fq12.rs b/benches/bls12_381/fq12.rs index 226b850..84daca2 100644 --- a/benches/bls12_381/fq12.rs +++ b/benches/bls12_381/fq12.rs @@ -1,7 +1,7 @@ use rand::{Rand, SeedableRng, XorShiftRng}; +use ff::Field; use pairing::bls12_381::*; -use pairing::Field; #[bench] fn bench_fq12_add_assign(b: &mut ::test::Bencher) { diff --git a/benches/bls12_381/fq2.rs b/benches/bls12_381/fq2.rs index ec26e98..521b6ab 100644 --- a/benches/bls12_381/fq2.rs +++ b/benches/bls12_381/fq2.rs @@ -1,7 +1,7 @@ use rand::{Rand, SeedableRng, XorShiftRng}; +use ff::{Field, SqrtField}; use pairing::bls12_381::*; -use pairing::{Field, SqrtField}; #[bench] fn bench_fq2_add_assign(b: &mut ::test::Bencher) { diff --git a/benches/bls12_381/fr.rs b/benches/bls12_381/fr.rs index 7278629..13b0d0e 100644 --- a/benches/bls12_381/fr.rs +++ b/benches/bls12_381/fr.rs @@ -1,7 +1,7 @@ use rand::{Rand, SeedableRng, XorShiftRng}; +use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; use pairing::bls12_381::*; -use pairing::{Field, PrimeField, PrimeFieldRepr, SqrtField}; #[bench] fn bench_fr_repr_add_nocarry(b: &mut ::test::Bencher) { diff --git a/benches/pairing_benches.rs b/benches/pairing_benches.rs index 424c4e7..af32a8a 100644 --- a/benches/pairing_benches.rs +++ b/benches/pairing_benches.rs @@ -1,5 +1,6 @@ #![feature(test)] +extern crate ff; extern crate pairing; extern crate rand; extern crate test; diff --git a/src/lib.rs b/src/lib.rs index 08365f1..effc050 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ #![deny(missing_debug_implementations)] extern crate byteorder; +extern crate ff; extern crate rand; #[cfg(test)] @@ -24,9 +25,9 @@ pub mod bls12_381; mod wnaf; pub use self::wnaf::Wnaf; +use ff::*; use std::error::Error; use std::fmt; -use std::io::{self, Read, Write}; /// An "engine" is a collection of types (fields, elliptic curve groups, etc.) /// with well-defined relationships. In particular, the G1/G2 curve groups are @@ -263,208 +264,6 @@ pub trait EncodedPoint: fn from_affine(affine: Self::Affine) -> Self; } -/// This trait represents an element of a field. -pub trait Field: - 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; - - /// Returns the one element of the field, the multiplicative identity. - fn one() -> Self; - - /// Returns true iff this element is zero. - fn is_zero(&self) -> bool; - - /// Squares this element. - fn square(&mut self); - - /// Doubles this element. - fn double(&mut self); - - /// Negates this element. - fn negate(&mut self); - - /// Adds another element to this element. - fn add_assign(&mut self, other: &Self); - - /// Subtracts another element from this element. - fn sub_assign(&mut self, other: &Self); - - /// Multiplies another element by this element. - fn mul_assign(&mut self, other: &Self); - - /// Computes the multiplicative inverse of this element, if nonzero. - fn inverse(&self) -> Option; - - /// Exponentiates this element by a power of the base prime modulus via - /// the Frobenius automorphism. - fn frobenius_map(&mut self, power: usize); - - /// Exponentiates this element by a number represented with `u64` limbs, - /// least significant digit first. - fn pow>(&self, exp: S) -> Self { - let mut res = Self::one(); - - let mut found_one = false; - - for i in BitIterator::new(exp) { - if found_one { - res.square(); - } else { - found_one = i; - } - - if i { - res.mul_assign(self); - } - } - - res - } -} - -/// 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; -} - -/// This trait represents a wrapper around a biginteger which can encode any element of a particular -/// prime field. It is a smart wrapper around a sequence of `u64` limbs, least-significant digit -/// first. -pub trait PrimeFieldRepr: - Sized - + Copy - + Clone - + Eq - + Ord - + Send - + Sync - + Default - + fmt::Debug - + fmt::Display - + 'static - + rand::Rand - + AsRef<[u64]> - + AsMut<[u64]> - + From -{ - /// Subtract another represetation from this one. - fn sub_noborrow(&mut self, other: &Self); - - /// Add another representation to this one. - fn add_nocarry(&mut self, other: &Self); - - /// Compute the number of bits needed to encode this number. Always a - /// multiple of 64. - fn num_bits(&self) -> u32; - - /// Returns true iff this number is zero. - fn is_zero(&self) -> bool; - - /// Returns true iff this number is odd. - fn is_odd(&self) -> bool; - - /// Returns true iff this number is even. - fn is_even(&self) -> bool; - - /// Performs a rightwise bitshift of this number, effectively dividing - /// it by 2. - fn div2(&mut self); - - /// Performs a rightwise bitshift of this number by some amount. - fn shr(&mut self, amt: u32); - - /// Performs a leftwise bitshift of this number, effectively multiplying - /// it by 2. Overflow is ignored. - fn mul2(&mut self); - - /// Performs a leftwise bitshift of this number by some amount. - fn shl(&mut self, amt: u32); - - /// Writes this `PrimeFieldRepr` as a big endian integer. - 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) - } - } - } -} - /// An error that may occur when trying to decode an `EncodedPoint`. #[derive(Debug)] pub enum GroupDecodingError { @@ -504,255 +303,3 @@ impl fmt::Display for GroupDecodingError { } } } - -/// 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 + 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; - - /// 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; - - /// How many bits are needed to represent an element of this field. - const NUM_BITS: 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; - - /// 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 { - pub fn new(t: E) -> Self { - let n = t.as_ref().len() * 64; - - BitIterator { t, n } - } -} - -impl> Iterator for BitIterator { - type Item = bool; - - fn next(&mut self) -> Option { - if self.n == 0 { - None - } else { - self.n -= 1; - let part = self.n / 64; - let bit = self.n - (64 * part); - - Some(self.t.as_ref()[part] & (1 << bit) > 0) - } - } -} - -#[test] -fn test_bit_iterator() { - let mut a = BitIterator::new([0xa953d79b83f6ab59, 0x6dea2059e200bd39]); - let expected = "01101101111010100010000001011001111000100000000010111101001110011010100101010011110101111001101110000011111101101010101101011001"; - - for e in expected.chars() { - assert!(a.next().unwrap() == (e == '1')); - } - - assert!(a.next().is_none()); - - let expected = "1010010101111110101010000101101011101000011101110101001000011001100100100011011010001011011011010001011011101100110100111011010010110001000011110100110001100110011101101000101100011100100100100100001010011101010111110011101011000011101000111011011101011001"; - - let mut a = BitIterator::new([ - 0x429d5f3ac3a3b759, - 0xb10f4c66768b1c92, - 0x92368b6d16ecd3b4, - 0xa57ea85ae8775219, - ]); - - for e in expected.chars() { - assert!(a.next().unwrap() == (e == '1')); - } - - assert!(a.next().is_none()); -} - -#[cfg(not(feature = "expose-arith"))] -use self::arith_impl::*; - -#[cfg(feature = "expose-arith")] -pub use self::arith_impl::*; - -#[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); - - *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 - } -} - -#[cfg(not(feature = "u128-support"))] -mod arith_impl { - #[inline(always)] - fn split_u64(i: u64) -> (u64, u64) { - (i >> 32, i & 0xFFFFFFFF) - } - - #[inline(always)] - fn combine_u64(hi: u64, lo: u64) -> u64 { - (hi << 32) | lo - } - - /// 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 d9d711ebb76780039a27c3cd0e6171c638ae2632 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 1 Jul 2018 07:59:34 +0100 Subject: [PATCH 30/60] Use explicit imports instead of re-exporting the ff crate --- src/bls12_381/ec.rs | 12 +-- src/bls12_381/fq.rs | 226 +++++++++++++++++++++---------------------- src/bls12_381/fq2.rs | 4 +- src/bls12_381/fr.rs | 123 +++++++++++------------ src/bls12_381/mod.rs | 4 +- src/lib.rs | 2 +- src/tests/field.rs | 2 +- 7 files changed, 185 insertions(+), 188 deletions(-) diff --git a/src/bls12_381/ec.rs b/src/bls12_381/ec.rs index 5cd5091..37fcbba 100644 --- a/src/bls12_381/ec.rs +++ b/src/bls12_381/ec.rs @@ -623,12 +623,10 @@ macro_rules! curve_impl { pub mod g1 { use super::super::{Bls12, Fq, Fq12, FqRepr, Fr, FrRepr}; use super::g2::G2Affine; + use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; use rand::{Rand, Rng}; use std::fmt; - use { - BitIterator, CurveAffine, CurveProjective, EncodedPoint, Engine, Field, GroupDecodingError, - PrimeField, PrimeFieldRepr, SqrtField, - }; + use {CurveAffine, CurveProjective, EncodedPoint, Engine, GroupDecodingError}; curve_impl!( "G1", @@ -1270,12 +1268,10 @@ pub mod g1 { pub mod g2 { use super::super::{Bls12, Fq, Fq12, Fq2, FqRepr, Fr, FrRepr}; use super::g1::G1Affine; + use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; use rand::{Rand, Rng}; use std::fmt; - use { - BitIterator, CurveAffine, CurveProjective, EncodedPoint, Engine, Field, GroupDecodingError, - PrimeField, PrimeFieldRepr, SqrtField, - }; + use {CurveAffine, CurveProjective, EncodedPoint, Engine, GroupDecodingError}; curve_impl!( "G2", diff --git a/src/bls12_381/fq.rs b/src/bls12_381/fq.rs index 738da38..e109294 100644 --- a/src/bls12_381/fq.rs +++ b/src/bls12_381/fq.rs @@ -682,7 +682,7 @@ impl PrimeFieldRepr for FqRepr { let mut carry = 0; for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::adc(*a, *b, &mut carry); + *a = ::ff::adc(*a, *b, &mut carry); } } @@ -691,7 +691,7 @@ impl PrimeFieldRepr for FqRepr { let mut borrow = 0; for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::sbb(*a, *b, &mut borrow); + *a = ::ff::sbb(*a, *b, &mut borrow); } } } @@ -909,52 +909,52 @@ impl Field for Fq { #[inline] fn mul_assign(&mut self, other: &Fq) { let mut carry = 0; - let r0 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); - let r1 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); - let r2 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); - let r3 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); - let r4 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[4], &mut carry); - let r5 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[5], &mut carry); + let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); + let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); + let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); + let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); + let r4 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[4], &mut carry); + let r5 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[5], &mut carry); let r6 = carry; let mut carry = 0; - let r1 = ::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); - let r2 = ::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); - let r3 = ::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[1], (other.0).0[4], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[1], (other.0).0[5], &mut carry); + let r1 = ::ff::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); + let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); + let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); + let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); + let r5 = ::ff::mac_with_carry(r5, (self.0).0[1], (other.0).0[4], &mut carry); + let r6 = ::ff::mac_with_carry(r6, (self.0).0[1], (other.0).0[5], &mut carry); let r7 = carry; let mut carry = 0; - let r2 = ::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); - let r3 = ::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[2], (other.0).0[4], &mut carry); - let r7 = ::mac_with_carry(r7, (self.0).0[2], (other.0).0[5], &mut carry); + let r2 = ::ff::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); + let r3 = ::ff::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); + let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); + let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); + let r6 = ::ff::mac_with_carry(r6, (self.0).0[2], (other.0).0[4], &mut carry); + let r7 = ::ff::mac_with_carry(r7, (self.0).0[2], (other.0).0[5], &mut carry); let r8 = carry; let mut carry = 0; - let r3 = ::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry); - let r7 = ::mac_with_carry(r7, (self.0).0[3], (other.0).0[4], &mut carry); - let r8 = ::mac_with_carry(r8, (self.0).0[3], (other.0).0[5], &mut carry); + let r3 = ::ff::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); + let r4 = ::ff::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); + let r5 = ::ff::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); + let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry); + let r7 = ::ff::mac_with_carry(r7, (self.0).0[3], (other.0).0[4], &mut carry); + let r8 = ::ff::mac_with_carry(r8, (self.0).0[3], (other.0).0[5], &mut carry); let r9 = carry; let mut carry = 0; - let r4 = ::mac_with_carry(r4, (self.0).0[4], (other.0).0[0], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[4], (other.0).0[1], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[4], (other.0).0[2], &mut carry); - let r7 = ::mac_with_carry(r7, (self.0).0[4], (other.0).0[3], &mut carry); - let r8 = ::mac_with_carry(r8, (self.0).0[4], (other.0).0[4], &mut carry); - let r9 = ::mac_with_carry(r9, (self.0).0[4], (other.0).0[5], &mut carry); + let r4 = ::ff::mac_with_carry(r4, (self.0).0[4], (other.0).0[0], &mut carry); + let r5 = ::ff::mac_with_carry(r5, (self.0).0[4], (other.0).0[1], &mut carry); + let r6 = ::ff::mac_with_carry(r6, (self.0).0[4], (other.0).0[2], &mut carry); + let r7 = ::ff::mac_with_carry(r7, (self.0).0[4], (other.0).0[3], &mut carry); + let r8 = ::ff::mac_with_carry(r8, (self.0).0[4], (other.0).0[4], &mut carry); + let r9 = ::ff::mac_with_carry(r9, (self.0).0[4], (other.0).0[5], &mut carry); let r10 = carry; let mut carry = 0; - let r5 = ::mac_with_carry(r5, (self.0).0[5], (other.0).0[0], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[5], (other.0).0[1], &mut carry); - let r7 = ::mac_with_carry(r7, (self.0).0[5], (other.0).0[2], &mut carry); - let r8 = ::mac_with_carry(r8, (self.0).0[5], (other.0).0[3], &mut carry); - let r9 = ::mac_with_carry(r9, (self.0).0[5], (other.0).0[4], &mut carry); - let r10 = ::mac_with_carry(r10, (self.0).0[5], (other.0).0[5], &mut carry); + let r5 = ::ff::mac_with_carry(r5, (self.0).0[5], (other.0).0[0], &mut carry); + let r6 = ::ff::mac_with_carry(r6, (self.0).0[5], (other.0).0[1], &mut carry); + let r7 = ::ff::mac_with_carry(r7, (self.0).0[5], (other.0).0[2], &mut carry); + let r8 = ::ff::mac_with_carry(r8, (self.0).0[5], (other.0).0[3], &mut carry); + let r9 = ::ff::mac_with_carry(r9, (self.0).0[5], (other.0).0[4], &mut carry); + let r10 = ::ff::mac_with_carry(r10, (self.0).0[5], (other.0).0[5], &mut carry); let r11 = carry; self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11); } @@ -962,29 +962,29 @@ impl Field for Fq { #[inline] fn square(&mut self) { let mut carry = 0; - let r1 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); - let r2 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); - let r3 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry); - let r4 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[4], &mut carry); - let r5 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[5], &mut carry); + let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); + let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); + let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry); + let r4 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[4], &mut carry); + let r5 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[5], &mut carry); let r6 = carry; let mut carry = 0; - let r3 = ::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[1], (self.0).0[4], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[1], (self.0).0[5], &mut carry); + let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry); + let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry); + let r5 = ::ff::mac_with_carry(r5, (self.0).0[1], (self.0).0[4], &mut carry); + let r6 = ::ff::mac_with_carry(r6, (self.0).0[1], (self.0).0[5], &mut carry); let r7 = carry; let mut carry = 0; - let r5 = ::mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[2], (self.0).0[4], &mut carry); - let r7 = ::mac_with_carry(r7, (self.0).0[2], (self.0).0[5], &mut carry); + let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry); + let r6 = ::ff::mac_with_carry(r6, (self.0).0[2], (self.0).0[4], &mut carry); + let r7 = ::ff::mac_with_carry(r7, (self.0).0[2], (self.0).0[5], &mut carry); let r8 = carry; let mut carry = 0; - let r7 = ::mac_with_carry(r7, (self.0).0[3], (self.0).0[4], &mut carry); - let r8 = ::mac_with_carry(r8, (self.0).0[3], (self.0).0[5], &mut carry); + let r7 = ::ff::mac_with_carry(r7, (self.0).0[3], (self.0).0[4], &mut carry); + let r8 = ::ff::mac_with_carry(r8, (self.0).0[3], (self.0).0[5], &mut carry); let r9 = carry; let mut carry = 0; - let r9 = ::mac_with_carry(r9, (self.0).0[4], (self.0).0[5], &mut carry); + let r9 = ::ff::mac_with_carry(r9, (self.0).0[4], (self.0).0[5], &mut carry); let r10 = carry; let r11 = r10 >> 63; @@ -1000,18 +1000,18 @@ impl Field for Fq { let r1 = r1 << 1; let mut carry = 0; - let r0 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry); - let r1 = ::adc(r1, 0, &mut carry); - let r2 = ::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry); - let r3 = ::adc(r3, 0, &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry); - let r5 = ::adc(r5, 0, &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry); - let r7 = ::adc(r7, 0, &mut carry); - let r8 = ::mac_with_carry(r8, (self.0).0[4], (self.0).0[4], &mut carry); - let r9 = ::adc(r9, 0, &mut carry); - let r10 = ::mac_with_carry(r10, (self.0).0[5], (self.0).0[5], &mut carry); - let r11 = ::adc(r11, 0, &mut carry); + let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry); + let r1 = ::ff::adc(r1, 0, &mut carry); + let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry); + let r3 = ::ff::adc(r3, 0, &mut carry); + let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry); + let r5 = ::ff::adc(r5, 0, &mut carry); + let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry); + let r7 = ::ff::adc(r7, 0, &mut carry); + let r8 = ::ff::mac_with_carry(r8, (self.0).0[4], (self.0).0[4], &mut carry); + let r9 = ::ff::adc(r9, 0, &mut carry); + let r10 = ::ff::mac_with_carry(r10, (self.0).0[5], (self.0).0[5], &mut carry); + let r11 = ::ff::adc(r11, 0, &mut carry); self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11); } } @@ -1055,63 +1055,63 @@ impl Fq { let k = r0.wrapping_mul(INV); let mut carry = 0; - ::mac_with_carry(r0, k, MODULUS.0[0], &mut carry); - r1 = ::mac_with_carry(r1, k, MODULUS.0[1], &mut carry); - r2 = ::mac_with_carry(r2, k, MODULUS.0[2], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[3], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[4], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[5], &mut carry); - r6 = ::adc(r6, 0, &mut carry); + ::ff::mac_with_carry(r0, k, MODULUS.0[0], &mut carry); + r1 = ::ff::mac_with_carry(r1, k, MODULUS.0[1], &mut carry); + r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[2], &mut carry); + r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[3], &mut carry); + r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[4], &mut carry); + r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[5], &mut carry); + r6 = ::ff::adc(r6, 0, &mut carry); let carry2 = carry; let k = r1.wrapping_mul(INV); let mut carry = 0; - ::mac_with_carry(r1, k, MODULUS.0[0], &mut carry); - r2 = ::mac_with_carry(r2, k, MODULUS.0[1], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[2], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[3], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[4], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[5], &mut carry); - r7 = ::adc(r7, carry2, &mut carry); + ::ff::mac_with_carry(r1, k, MODULUS.0[0], &mut carry); + r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[1], &mut carry); + r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[2], &mut carry); + r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[3], &mut carry); + r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[4], &mut carry); + r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[5], &mut carry); + r7 = ::ff::adc(r7, carry2, &mut carry); let carry2 = carry; let k = r2.wrapping_mul(INV); let mut carry = 0; - ::mac_with_carry(r2, k, MODULUS.0[0], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[1], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[2], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[3], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[4], &mut carry); - r7 = ::mac_with_carry(r7, k, MODULUS.0[5], &mut carry); - r8 = ::adc(r8, carry2, &mut carry); + ::ff::mac_with_carry(r2, k, MODULUS.0[0], &mut carry); + r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[1], &mut carry); + r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[2], &mut carry); + r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[3], &mut carry); + r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[4], &mut carry); + r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[5], &mut carry); + r8 = ::ff::adc(r8, carry2, &mut carry); let carry2 = carry; let k = r3.wrapping_mul(INV); let mut carry = 0; - ::mac_with_carry(r3, k, MODULUS.0[0], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[1], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[2], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[3], &mut carry); - r7 = ::mac_with_carry(r7, k, MODULUS.0[4], &mut carry); - r8 = ::mac_with_carry(r8, k, MODULUS.0[5], &mut carry); - r9 = ::adc(r9, carry2, &mut carry); + ::ff::mac_with_carry(r3, k, MODULUS.0[0], &mut carry); + r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[1], &mut carry); + r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[2], &mut carry); + r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[3], &mut carry); + r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[4], &mut carry); + r8 = ::ff::mac_with_carry(r8, k, MODULUS.0[5], &mut carry); + r9 = ::ff::adc(r9, carry2, &mut carry); let carry2 = carry; let k = r4.wrapping_mul(INV); let mut carry = 0; - ::mac_with_carry(r4, k, MODULUS.0[0], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[1], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[2], &mut carry); - r7 = ::mac_with_carry(r7, k, MODULUS.0[3], &mut carry); - r8 = ::mac_with_carry(r8, k, MODULUS.0[4], &mut carry); - r9 = ::mac_with_carry(r9, k, MODULUS.0[5], &mut carry); - r10 = ::adc(r10, carry2, &mut carry); + ::ff::mac_with_carry(r4, k, MODULUS.0[0], &mut carry); + r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[1], &mut carry); + r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[2], &mut carry); + r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[3], &mut carry); + r8 = ::ff::mac_with_carry(r8, k, MODULUS.0[4], &mut carry); + r9 = ::ff::mac_with_carry(r9, k, MODULUS.0[5], &mut carry); + r10 = ::ff::adc(r10, carry2, &mut carry); let carry2 = carry; let k = r5.wrapping_mul(INV); let mut carry = 0; - ::mac_with_carry(r5, k, MODULUS.0[0], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[1], &mut carry); - r7 = ::mac_with_carry(r7, k, MODULUS.0[2], &mut carry); - r8 = ::mac_with_carry(r8, k, MODULUS.0[3], &mut carry); - r9 = ::mac_with_carry(r9, k, MODULUS.0[4], &mut carry); - r10 = ::mac_with_carry(r10, k, MODULUS.0[5], &mut carry); - r11 = ::adc(r11, carry2, &mut carry); + ::ff::mac_with_carry(r5, k, MODULUS.0[0], &mut carry); + r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[1], &mut carry); + r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[2], &mut carry); + r8 = ::ff::mac_with_carry(r8, k, MODULUS.0[3], &mut carry); + r9 = ::ff::mac_with_carry(r9, k, MODULUS.0[4], &mut carry); + r10 = ::ff::mac_with_carry(r10, k, MODULUS.0[5], &mut carry); + r11 = ::ff::adc(r11, carry2, &mut carry); (self.0).0[0] = r6; (self.0).0[1] = r7; (self.0).0[2] = r8; @@ -1123,9 +1123,7 @@ impl Fq { } impl SqrtField for Fq { - fn legendre(&self) -> ::LegendreSymbol { - use LegendreSymbol::*; - + fn legendre(&self) -> ::ff::LegendreSymbol { // s = self^((q - 1) // 2) let s = self.pow([ 0xdcff7fffffffd555, @@ -1136,11 +1134,11 @@ impl SqrtField for Fq { 0xd0088f51cbff34d, ]); if s == Fq::zero() { - Zero + ::ff::LegendreSymbol::Zero } else if s == Fq::one() { - QuadraticResidue + ::ff::LegendreSymbol::QuadraticResidue } else { - QuadraticNonResidue + ::ff::LegendreSymbol::QuadraticNonResidue } } @@ -2924,7 +2922,7 @@ fn fq_repr_tests() { #[test] fn test_fq_legendre() { - use LegendreSymbol::*; + use ff::LegendreSymbol::*; assert_eq!(QuadraticResidue, Fq::one().legendre()); assert_eq!(Zero, Fq::zero().legendre()); diff --git a/src/bls12_381/fq2.rs b/src/bls12_381/fq2.rs index 18cd580..1f3cd6f 100644 --- a/src/bls12_381/fq2.rs +++ b/src/bls12_381/fq2.rs @@ -160,7 +160,7 @@ impl Field for Fq2 { } impl SqrtField for Fq2 { - fn legendre(&self) -> ::LegendreSymbol { + fn legendre(&self) -> ::ff::LegendreSymbol { self.norm().legendre() } @@ -865,7 +865,7 @@ fn test_fq2_sqrt() { #[test] fn test_fq2_legendre() { - use LegendreSymbol::*; + use ff::LegendreSymbol::*; assert_eq!(Zero, Fq2::zero().legendre()); // i^2 = -1 diff --git a/src/bls12_381/fr.rs b/src/bls12_381/fr.rs index 4e9d6ab..e9eee24 100644 --- a/src/bls12_381/fr.rs +++ b/src/bls12_381/fr.rs @@ -1,5 +1,4 @@ -use LegendreSymbol::*; -use {Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField}; +use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField}; // r = 52435875175126190479447740508185965837690552500527637822603658699938581184513 const MODULUS: FrRepr = FrRepr([ @@ -229,7 +228,7 @@ impl PrimeFieldRepr for FrRepr { let mut carry = 0; for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::adc(*a, *b, &mut carry); + *a = ::ff::adc(*a, *b, &mut carry); } } @@ -238,7 +237,7 @@ impl PrimeFieldRepr for FrRepr { let mut borrow = 0; for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::sbb(*a, *b, &mut borrow); + *a = ::ff::sbb(*a, *b, &mut borrow); } } } @@ -437,28 +436,28 @@ impl Field for Fr { #[inline] fn mul_assign(&mut self, other: &Fr) { let mut carry = 0; - let r0 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); - let r1 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); - let r2 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); - let r3 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); + let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); + let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); + let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); + let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); let r4 = carry; let mut carry = 0; - let r1 = ::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); - let r2 = ::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); - let r3 = ::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); + let r1 = ::ff::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); + let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); + let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); + let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); let r5 = carry; let mut carry = 0; - let r2 = ::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); - let r3 = ::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); + let r2 = ::ff::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); + let r3 = ::ff::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); + let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); + let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); let r6 = carry; let mut carry = 0; - let r3 = ::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry); + let r3 = ::ff::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); + let r4 = ::ff::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); + let r5 = ::ff::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); + let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry); let r7 = carry; self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7); } @@ -466,16 +465,16 @@ impl Field for Fr { #[inline] fn square(&mut self) { let mut carry = 0; - let r1 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); - let r2 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); - let r3 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry); + let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); + let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); + let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry); let r4 = carry; let mut carry = 0; - let r3 = ::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry); + let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry); + let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry); let r5 = carry; let mut carry = 0; - let r5 = ::mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry); + let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry); let r6 = carry; let r7 = r6 >> 63; @@ -487,14 +486,14 @@ impl Field for Fr { let r1 = r1 << 1; let mut carry = 0; - let r0 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry); - let r1 = ::adc(r1, 0, &mut carry); - let r2 = ::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry); - let r3 = ::adc(r3, 0, &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry); - let r5 = ::adc(r5, 0, &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry); - let r7 = ::adc(r7, 0, &mut carry); + let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry); + let r1 = ::ff::adc(r1, 0, &mut carry); + let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry); + let r3 = ::ff::adc(r3, 0, &mut carry); + let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry); + let r5 = ::ff::adc(r5, 0, &mut carry); + let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry); + let r7 = ::ff::adc(r7, 0, &mut carry); self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7); } } @@ -534,35 +533,35 @@ impl Fr { let k = r0.wrapping_mul(INV); let mut carry = 0; - ::mac_with_carry(r0, k, MODULUS.0[0], &mut carry); - r1 = ::mac_with_carry(r1, k, MODULUS.0[1], &mut carry); - r2 = ::mac_with_carry(r2, k, MODULUS.0[2], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[3], &mut carry); - r4 = ::adc(r4, 0, &mut carry); + ::ff::mac_with_carry(r0, k, MODULUS.0[0], &mut carry); + r1 = ::ff::mac_with_carry(r1, k, MODULUS.0[1], &mut carry); + r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[2], &mut carry); + r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[3], &mut carry); + r4 = ::ff::adc(r4, 0, &mut carry); let carry2 = carry; let k = r1.wrapping_mul(INV); let mut carry = 0; - ::mac_with_carry(r1, k, MODULUS.0[0], &mut carry); - r2 = ::mac_with_carry(r2, k, MODULUS.0[1], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[2], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[3], &mut carry); - r5 = ::adc(r5, carry2, &mut carry); + ::ff::mac_with_carry(r1, k, MODULUS.0[0], &mut carry); + r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[1], &mut carry); + r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[2], &mut carry); + r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[3], &mut carry); + r5 = ::ff::adc(r5, carry2, &mut carry); let carry2 = carry; let k = r2.wrapping_mul(INV); let mut carry = 0; - ::mac_with_carry(r2, k, MODULUS.0[0], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[1], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[2], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[3], &mut carry); - r6 = ::adc(r6, carry2, &mut carry); + ::ff::mac_with_carry(r2, k, MODULUS.0[0], &mut carry); + r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[1], &mut carry); + r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[2], &mut carry); + r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[3], &mut carry); + r6 = ::ff::adc(r6, carry2, &mut carry); let carry2 = carry; let k = r3.wrapping_mul(INV); let mut carry = 0; - ::mac_with_carry(r3, k, MODULUS.0[0], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[1], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[2], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[3], &mut carry); - r7 = ::adc(r7, carry2, &mut carry); + ::ff::mac_with_carry(r3, k, MODULUS.0[0], &mut carry); + r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[1], &mut carry); + r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[2], &mut carry); + r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[3], &mut carry); + r7 = ::ff::adc(r7, carry2, &mut carry); (self.0).0[0] = r4; (self.0).0[1] = r5; (self.0).0[2] = r6; @@ -572,7 +571,7 @@ impl Fr { } impl SqrtField for Fr { - fn legendre(&self) -> ::LegendreSymbol { + fn legendre(&self) -> ::ff::LegendreSymbol { // s = self^((r - 1) // 2) let s = self.pow([ 0x7fffffff80000000, @@ -581,11 +580,11 @@ impl SqrtField for Fr { 0x39f6d3a994cebea4, ]); if s == Self::zero() { - Zero + ::ff::LegendreSymbol::Zero } else if s == Self::one() { - QuadraticResidue + ::ff::LegendreSymbol::QuadraticResidue } else { - QuadraticNonResidue + ::ff::LegendreSymbol::QuadraticNonResidue } } @@ -593,9 +592,9 @@ impl SqrtField for Fr { // Tonelli-Shank's algorithm for q mod 16 = 1 // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) match self.legendre() { - Zero => Some(*self), - QuadraticNonResidue => None, - QuadraticResidue => { + ::ff::LegendreSymbol::Zero => Some(*self), + ::ff::LegendreSymbol::QuadraticNonResidue => None, + ::ff::LegendreSymbol::QuadraticResidue => { let mut c = Fr(ROOT_OF_UNITY); // r = self^((t + 1) // 2) let mut r = self.pow([ @@ -909,6 +908,8 @@ fn test_fr_repr_sub_noborrow() { #[test] fn test_fr_legendre() { + use ff::LegendreSymbol::*; + assert_eq!(QuadraticResidue, Fr::one().legendre()); assert_eq!(Zero, Fr::zero().legendre()); diff --git a/src/bls12_381/mod.rs b/src/bls12_381/mod.rs index a5db4b5..c6c13c5 100644 --- a/src/bls12_381/mod.rs +++ b/src/bls12_381/mod.rs @@ -18,7 +18,9 @@ pub use self::fq2::Fq2; pub use self::fq6::Fq6; pub use self::fr::{Fr, FrRepr}; -use super::{BitIterator, CurveAffine, Engine, Field}; +use super::{CurveAffine, Engine}; + +use ff::{BitIterator, Field}; // The BLS parameter x for BLS12-381 is -0xd201000000010000 const BLS_X: u64 = 0xd201000000010000; diff --git a/src/lib.rs b/src/lib.rs index effc050..0c336ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ pub mod bls12_381; mod wnaf; pub use self::wnaf::Wnaf; -use ff::*; +use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField}; use std::error::Error; use std::fmt; diff --git a/src/tests/field.rs b/src/tests/field.rs index 74422fd..55396a7 100644 --- a/src/tests/field.rs +++ b/src/tests/field.rs @@ -1,5 +1,5 @@ +use ff::{Field, LegendreSymbol, PrimeField, SqrtField}; use rand::{Rng, SeedableRng, XorShiftRng}; -use {Field, LegendreSymbol, PrimeField, SqrtField}; pub fn random_frobenius_tests>(characteristic: C, maxpower: usize) { let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); From a9d8079c2a9388d2a0f22f8f43d0dad9db877c00 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 06:57:05 +0100 Subject: [PATCH 31/60] Replace implementations of Fq and Fr with derives --- benches/bls12_381/fr.rs | 2 +- src/bls12_381/fq.rs | 735 +--------------------------------------- src/bls12_381/fr.rs | 649 +---------------------------------- src/lib.rs | 1 + 4 files changed, 22 insertions(+), 1365 deletions(-) diff --git a/benches/bls12_381/fr.rs b/benches/bls12_381/fr.rs index 13b0d0e..9cab671 100644 --- a/benches/bls12_381/fr.rs +++ b/benches/bls12_381/fr.rs @@ -1,6 +1,6 @@ use rand::{Rand, SeedableRng, XorShiftRng}; -use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; +use ff::{Field, PrimeField, PrimeFieldRepr}; use pairing::bls12_381::*; #[bench] diff --git a/src/bls12_381/fq.rs b/src/bls12_381/fq.rs index e109294..2b4b7a6 100644 --- a/src/bls12_381/fq.rs +++ b/src/bls12_381/fq.rs @@ -1,69 +1,5 @@ use super::fq2::Fq2; -use std::cmp::Ordering; -use {Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField}; - -// q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 -const MODULUS: FqRepr = FqRepr([ - 0xb9feffffffffaaab, - 0x1eabfffeb153ffff, - 0x6730d2a0f6b0f624, - 0x64774b84f38512bf, - 0x4b1ba7b6434bacd7, - 0x1a0111ea397fe69a, -]); - -// The number of bits needed to represent the modulus. -const MODULUS_BITS: u32 = 381; - -// The number of bits that must be shaved from the beginning of -// the representation when randomly sampling. -const REPR_SHAVE_BITS: u32 = 3; - -// R = 2**384 % q -const R: FqRepr = FqRepr([ - 0x760900000002fffd, - 0xebf4000bc40c0002, - 0x5f48985753c758ba, - 0x77ce585370525745, - 0x5c071a97a256ec6d, - 0x15f65ec3fa80e493, -]); - -// R2 = R^2 % q -const R2: FqRepr = FqRepr([ - 0xf4df1f341c341746, - 0xa76e6a609d104f1, - 0x8de5476c4c95b6d5, - 0x67eb88a9939d83c0, - 0x9a793e85b519952d, - 0x11988fe592cae3aa, -]); - -// INV = -(q^{-1} mod 2^64) mod 2^64 -const INV: u64 = 0x89f3fffcfffcfffd; - -// GENERATOR = 2 (multiplicative generator of q-1 order, that is also quadratic nonresidue) -const GENERATOR: FqRepr = FqRepr([ - 0x321300000006554f, - 0xb93c0018d6c40005, - 0x57605e0db0ddbb51, - 0x8b256521ed1f9bcb, - 0x6cf28d7901622c03, - 0x11ebab9dbb81e28c, -]); - -// 2^s * t = MODULUS - 1 with t odd -const S: u32 = 1; - -// 2^s root of unity computed by GENERATOR^t -const ROOT_OF_UNITY: FqRepr = FqRepr([ - 0x43f5fffffffcaaae, - 0x32b7fff2ed47fffd, - 0x7e83a49a2e99d69, - 0xeca8f3318332bb7a, - 0xef148d1ea0f4c069, - 0x40ab3263eff0206, -]); +use {Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; // B coefficient of BLS12-381 curve, 4. pub const B_COEFF: Fq = Fq(FqRepr([ @@ -507,667 +443,11 @@ pub const NEGATIVE_ONE: Fq = Fq(FqRepr([ 0x40ab3263eff0206, ])); -#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] -pub struct FqRepr(pub [u64; 6]); - -impl ::rand::Rand for FqRepr { - #[inline(always)] - fn rand(rng: &mut R) -> Self { - FqRepr(rng.gen()) - } -} - -impl ::std::fmt::Display for FqRepr { - 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 FqRepr { - #[inline(always)] - fn as_ref(&self) -> &[u64] { - &self.0 - } -} - -impl AsMut<[u64]> for FqRepr { - #[inline(always)] - fn as_mut(&mut self) -> &mut [u64] { - &mut self.0 - } -} - -impl From for FqRepr { - #[inline(always)] - fn from(val: u64) -> FqRepr { - let mut repr = Self::default(); - repr.0[0] = val; - repr - } -} - -impl Ord for FqRepr { - #[inline(always)] - fn cmp(&self, other: &FqRepr) -> Ordering { - for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) { - if a < b { - return Ordering::Less; - } else if a > b { - return Ordering::Greater; - } - } - - Ordering::Equal - } -} - -impl PartialOrd for FqRepr { - #[inline(always)] - fn partial_cmp(&self, other: &FqRepr) -> Option { - Some(self.cmp(other)) - } -} - -impl PrimeFieldRepr for FqRepr { - #[inline(always)] - fn is_odd(&self) -> bool { - self.0[0] & 1 == 1 - } - - #[inline(always)] - fn is_even(&self) -> bool { - !self.is_odd() - } - - #[inline(always)] - fn is_zero(&self) -> bool { - self.0.iter().all(|&e| e == 0) - } - - #[inline(always)] - fn shr(&mut self, mut n: u32) { - if n >= 64 * 6 { - *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 div2(&mut self) { - let mut t = 0; - for i in self.0.iter_mut().rev() { - let t2 = *i << 63; - *i >>= 1; - *i |= t; - t = t2; - } - } - - #[inline(always)] - fn mul2(&mut self) { - let mut last = 0; - for i in &mut self.0 { - let tmp = *i >> 63; - *i <<= 1; - *i |= last; - last = tmp; - } - } - - #[inline(always)] - fn shl(&mut self, mut n: u32) { - if n >= 64 * 6 { - *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 = (6 as u32) * 64; - for i in self.0.iter().rev() { - let leading = i.leading_zeros(); - ret -= leading; - if leading != 64 { - break; - } - } - - ret - } - - #[inline(always)] - fn add_nocarry(&mut self, other: &FqRepr) { - let mut carry = 0; - - for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::ff::adc(*a, *b, &mut carry); - } - } - - #[inline(always)] - fn sub_noborrow(&mut self, other: &FqRepr) { - let mut borrow = 0; - - for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::ff::sbb(*a, *b, &mut borrow); - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(PrimeField)] +#[PrimeFieldModulus = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787"] +#[PrimeFieldGenerator = "2"] pub struct Fq(FqRepr); -/// `Fq` elements are ordered lexicographically. -impl Ord for Fq { - #[inline(always)] - fn cmp(&self, other: &Fq) -> Ordering { - self.into_repr().cmp(&other.into_repr()) - } -} - -impl PartialOrd for Fq { - #[inline(always)] - fn partial_cmp(&self, other: &Fq) -> Option { - Some(self.cmp(other)) - } -} - -impl ::std::fmt::Display for Fq { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "Fq({})", self.into_repr()) - } -} - -impl ::rand::Rand for Fq { - fn rand(rng: &mut R) -> Self { - loop { - let mut tmp = Fq(FqRepr::rand(rng)); - - // Mask away the unused bits at the beginning. - tmp.0.as_mut()[5] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; - - if tmp.is_valid() { - return tmp; - } - } - } -} - -impl From for FqRepr { - fn from(e: Fq) -> FqRepr { - e.into_repr() - } -} - -impl PrimeField for Fq { - type Repr = FqRepr; - - fn from_repr(r: FqRepr) -> Result { - let mut r = Fq(r); - if r.is_valid() { - r.mul_assign(&Fq(R2)); - - Ok(r) - } else { - Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0))) - } - } - - fn into_repr(&self) -> FqRepr { - let mut r = *self; - r.mont_reduce( - (self.0).0[0], - (self.0).0[1], - (self.0).0[2], - (self.0).0[3], - (self.0).0[4], - (self.0).0[5], - 0, - 0, - 0, - 0, - 0, - 0, - ); - r.0 - } - - fn char() -> FqRepr { - MODULUS - } - - const NUM_BITS: u32 = MODULUS_BITS; - - const CAPACITY: u32 = Self::NUM_BITS - 1; - - fn multiplicative_generator() -> Self { - Fq(GENERATOR) - } - - const S: u32 = S; - - fn root_of_unity() -> Self { - Fq(ROOT_OF_UNITY) - } -} - -impl Field for Fq { - #[inline] - fn zero() -> Self { - Fq(FqRepr::from(0)) - } - - #[inline] - fn one() -> Self { - Fq(R) - } - - #[inline] - fn is_zero(&self) -> bool { - self.0.is_zero() - } - - #[inline] - fn add_assign(&mut self, other: &Fq) { - // This cannot exceed the backing capacity. - self.0.add_nocarry(&other.0); - - // However, it may need to be reduced. - self.reduce(); - } - - #[inline] - fn double(&mut self) { - // This cannot exceed the backing capacity. - self.0.mul2(); - - // However, it may need to be reduced. - self.reduce(); - } - - #[inline] - fn sub_assign(&mut self, other: &Fq) { - // 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); - } - - #[inline] - fn negate(&mut self) { - if !self.is_zero() { - let mut tmp = MODULUS; - tmp.sub_noborrow(&self.0); - self.0 = tmp; - } - } - - fn inverse(&self) -> Option { - if self.is_zero() { - None - } else { - // Guajardo Kumar Paar Pelzl - // Efficient Software-Implementation of Finite Fields with Applications to Cryptography - // Algorithm 16 (BEA for Inversion in Fp) - - let one = FqRepr::from(1); - - let mut u = self.0; - let mut v = MODULUS; - let mut b = Fq(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 { - Some(b) - } else { - Some(c) - } - } - } - - #[inline(always)] - fn frobenius_map(&mut self, _: usize) { - // This has no effect in a prime field. - } - - #[inline] - fn mul_assign(&mut self, other: &Fq) { - let mut carry = 0; - let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); - let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); - let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); - let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); - let r4 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[4], &mut carry); - let r5 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[5], &mut carry); - let r6 = carry; - let mut carry = 0; - let r1 = ::ff::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); - let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); - let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[1], (other.0).0[4], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[1], (other.0).0[5], &mut carry); - let r7 = carry; - let mut carry = 0; - let r2 = ::ff::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); - let r3 = ::ff::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[2], (other.0).0[4], &mut carry); - let r7 = ::ff::mac_with_carry(r7, (self.0).0[2], (other.0).0[5], &mut carry); - let r8 = carry; - let mut carry = 0; - let r3 = ::ff::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry); - let r7 = ::ff::mac_with_carry(r7, (self.0).0[3], (other.0).0[4], &mut carry); - let r8 = ::ff::mac_with_carry(r8, (self.0).0[3], (other.0).0[5], &mut carry); - let r9 = carry; - let mut carry = 0; - let r4 = ::ff::mac_with_carry(r4, (self.0).0[4], (other.0).0[0], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[4], (other.0).0[1], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[4], (other.0).0[2], &mut carry); - let r7 = ::ff::mac_with_carry(r7, (self.0).0[4], (other.0).0[3], &mut carry); - let r8 = ::ff::mac_with_carry(r8, (self.0).0[4], (other.0).0[4], &mut carry); - let r9 = ::ff::mac_with_carry(r9, (self.0).0[4], (other.0).0[5], &mut carry); - let r10 = carry; - let mut carry = 0; - let r5 = ::ff::mac_with_carry(r5, (self.0).0[5], (other.0).0[0], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[5], (other.0).0[1], &mut carry); - let r7 = ::ff::mac_with_carry(r7, (self.0).0[5], (other.0).0[2], &mut carry); - let r8 = ::ff::mac_with_carry(r8, (self.0).0[5], (other.0).0[3], &mut carry); - let r9 = ::ff::mac_with_carry(r9, (self.0).0[5], (other.0).0[4], &mut carry); - let r10 = ::ff::mac_with_carry(r10, (self.0).0[5], (other.0).0[5], &mut carry); - let r11 = carry; - self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11); - } - - #[inline] - fn square(&mut self) { - let mut carry = 0; - let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); - let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); - let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry); - let r4 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[4], &mut carry); - let r5 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[5], &mut carry); - let r6 = carry; - let mut carry = 0; - let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[1], (self.0).0[4], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[1], (self.0).0[5], &mut carry); - let r7 = carry; - let mut carry = 0; - let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[2], (self.0).0[4], &mut carry); - let r7 = ::ff::mac_with_carry(r7, (self.0).0[2], (self.0).0[5], &mut carry); - let r8 = carry; - let mut carry = 0; - let r7 = ::ff::mac_with_carry(r7, (self.0).0[3], (self.0).0[4], &mut carry); - let r8 = ::ff::mac_with_carry(r8, (self.0).0[3], (self.0).0[5], &mut carry); - let r9 = carry; - let mut carry = 0; - let r9 = ::ff::mac_with_carry(r9, (self.0).0[4], (self.0).0[5], &mut carry); - let r10 = carry; - - let r11 = r10 >> 63; - let r10 = (r10 << 1) | (r9 >> 63); - let r9 = (r9 << 1) | (r8 >> 63); - let r8 = (r8 << 1) | (r7 >> 63); - let r7 = (r7 << 1) | (r6 >> 63); - let r6 = (r6 << 1) | (r5 >> 63); - let r5 = (r5 << 1) | (r4 >> 63); - let r4 = (r4 << 1) | (r3 >> 63); - let r3 = (r3 << 1) | (r2 >> 63); - let r2 = (r2 << 1) | (r1 >> 63); - let r1 = r1 << 1; - - let mut carry = 0; - let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry); - let r1 = ::ff::adc(r1, 0, &mut carry); - let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry); - let r3 = ::ff::adc(r3, 0, &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry); - let r5 = ::ff::adc(r5, 0, &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry); - let r7 = ::ff::adc(r7, 0, &mut carry); - let r8 = ::ff::mac_with_carry(r8, (self.0).0[4], (self.0).0[4], &mut carry); - let r9 = ::ff::adc(r9, 0, &mut carry); - let r10 = ::ff::mac_with_carry(r10, (self.0).0[5], (self.0).0[5], &mut carry); - let r11 = ::ff::adc(r11, 0, &mut carry); - self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11); - } -} - -impl Fq { - /// 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 internally. - #[inline(always)] - fn reduce(&mut self) { - if !self.is_valid() { - self.0.sub_noborrow(&MODULUS); - } - } - - #[inline(always)] - fn mont_reduce( - &mut self, - r0: u64, - mut r1: u64, - mut r2: u64, - mut r3: u64, - mut r4: u64, - mut r5: u64, - mut r6: u64, - mut r7: u64, - mut r8: u64, - mut r9: u64, - mut r10: u64, - mut r11: u64, - ) { - // The Montgomery reduction here is based on Algorithm 14.32 in - // Handbook of Applied Cryptography - // . - - let k = r0.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r0, k, MODULUS.0[0], &mut carry); - r1 = ::ff::mac_with_carry(r1, k, MODULUS.0[1], &mut carry); - r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[2], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[3], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[4], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[5], &mut carry); - r6 = ::ff::adc(r6, 0, &mut carry); - let carry2 = carry; - let k = r1.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r1, k, MODULUS.0[0], &mut carry); - r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[1], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[2], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[3], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[4], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[5], &mut carry); - r7 = ::ff::adc(r7, carry2, &mut carry); - let carry2 = carry; - let k = r2.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r2, k, MODULUS.0[0], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[1], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[2], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[3], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[4], &mut carry); - r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[5], &mut carry); - r8 = ::ff::adc(r8, carry2, &mut carry); - let carry2 = carry; - let k = r3.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r3, k, MODULUS.0[0], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[1], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[2], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[3], &mut carry); - r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[4], &mut carry); - r8 = ::ff::mac_with_carry(r8, k, MODULUS.0[5], &mut carry); - r9 = ::ff::adc(r9, carry2, &mut carry); - let carry2 = carry; - let k = r4.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r4, k, MODULUS.0[0], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[1], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[2], &mut carry); - r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[3], &mut carry); - r8 = ::ff::mac_with_carry(r8, k, MODULUS.0[4], &mut carry); - r9 = ::ff::mac_with_carry(r9, k, MODULUS.0[5], &mut carry); - r10 = ::ff::adc(r10, carry2, &mut carry); - let carry2 = carry; - let k = r5.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r5, k, MODULUS.0[0], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[1], &mut carry); - r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[2], &mut carry); - r8 = ::ff::mac_with_carry(r8, k, MODULUS.0[3], &mut carry); - r9 = ::ff::mac_with_carry(r9, k, MODULUS.0[4], &mut carry); - r10 = ::ff::mac_with_carry(r10, k, MODULUS.0[5], &mut carry); - r11 = ::ff::adc(r11, carry2, &mut carry); - (self.0).0[0] = r6; - (self.0).0[1] = r7; - (self.0).0[2] = r8; - (self.0).0[3] = r9; - (self.0).0[4] = r10; - (self.0).0[5] = r11; - self.reduce(); - } -} - -impl SqrtField for Fq { - fn legendre(&self) -> ::ff::LegendreSymbol { - // s = self^((q - 1) // 2) - let s = self.pow([ - 0xdcff7fffffffd555, - 0xf55ffff58a9ffff, - 0xb39869507b587b12, - 0xb23ba5c279c2895f, - 0x258dd3db21a5d66b, - 0xd0088f51cbff34d, - ]); - if s == Fq::zero() { - ::ff::LegendreSymbol::Zero - } else if s == Fq::one() { - ::ff::LegendreSymbol::QuadraticResidue - } else { - ::ff::LegendreSymbol::QuadraticNonResidue - } - } - - fn sqrt(&self) -> Option { - // Shank's algorithm for q mod 4 = 3 - // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2) - - // a1 = self^((q - 3) // 4) - let mut a1 = self.pow([ - 0xee7fbfffffffeaaa, - 0x7aaffffac54ffff, - 0xd9cc34a83dac3d89, - 0xd91dd2e13ce144af, - 0x92c6e9ed90d2eb35, - 0x680447a8e5ff9a6, - ]); - let mut a0 = a1; - a0.square(); - a0.mul_assign(self); - - if a0 == NEGATIVE_ONE { - None - } else { - a1.mul_assign(self); - Some(a1) - } - } -} - #[test] fn test_b_coeff() { assert_eq!(Fq::from_repr(FqRepr::from(4)).unwrap(), B_COEFF); @@ -1897,6 +1177,8 @@ use rand::{Rand, SeedableRng, XorShiftRng}; #[test] fn test_fq_repr_ordering() { + use std::cmp::Ordering; + fn assert_equality(a: FqRepr, b: FqRepr) { assert_eq!(a, b); assert!(a.cmp(&b) == Ordering::Equal); @@ -2743,6 +2025,8 @@ fn test_fq_pow() { #[test] fn test_fq_sqrt() { + use ff::SqrtField; + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); assert_eq!(Fq::zero().sqrt().unwrap(), Fq::zero()); @@ -2876,6 +2160,8 @@ fn test_fq_num_bits() { #[test] fn test_fq_root_of_unity() { + use ff::SqrtField; + assert_eq!(Fq::S, 1); assert_eq!( Fq::multiplicative_generator(), @@ -2923,6 +2209,7 @@ fn fq_repr_tests() { #[test] fn test_fq_legendre() { use ff::LegendreSymbol::*; + use ff::SqrtField; assert_eq!(QuadraticResidue, Fq::one().legendre()); assert_eq!(Zero, Fq::zero().legendre()); diff --git a/src/bls12_381/fr.rs b/src/bls12_381/fr.rs index e9eee24..6e142f0 100644 --- a/src/bls12_381/fr.rs +++ b/src/bls12_381/fr.rs @@ -1,646 +1,10 @@ -use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField}; +use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; -// r = 52435875175126190479447740508185965837690552500527637822603658699938581184513 -const MODULUS: FrRepr = FrRepr([ - 0xffffffff00000001, - 0x53bda402fffe5bfe, - 0x3339d80809a1d805, - 0x73eda753299d7d48, -]); - -// The number of bits needed to represent the modulus. -const MODULUS_BITS: u32 = 255; - -// The number of bits that must be shaved from the beginning of -// the representation when randomly sampling. -const REPR_SHAVE_BITS: u32 = 1; - -// R = 2**256 % r -const R: FrRepr = FrRepr([ - 0x1fffffffe, - 0x5884b7fa00034802, - 0x998c4fefecbc4ff5, - 0x1824b159acc5056f, -]); - -// R2 = R^2 % r -const R2: FrRepr = FrRepr([ - 0xc999e990f3f29c6d, - 0x2b6cedcb87925c23, - 0x5d314967254398f, - 0x748d9d99f59ff11, -]); - -// INV = -(r^{-1} mod 2^64) mod 2^64 -const INV: u64 = 0xfffffffeffffffff; - -// GENERATOR = 7 (multiplicative generator of r-1 order, that is also quadratic nonresidue) -const GENERATOR: FrRepr = FrRepr([ - 0xefffffff1, - 0x17e363d300189c0f, - 0xff9c57876f8457b0, - 0x351332208fc5a8c4, -]); - -// 2^s * t = MODULUS - 1 with t odd -const S: u32 = 32; - -// 2^s root of unity computed by GENERATOR^t -const ROOT_OF_UNITY: FrRepr = FrRepr([ - 0xb9b58d8c5f0e466a, - 0x5b1b4c801819d7ec, - 0xaf53ae352a31e64, - 0x5bf3adda19e9b27b, -]); - -#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] -pub struct FrRepr(pub [u64; 4]); - -impl ::rand::Rand for FrRepr { - #[inline(always)] - fn rand(rng: &mut R) -> Self { - FrRepr(rng.gen()) - } -} - -impl ::std::fmt::Display for FrRepr { - 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 FrRepr { - #[inline(always)] - fn as_ref(&self) -> &[u64] { - &self.0 - } -} - -impl AsMut<[u64]> for FrRepr { - #[inline(always)] - fn as_mut(&mut self) -> &mut [u64] { - &mut self.0 - } -} - -impl From for FrRepr { - #[inline(always)] - fn from(val: u64) -> FrRepr { - let mut repr = Self::default(); - repr.0[0] = val; - repr - } -} - -impl Ord for FrRepr { - #[inline(always)] - fn cmp(&self, other: &FrRepr) -> ::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 FrRepr { - #[inline(always)] - fn partial_cmp(&self, other: &FrRepr) -> Option<::std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl PrimeFieldRepr for FrRepr { - #[inline(always)] - fn is_odd(&self) -> bool { - self.0[0] & 1 == 1 - } - - #[inline(always)] - fn is_even(&self) -> bool { - !self.is_odd() - } - - #[inline(always)] - fn is_zero(&self) -> bool { - self.0.iter().all(|&e| e == 0) - } - - #[inline(always)] - fn shr(&mut self, mut n: u32) { - if n >= 64 * 4 { - *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 div2(&mut self) { - let mut t = 0; - for i in self.0.iter_mut().rev() { - let t2 = *i << 63; - *i >>= 1; - *i |= t; - t = t2; - } - } - - #[inline(always)] - fn mul2(&mut self) { - let mut last = 0; - for i in &mut self.0 { - let tmp = *i >> 63; - *i <<= 1; - *i |= last; - last = tmp; - } - } - - #[inline(always)] - fn shl(&mut self, mut n: u32) { - if n >= 64 * 4 { - *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 = (4 as u32) * 64; - for i in self.0.iter().rev() { - let leading = i.leading_zeros(); - ret -= leading; - if leading != 64 { - break; - } - } - - ret - } - - #[inline(always)] - fn add_nocarry(&mut self, other: &FrRepr) { - let mut carry = 0; - - for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::ff::adc(*a, *b, &mut carry); - } - } - - #[inline(always)] - fn sub_noborrow(&mut self, other: &FrRepr) { - let mut borrow = 0; - - for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::ff::sbb(*a, *b, &mut borrow); - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(PrimeField)] +#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"] +#[PrimeFieldGenerator = "7"] pub struct Fr(FrRepr); -impl ::std::fmt::Display for Fr { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "Fr({})", self.into_repr()) - } -} - -impl ::rand::Rand for Fr { - fn rand(rng: &mut R) -> Self { - loop { - let mut tmp = Fr(FrRepr::rand(rng)); - - // Mask away the unused bits at the beginning. - tmp.0.as_mut()[3] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; - - if tmp.is_valid() { - return tmp; - } - } - } -} - -impl From for FrRepr { - fn from(e: Fr) -> FrRepr { - e.into_repr() - } -} - -impl PrimeField for Fr { - type Repr = FrRepr; - - fn from_repr(r: FrRepr) -> Result { - let mut r = Fr(r); - if r.is_valid() { - r.mul_assign(&Fr(R2)); - - Ok(r) - } else { - Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0))) - } - } - - fn into_repr(&self) -> FrRepr { - let mut r = *self; - r.mont_reduce( - (self.0).0[0], - (self.0).0[1], - (self.0).0[2], - (self.0).0[3], - 0, - 0, - 0, - 0, - ); - r.0 - } - - fn char() -> FrRepr { - MODULUS - } - - const NUM_BITS: u32 = MODULUS_BITS; - - const CAPACITY: u32 = Self::NUM_BITS - 1; - - fn multiplicative_generator() -> Self { - Fr(GENERATOR) - } - - const S: u32 = S; - - fn root_of_unity() -> Self { - Fr(ROOT_OF_UNITY) - } -} - -impl Field for Fr { - #[inline] - fn zero() -> Self { - Fr(FrRepr::from(0)) - } - - #[inline] - fn one() -> Self { - Fr(R) - } - - #[inline] - fn is_zero(&self) -> bool { - self.0.is_zero() - } - - #[inline] - fn add_assign(&mut self, other: &Fr) { - // This cannot exceed the backing capacity. - self.0.add_nocarry(&other.0); - - // However, it may need to be reduced. - self.reduce(); - } - - #[inline] - fn double(&mut self) { - // This cannot exceed the backing capacity. - self.0.mul2(); - - // However, it may need to be reduced. - self.reduce(); - } - - #[inline] - fn sub_assign(&mut self, other: &Fr) { - // 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); - } - - #[inline] - fn negate(&mut self) { - if !self.is_zero() { - let mut tmp = MODULUS; - tmp.sub_noborrow(&self.0); - self.0 = tmp; - } - } - - fn inverse(&self) -> Option { - if self.is_zero() { - None - } else { - // Guajardo Kumar Paar Pelzl - // Efficient Software-Implementation of Finite Fields with Applications to Cryptography - // Algorithm 16 (BEA for Inversion in Fp) - - let one = FrRepr::from(1); - - let mut u = self.0; - let mut v = MODULUS; - let mut b = Fr(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 { - Some(b) - } else { - Some(c) - } - } - } - - #[inline(always)] - fn frobenius_map(&mut self, _: usize) { - // This has no effect in a prime field. - } - - #[inline] - fn mul_assign(&mut self, other: &Fr) { - let mut carry = 0; - let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); - let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); - let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); - let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); - let r4 = carry; - let mut carry = 0; - let r1 = ::ff::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); - let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); - let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); - let r5 = carry; - let mut carry = 0; - let r2 = ::ff::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); - let r3 = ::ff::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); - let r6 = carry; - let mut carry = 0; - let r3 = ::ff::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry); - let r7 = carry; - self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7); - } - - #[inline] - fn square(&mut self) { - let mut carry = 0; - let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); - let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); - let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry); - let r4 = carry; - let mut carry = 0; - let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry); - let r5 = carry; - let mut carry = 0; - let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry); - let r6 = carry; - - let r7 = r6 >> 63; - let r6 = (r6 << 1) | (r5 >> 63); - let r5 = (r5 << 1) | (r4 >> 63); - let r4 = (r4 << 1) | (r3 >> 63); - let r3 = (r3 << 1) | (r2 >> 63); - let r2 = (r2 << 1) | (r1 >> 63); - let r1 = r1 << 1; - - let mut carry = 0; - let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry); - let r1 = ::ff::adc(r1, 0, &mut carry); - let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry); - let r3 = ::ff::adc(r3, 0, &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry); - let r5 = ::ff::adc(r5, 0, &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry); - let r7 = ::ff::adc(r7, 0, &mut carry); - self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7); - } -} - -impl Fr { - /// 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 internally. - #[inline(always)] - fn reduce(&mut self) { - if !self.is_valid() { - self.0.sub_noborrow(&MODULUS); - } - } - - #[inline(always)] - fn mont_reduce( - &mut self, - r0: u64, - mut r1: u64, - mut r2: u64, - mut r3: u64, - mut r4: u64, - mut r5: u64, - mut r6: u64, - mut r7: u64, - ) { - // The Montgomery reduction here is based on Algorithm 14.32 in - // Handbook of Applied Cryptography - // . - - let k = r0.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r0, k, MODULUS.0[0], &mut carry); - r1 = ::ff::mac_with_carry(r1, k, MODULUS.0[1], &mut carry); - r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[2], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[3], &mut carry); - r4 = ::ff::adc(r4, 0, &mut carry); - let carry2 = carry; - let k = r1.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r1, k, MODULUS.0[0], &mut carry); - r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[1], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[2], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[3], &mut carry); - r5 = ::ff::adc(r5, carry2, &mut carry); - let carry2 = carry; - let k = r2.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r2, k, MODULUS.0[0], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[1], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[2], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[3], &mut carry); - r6 = ::ff::adc(r6, carry2, &mut carry); - let carry2 = carry; - let k = r3.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r3, k, MODULUS.0[0], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[1], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[2], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[3], &mut carry); - r7 = ::ff::adc(r7, carry2, &mut carry); - (self.0).0[0] = r4; - (self.0).0[1] = r5; - (self.0).0[2] = r6; - (self.0).0[3] = r7; - self.reduce(); - } -} - -impl SqrtField for Fr { - fn legendre(&self) -> ::ff::LegendreSymbol { - // s = self^((r - 1) // 2) - let s = self.pow([ - 0x7fffffff80000000, - 0xa9ded2017fff2dff, - 0x199cec0404d0ec02, - 0x39f6d3a994cebea4, - ]); - if s == Self::zero() { - ::ff::LegendreSymbol::Zero - } else if s == Self::one() { - ::ff::LegendreSymbol::QuadraticResidue - } else { - ::ff::LegendreSymbol::QuadraticNonResidue - } - } - - fn sqrt(&self) -> Option { - // Tonelli-Shank's algorithm for q mod 16 = 1 - // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) - match self.legendre() { - ::ff::LegendreSymbol::Zero => Some(*self), - ::ff::LegendreSymbol::QuadraticNonResidue => None, - ::ff::LegendreSymbol::QuadraticResidue => { - let mut c = Fr(ROOT_OF_UNITY); - // r = self^((t + 1) // 2) - let mut r = self.pow([ - 0x7fff2dff80000000, - 0x4d0ec02a9ded201, - 0x94cebea4199cec04, - 0x39f6d3a9, - ]); - // t = self^t - let mut t = self.pow([ - 0xfffe5bfeffffffff, - 0x9a1d80553bda402, - 0x299d7d483339d808, - 0x73eda753, - ]); - 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) - } - } - } -} - #[cfg(test)] use rand::{Rand, SeedableRng, XorShiftRng}; @@ -909,6 +273,7 @@ fn test_fr_repr_sub_noborrow() { #[test] fn test_fr_legendre() { use ff::LegendreSymbol::*; + use ff::SqrtField; assert_eq!(QuadraticResidue, Fr::one().legendre()); assert_eq!(Zero, Fr::zero().legendre()); @@ -1418,6 +783,8 @@ fn test_fr_pow() { #[test] fn test_fr_sqrt() { + use ff::SqrtField; + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); assert_eq!(Fr::zero().sqrt().unwrap(), Fr::zero()); @@ -1583,6 +950,8 @@ fn test_fr_num_bits() { #[test] fn test_fr_root_of_unity() { + use ff::SqrtField; + assert_eq!(Fr::S, 32); assert_eq!( Fr::multiplicative_generator(), diff --git a/src/lib.rs b/src/lib.rs index 0c336ed..fefdae3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ #![deny(missing_debug_implementations)] extern crate byteorder; +#[macro_use] extern crate ff; extern crate rand; From defdf8df52dbd75fc74286a6599e019cbe5fb162 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 15:49:47 +0100 Subject: [PATCH 32/60] Connect ff u128-support to pairing u128-support --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index dcf7c32..c11d2a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,5 +20,5 @@ ff = "0.3" [features] unstable-features = ["expose-arith"] expose-arith = [] -u128-support = [] +u128-support = ["ff/u128-support"] default = [] From bb22a167afed01195824c290be668b1450ce04e2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 15:51:32 +0100 Subject: [PATCH 33/60] Update authors --- Cargo.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c11d2a9..9fe707f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,10 @@ name = "pairing" # Remember to change version string in README.md. version = "0.14.2" -authors = ["Sean Bowe "] +authors = [ + "Sean Bowe ", + "Jack Grigg ", +] license = "MIT/Apache-2.0" description = "Pairing-friendly elliptic curve library" From c49590bab72161706343e584d839a55e8913f799 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 16:04:52 +0100 Subject: [PATCH 34/60] Change all remaining uses of *Field to reference ff crate --- src/bls12_381/fq.rs | 2 +- src/bls12_381/fq12.rs | 4 ++-- src/bls12_381/fq2.rs | 22 +++++++++++----------- src/bls12_381/fq6.rs | 4 ++-- src/tests/curve.rs | 5 +++-- src/tests/repr.rs | 2 +- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/bls12_381/fq.rs b/src/bls12_381/fq.rs index 2b4b7a6..2661aa5 100644 --- a/src/bls12_381/fq.rs +++ b/src/bls12_381/fq.rs @@ -1,5 +1,5 @@ use super::fq2::Fq2; -use {Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; +use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; // B coefficient of BLS12-381 curve, 4. pub const B_COEFF: Fq = Fq(FqRepr([ diff --git a/src/bls12_381/fq12.rs b/src/bls12_381/fq12.rs index 2bec0b1..b24fcaa 100644 --- a/src/bls12_381/fq12.rs +++ b/src/bls12_381/fq12.rs @@ -1,8 +1,8 @@ use super::fq::FROBENIUS_COEFF_FQ12_C1; use super::fq2::Fq2; use super::fq6::Fq6; +use ff::Field; use rand::{Rand, Rng}; -use Field; /// An element of Fq12, represented by c0 + c1 * w. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -182,7 +182,7 @@ fn test_fq12_mul_by_014() { #[test] fn fq12_field_tests() { - use PrimeField; + use ff::PrimeField; ::tests::field::random_field_tests::(); ::tests::field::random_frobenius_tests::(super::fq::Fq::char(), 13); diff --git a/src/bls12_381/fq2.rs b/src/bls12_381/fq2.rs index 1f3cd6f..7ae159f 100644 --- a/src/bls12_381/fq2.rs +++ b/src/bls12_381/fq2.rs @@ -1,6 +1,6 @@ use super::fq::{FROBENIUS_COEFF_FQ2_C1, Fq, NEGATIVE_ONE}; +use ff::{Field, SqrtField}; use rand::{Rand, Rng}; -use {Field, SqrtField}; use std::cmp::Ordering; @@ -272,7 +272,7 @@ fn test_fq2_basics() { #[test] fn test_fq2_squaring() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::one(), @@ -346,7 +346,7 @@ fn test_fq2_squaring() { #[test] fn test_fq2_mul() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -410,7 +410,7 @@ fn test_fq2_mul() { #[test] fn test_fq2_inverse() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; assert!(Fq2::zero().inverse().is_none()); @@ -459,7 +459,7 @@ fn test_fq2_inverse() { #[test] fn test_fq2_addition() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -523,7 +523,7 @@ fn test_fq2_addition() { #[test] fn test_fq2_subtraction() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -587,7 +587,7 @@ fn test_fq2_subtraction() { #[test] fn test_fq2_negation() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -634,7 +634,7 @@ fn test_fq2_negation() { #[test] fn test_fq2_doubling() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -681,7 +681,7 @@ fn test_fq2_doubling() { #[test] fn test_fq2_frobenius_map() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -794,7 +794,7 @@ fn test_fq2_frobenius_map() { #[test] fn test_fq2_sqrt() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; assert_eq!( Fq2 { @@ -900,7 +900,7 @@ fn test_fq2_mul_nonresidue() { #[test] fn fq2_field_tests() { - use PrimeField; + use ff::PrimeField; ::tests::field::random_field_tests::(); ::tests::field::random_sqrt_tests::(); diff --git a/src/bls12_381/fq6.rs b/src/bls12_381/fq6.rs index c065f27..36c6e28 100644 --- a/src/bls12_381/fq6.rs +++ b/src/bls12_381/fq6.rs @@ -1,7 +1,7 @@ use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2}; use super::fq2::Fq2; +use ff::Field; use rand::{Rand, Rng}; -use Field; /// An element of Fq6, represented by c0 + c1 * v + c2 * v^(2). #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -367,7 +367,7 @@ fn test_fq6_mul_by_01() { #[test] fn fq6_field_tests() { - use PrimeField; + use ff::PrimeField; ::tests::field::random_field_tests::(); ::tests::field::random_frobenius_tests::(super::fq::Fq::char(), 13); diff --git a/src/tests/curve.rs b/src/tests/curve.rs index 1480b74..bb0406c 100644 --- a/src/tests/curve.rs +++ b/src/tests/curve.rs @@ -1,6 +1,7 @@ +use ff::Field; use rand::{Rand, Rng, SeedableRng, XorShiftRng}; -use {CurveAffine, CurveProjective, EncodedPoint, Field}; +use {CurveAffine, CurveProjective, EncodedPoint}; pub fn curve_tests() { let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); @@ -66,8 +67,8 @@ pub fn curve_tests() { } fn random_wnaf_tests() { + use ff::PrimeField; use wnaf::*; - use PrimeField; let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); diff --git a/src/tests/repr.rs b/src/tests/repr.rs index 681a476..09dd441 100644 --- a/src/tests/repr.rs +++ b/src/tests/repr.rs @@ -1,5 +1,5 @@ +use ff::PrimeFieldRepr; use rand::{SeedableRng, XorShiftRng}; -use PrimeFieldRepr; pub fn random_repr_tests() { random_encoding_tests::(); From 06a152734c3bc0b36df18d2a3d531b507199ab72 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 18:41:55 +0100 Subject: [PATCH 35/60] Add missing SqrtField import to benches --- benches/bls12_381/fr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benches/bls12_381/fr.rs b/benches/bls12_381/fr.rs index 9cab671..13b0d0e 100644 --- a/benches/bls12_381/fr.rs +++ b/benches/bls12_381/fr.rs @@ -1,6 +1,6 @@ use rand::{Rand, SeedableRng, XorShiftRng}; -use ff::{Field, PrimeField, PrimeFieldRepr}; +use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; use pairing::bls12_381::*; #[bench] From 002173e187ff5ce94a2a5e722300509fcf0ba363 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 20:58:41 +0100 Subject: [PATCH 36/60] Update README.md Closes #4. --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4bd82ad..d08329e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ ## Disclaimers * This library does not provide constant-time guarantees. -* This library relies on Rust's `i128_type` feature, which is currently only available in the nightly compiler. ## Usage @@ -13,10 +12,10 @@ Add the `ff` crate to your `Cargo.toml`: ```toml [dependencies] -ff = "0.2" +ff = "0.3" ``` -The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` traits. See the **[documentation](https://docs.rs/ff/0.2.0/ff/)** for more. +The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` traits. See the **[documentation](https://docs.rs/ff/0.3.0/ff/)** for more. ### #![derive(PrimeField)] From 69ce66ae6cf43755e7fd5eea75f6945d0fa6ac2b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 21:08:24 +0100 Subject: [PATCH 37/60] Place ff_derive re-exports behind a feature Part of #3. --- Cargo.toml | 2 +- README.md | 9 +++++++++ src/lib.rs | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d2af3de..5f34fa0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,6 @@ rand = "0.4" ff_derive = { version = "0.3.0", path = "ff_derive", optional = true } [features] -default = ["derive"] +default = [] u128-support = [] derive = ["ff_derive"] diff --git a/README.md b/README.md index d08329e..ae676c1 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,15 @@ The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` If you need an implementation of a prime field, this library also provides a procedural macro that will expand into an efficient implementation of a prime field when supplied with the modulus. `PrimeFieldGenerator` must be an element of Fp of p-1 order, that is also quadratic nonresidue. +First, enable the `derive` crate feature: + +```toml +[dependencies] +ff = { version = "0.3", features = ["derive"] } +``` + +And then use the macro like so: + ```rust extern crate rand; #[macro_use] diff --git a/src/lib.rs b/src/lib.rs index 541fe76..d79bc14 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,9 +3,11 @@ extern crate byteorder; extern crate rand; +#[cfg(feature = "derive")] #[macro_use] extern crate ff_derive; +#[cfg(feature = "derive")] pub use ff_derive::*; use std::error::Error; From 0eb9f5040b8d24703392ba23798347a1163ce802 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 21:19:20 +0100 Subject: [PATCH 38/60] Remove u128-support feature and arithmetic Closes #2. --- Cargo.toml | 1 - src/lib.rs | 80 ------------------------------------------------------ 2 files changed, 81 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5f34fa0..0cdd633 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,5 +15,4 @@ ff_derive = { version = "0.3.0", path = "ff_derive", optional = true } [features] default = [] -u128-support = [] derive = ["ff_derive"] diff --git a/src/lib.rs b/src/lib.rs index d79bc14..b662dc4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -349,7 +349,6 @@ fn test_bit_iterator() { pub use self::arith_impl::*; -#[cfg(feature = "u128-support")] mod arith_impl { /// Calculate a - b - borrow, returning the result and modifying /// the borrow value. @@ -384,82 +383,3 @@ mod arith_impl { tmp as u64 } } - -#[cfg(not(feature = "u128-support"))] -mod arith_impl { - #[inline(always)] - fn split_u64(i: u64) -> (u64, u64) { - (i >> 32, i & 0xFFFFFFFF) - } - - #[inline(always)] - fn combine_u64(hi: u64, lo: u64) -> u64 { - (hi << 32) | lo - } - - /// 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 2067360930fbf07b74109fe776c4260766046816 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 21:31:35 +0100 Subject: [PATCH 39/60] Add ScalarEngine trait This is extracted from pairing's Engine trait. --- src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index b662dc4..a9d117f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -290,6 +290,14 @@ pub trait PrimeField: Field { fn root_of_unity() -> Self; } +/// An "engine" is a collection of types (fields, elliptic curve groups, etc.) +/// with well-defined relationships. Specific relationships (for example, a +/// pairing-friendly curve) can be defined in a subtrait. +pub trait ScalarEngine: Sized + 'static + Clone { + /// This is the scalar field of the engine's groups. + type Fr: PrimeField + SqrtField; +} + #[derive(Debug)] pub struct BitIterator { t: E, From 526676ecfce49661fe18d0e1635fde331b8e150d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 23:07:41 +0100 Subject: [PATCH 40/60] Bump version to 0.4.0 --- Cargo.toml | 2 +- README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0cdd633..22db67a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ff" -version = "0.3.0" +version = "0.4.0" authors = ["Sean Bowe "] description = "Library for building and interfacing with finite fields" documentation = "https://docs.rs/ff/" diff --git a/README.md b/README.md index ae676c1..3efef94 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,10 @@ Add the `ff` crate to your `Cargo.toml`: ```toml [dependencies] -ff = "0.3" +ff = "0.4" ``` -The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` traits. See the **[documentation](https://docs.rs/ff/0.3.0/ff/)** for more. +The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` traits. See the **[documentation](https://docs.rs/ff/0.4.0/ff/)** for more. ### #![derive(PrimeField)] @@ -25,7 +25,7 @@ First, enable the `derive` crate feature: ```toml [dependencies] -ff = { version = "0.3", features = ["derive"] } +ff = { version = "0.4", features = ["derive"] } ``` And then use the macro like so: From 94cacc6152c1ad0d24fc16e0dd6819caf6eef360 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 20:03:57 +0100 Subject: [PATCH 41/60] Migrate curve traits and tests, and WNAF, from pairing --- Cargo.toml | 7 +- src/lib.rs | 196 ++++++++++++++++++++++ src/tests/mod.rs | 421 +++++++++++++++++++++++++++++++++++++++++++++++ src/wnaf.rs | 181 ++++++++++++++++++++ 4 files changed, 804 insertions(+), 1 deletion(-) create mode 100644 src/tests/mod.rs create mode 100644 src/wnaf.rs diff --git a/Cargo.toml b/Cargo.toml index 3bde5ae..3110964 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "group" version = "0.0.0" -authors = ["Sean Bowe "] +authors = [ + "Sean Bowe ", + "Jack Grigg ", +] license = "MIT/Apache-2.0" description = "Elliptic curve group traits and utilities" @@ -10,3 +13,5 @@ homepage = "https://github.com/ebfull/group" repository = "https://github.com/ebfull/group" [dependencies] +ff = "0.4" +rand = "0.4" diff --git a/src/lib.rs b/src/lib.rs index e69de29..fc924c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -0,0 +1,196 @@ +extern crate ff; +extern crate rand; + +use ff::{PrimeField, PrimeFieldDecodingError, ScalarEngine, SqrtField}; +use std::error::Error; +use std::fmt; + +pub mod tests; + +mod wnaf; +pub use self::wnaf::Wnaf; + +/// Projective representation of an elliptic curve point guaranteed to be +/// in the correct prime order subgroup. +pub trait CurveProjective: + PartialEq + + Eq + + Sized + + Copy + + Clone + + Send + + Sync + + fmt::Debug + + fmt::Display + + rand::Rand + + 'static +{ + type Engine: ScalarEngine; + type Scalar: PrimeField + SqrtField; + type Base: SqrtField; + type Affine: CurveAffine; + + /// Returns the additive identity. + fn zero() -> Self; + + /// Returns a fixed generator of unknown exponent. + fn one() -> Self; + + /// Determines if this point is the point at infinity. + fn is_zero(&self) -> bool; + + /// Normalizes a slice of projective elements so that + /// conversion to affine is cheap. + fn batch_normalization(v: &mut [Self]); + + /// Checks if the point is already "normalized" so that + /// cheap affine conversion is possible. + fn is_normalized(&self) -> bool; + + /// Doubles this element. + fn double(&mut self); + + /// Adds another element to this element. + fn add_assign(&mut self, other: &Self); + + /// Subtracts another element from this element. + fn sub_assign(&mut self, other: &Self) { + let mut tmp = *other; + tmp.negate(); + self.add_assign(&tmp); + } + + /// Adds an affine element to this element. + fn add_assign_mixed(&mut self, other: &Self::Affine); + + /// Negates this element. + fn negate(&mut self); + + /// Performs scalar multiplication of this element. + fn mul_assign::Repr>>(&mut self, other: S); + + /// Converts this element into its affine representation. + fn into_affine(&self) -> Self::Affine; + + /// Recommends a wNAF window table size given a scalar. Always returns a number + /// between 2 and 22, inclusive. + fn recommended_wnaf_for_scalar(scalar: ::Repr) -> usize; + + /// Recommends a wNAF window size given the number of scalars you intend to multiply + /// a base by. Always returns a number between 2 and 22, inclusive. + fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize; +} + +/// Affine representation of an elliptic curve point guaranteed to be +/// in the correct prime order subgroup. +pub trait CurveAffine: + Copy + Clone + Sized + Send + Sync + fmt::Debug + fmt::Display + PartialEq + Eq + 'static +{ + type Engine: ScalarEngine; + type Scalar: PrimeField + SqrtField; + type Base: SqrtField; + type Projective: CurveProjective; + type Uncompressed: EncodedPoint; + type Compressed: EncodedPoint; + + /// Returns the additive identity. + fn zero() -> Self; + + /// Returns a fixed generator of unknown exponent. + fn one() -> Self; + + /// Determines if this point represents the point at infinity; the + /// additive identity. + fn is_zero(&self) -> bool; + + /// Negates this element. + fn negate(&mut self); + + /// Performs scalar multiplication of this element with mixed addition. + fn mul::Repr>>(&self, other: S) -> Self::Projective; + + /// Converts this element into its affine representation. + fn into_projective(&self) -> Self::Projective; + + /// Converts this element into its compressed encoding, so long as it's not + /// the point at infinity. + fn into_compressed(&self) -> Self::Compressed { + ::from_affine(*self) + } + + /// Converts this element into its uncompressed encoding, so long as it's not + /// the point at infinity. + fn into_uncompressed(&self) -> Self::Uncompressed { + ::from_affine(*self) + } +} + +/// An encoded elliptic curve point, which should essentially wrap a `[u8; N]`. +pub trait EncodedPoint: + Sized + Send + Sync + AsRef<[u8]> + AsMut<[u8]> + Clone + Copy + 'static +{ + type Affine: CurveAffine; + + /// Creates an empty representation. + fn empty() -> Self; + + /// Returns the number of bytes consumed by this representation. + fn size() -> usize; + + /// Converts an `EncodedPoint` into a `CurveAffine` element, + /// if the encoding represents a valid element. + fn into_affine(&self) -> Result; + + /// Converts an `EncodedPoint` into a `CurveAffine` element, + /// without guaranteeing that the encoding represents a valid + /// element. This is useful when the caller knows the encoding is + /// valid already. + /// + /// If the encoding is invalid, this can break API invariants, + /// so caution is strongly encouraged. + fn into_affine_unchecked(&self) -> Result; + + /// Creates an `EncodedPoint` from an affine point, as long as the + /// point is not the point at infinity. + fn from_affine(affine: Self::Affine) -> Self; +} + +/// An error that may occur when trying to decode an `EncodedPoint`. +#[derive(Debug)] +pub enum GroupDecodingError { + /// The coordinate(s) do not lie on the curve. + NotOnCurve, + /// The element is not part of the r-order subgroup. + NotInSubgroup, + /// One of the coordinates could not be decoded + CoordinateDecodingError(&'static str, PrimeFieldDecodingError), + /// The compression mode of the encoded element was not as expected + UnexpectedCompressionMode, + /// The encoding contained bits that should not have been set + UnexpectedInformation, +} + +impl Error for GroupDecodingError { + fn description(&self) -> &str { + match *self { + GroupDecodingError::NotOnCurve => "coordinate(s) do not lie on the curve", + GroupDecodingError::NotInSubgroup => "the element is not part of an r-order subgroup", + GroupDecodingError::CoordinateDecodingError(..) => "coordinate(s) could not be decoded", + GroupDecodingError::UnexpectedCompressionMode => { + "encoding has unexpected compression mode" + } + GroupDecodingError::UnexpectedInformation => "encoding has unexpected information", + } + } +} + +impl fmt::Display for GroupDecodingError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + GroupDecodingError::CoordinateDecodingError(description, ref err) => { + write!(f, "{} decoding error: {}", description, err) + } + _ => write!(f, "{}", self.description()), + } + } +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs new file mode 100644 index 0000000..b4c47db --- /dev/null +++ b/src/tests/mod.rs @@ -0,0 +1,421 @@ +use rand::{Rand, Rng, SeedableRng, XorShiftRng}; + +use {CurveAffine, CurveProjective, EncodedPoint}; + +pub fn curve_tests() { + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + + // Negation edge case with zero. + { + let mut z = G::zero(); + z.negate(); + assert!(z.is_zero()); + } + + // Doubling edge case with zero. + { + let mut z = G::zero(); + z.double(); + assert!(z.is_zero()); + } + + // Addition edge cases with zero + { + let mut r = G::rand(&mut rng); + let rcopy = r; + r.add_assign(&G::zero()); + assert_eq!(r, rcopy); + r.add_assign_mixed(&G::Affine::zero()); + assert_eq!(r, rcopy); + + let mut z = G::zero(); + z.add_assign(&G::zero()); + assert!(z.is_zero()); + z.add_assign_mixed(&G::Affine::zero()); + assert!(z.is_zero()); + + let mut z2 = z; + z2.add_assign(&r); + + z.add_assign_mixed(&r.into_affine()); + + assert_eq!(z, z2); + assert_eq!(z, r); + } + + // Transformations + { + let a = G::rand(&mut rng); + let b = a.into_affine().into_projective(); + let c = a.into_affine() + .into_projective() + .into_affine() + .into_projective(); + assert_eq!(a, b); + assert_eq!(b, c); + } + + random_addition_tests::(); + random_multiplication_tests::(); + random_doubling_tests::(); + random_negation_tests::(); + random_transformation_tests::(); + random_wnaf_tests::(); + random_encoding_tests::(); +} + +fn random_wnaf_tests() { + use ff::PrimeField; + + use wnaf::*; + + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + + { + let mut table = vec![]; + let mut wnaf = vec![]; + + for w in 2..14 { + for _ in 0..100 { + let g = G::rand(&mut rng); + let s = G::Scalar::rand(&mut rng).into_repr(); + let mut g1 = g; + g1.mul_assign(s); + + wnaf_table(&mut table, g, w); + wnaf_form(&mut wnaf, s, w); + let g2 = wnaf_exp(&table, &wnaf); + + assert_eq!(g1, g2); + } + } + } + + { + fn only_compiles_if_send(_: &S) {} + + for _ in 0..100 { + let g = G::rand(&mut rng); + let s = G::Scalar::rand(&mut rng).into_repr(); + let mut g1 = g; + g1.mul_assign(s); + + let g2 = { + let mut wnaf = Wnaf::new(); + wnaf.base(g, 1).scalar(s) + }; + let g3 = { + let mut wnaf = Wnaf::new(); + wnaf.scalar(s).base(g) + }; + let g4 = { + let mut wnaf = Wnaf::new(); + let mut shared = wnaf.base(g, 1).shared(); + + only_compiles_if_send(&shared); + + shared.scalar(s) + }; + let g5 = { + let mut wnaf = Wnaf::new(); + let mut shared = wnaf.scalar(s).shared(); + + only_compiles_if_send(&shared); + + shared.base(g) + }; + + let g6 = { + let mut wnaf = Wnaf::new(); + { + // Populate the vectors. + wnaf.base(rng.gen(), 1).scalar(rng.gen()); + } + wnaf.base(g, 1).scalar(s) + }; + let g7 = { + let mut wnaf = Wnaf::new(); + { + // Populate the vectors. + wnaf.base(rng.gen(), 1).scalar(rng.gen()); + } + wnaf.scalar(s).base(g) + }; + let g8 = { + let mut wnaf = Wnaf::new(); + { + // Populate the vectors. + wnaf.base(rng.gen(), 1).scalar(rng.gen()); + } + let mut shared = wnaf.base(g, 1).shared(); + + only_compiles_if_send(&shared); + + shared.scalar(s) + }; + let g9 = { + let mut wnaf = Wnaf::new(); + { + // Populate the vectors. + wnaf.base(rng.gen(), 1).scalar(rng.gen()); + } + let mut shared = wnaf.scalar(s).shared(); + + only_compiles_if_send(&shared); + + shared.base(g) + }; + + assert_eq!(g1, g2); + assert_eq!(g1, g3); + assert_eq!(g1, g4); + assert_eq!(g1, g5); + assert_eq!(g1, g6); + assert_eq!(g1, g7); + assert_eq!(g1, g8); + assert_eq!(g1, g9); + } + } +} + +fn random_negation_tests() { + use ff::Field; + + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + + for _ in 0..1000 { + let r = G::rand(&mut rng); + + let s = G::Scalar::rand(&mut rng); + let mut sneg = s; + sneg.negate(); + + let mut t1 = r; + t1.mul_assign(s); + + let mut t2 = r; + t2.mul_assign(sneg); + + let mut t3 = t1; + t3.add_assign(&t2); + assert!(t3.is_zero()); + + let mut t4 = t1; + t4.add_assign_mixed(&t2.into_affine()); + assert!(t4.is_zero()); + + t1.negate(); + assert_eq!(t1, t2); + } +} + +fn random_doubling_tests() { + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + + for _ in 0..1000 { + let mut a = G::rand(&mut rng); + let mut b = G::rand(&mut rng); + + // 2(a + b) + let mut tmp1 = a; + tmp1.add_assign(&b); + tmp1.double(); + + // 2a + 2b + a.double(); + b.double(); + + let mut tmp2 = a; + tmp2.add_assign(&b); + + let mut tmp3 = a; + tmp3.add_assign_mixed(&b.into_affine()); + + assert_eq!(tmp1, tmp2); + assert_eq!(tmp1, tmp3); + } +} + +fn random_multiplication_tests() { + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + + for _ in 0..1000 { + let mut a = G::rand(&mut rng); + let mut b = G::rand(&mut rng); + let a_affine = a.into_affine(); + let b_affine = b.into_affine(); + + let s = G::Scalar::rand(&mut rng); + + // s ( a + b ) + let mut tmp1 = a; + tmp1.add_assign(&b); + tmp1.mul_assign(s); + + // sa + sb + a.mul_assign(s); + b.mul_assign(s); + + let mut tmp2 = a; + tmp2.add_assign(&b); + + // Affine multiplication + let mut tmp3 = a_affine.mul(s); + tmp3.add_assign(&b_affine.mul(s)); + + assert_eq!(tmp1, tmp2); + assert_eq!(tmp1, tmp3); + } +} + +fn random_addition_tests() { + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + + for _ in 0..1000 { + let a = G::rand(&mut rng); + let b = G::rand(&mut rng); + let c = G::rand(&mut rng); + let a_affine = a.into_affine(); + let b_affine = b.into_affine(); + let c_affine = c.into_affine(); + + // a + a should equal the doubling + { + let mut aplusa = a; + aplusa.add_assign(&a); + + let mut aplusamixed = a; + aplusamixed.add_assign_mixed(&a.into_affine()); + + let mut adouble = a; + adouble.double(); + + assert_eq!(aplusa, adouble); + assert_eq!(aplusa, aplusamixed); + } + + let mut tmp = vec![G::zero(); 6]; + + // (a + b) + c + tmp[0] = a; + tmp[0].add_assign(&b); + tmp[0].add_assign(&c); + + // a + (b + c) + tmp[1] = b; + tmp[1].add_assign(&c); + tmp[1].add_assign(&a); + + // (a + c) + b + tmp[2] = a; + tmp[2].add_assign(&c); + tmp[2].add_assign(&b); + + // Mixed addition + + // (a + b) + c + tmp[3] = a_affine.into_projective(); + tmp[3].add_assign_mixed(&b_affine); + tmp[3].add_assign_mixed(&c_affine); + + // a + (b + c) + tmp[4] = b_affine.into_projective(); + tmp[4].add_assign_mixed(&c_affine); + tmp[4].add_assign_mixed(&a_affine); + + // (a + c) + b + tmp[5] = a_affine.into_projective(); + tmp[5].add_assign_mixed(&c_affine); + tmp[5].add_assign_mixed(&b_affine); + + // Comparisons + for i in 0..6 { + for j in 0..6 { + assert_eq!(tmp[i], tmp[j]); + assert_eq!(tmp[i].into_affine(), tmp[j].into_affine()); + } + + assert!(tmp[i] != a); + assert!(tmp[i] != b); + assert!(tmp[i] != c); + + assert!(a != tmp[i]); + assert!(b != tmp[i]); + assert!(c != tmp[i]); + } + } +} + +fn random_transformation_tests() { + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + + for _ in 0..1000 { + let g = G::rand(&mut rng); + let g_affine = g.into_affine(); + let g_projective = g_affine.into_projective(); + assert_eq!(g, g_projective); + } + + // Batch normalization + for _ in 0..10 { + let mut v = (0..1000).map(|_| G::rand(&mut rng)).collect::>(); + + for i in &v { + assert!(!i.is_normalized()); + } + + use rand::distributions::{IndependentSample, Range}; + let between = Range::new(0, 1000); + // Sprinkle in some normalized points + for _ in 0..5 { + v[between.ind_sample(&mut rng)] = G::zero(); + } + for _ in 0..5 { + let s = between.ind_sample(&mut rng); + v[s] = v[s].into_affine().into_projective(); + } + + let expected_v = v.iter() + .map(|v| v.into_affine().into_projective()) + .collect::>(); + G::batch_normalization(&mut v); + + for i in &v { + assert!(i.is_normalized()); + } + + assert_eq!(v, expected_v); + } +} + +fn random_encoding_tests() { + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); + + assert_eq!( + G::zero().into_uncompressed().into_affine().unwrap(), + G::zero() + ); + + assert_eq!( + G::zero().into_compressed().into_affine().unwrap(), + G::zero() + ); + + for _ in 0..1000 { + let mut r = G::Projective::rand(&mut rng).into_affine(); + + let uncompressed = r.into_uncompressed(); + let de_uncompressed = uncompressed.into_affine().unwrap(); + assert_eq!(de_uncompressed, r); + + let compressed = r.into_compressed(); + let de_compressed = compressed.into_affine().unwrap(); + assert_eq!(de_compressed, r); + + r.negate(); + + let compressed = r.into_compressed(); + let de_compressed = compressed.into_affine().unwrap(); + assert_eq!(de_compressed, r); + } +} diff --git a/src/wnaf.rs b/src/wnaf.rs new file mode 100644 index 0000000..381cd10 --- /dev/null +++ b/src/wnaf.rs @@ -0,0 +1,181 @@ +use ff::{PrimeField, PrimeFieldRepr}; + +use super::CurveProjective; + +/// Replaces the contents of `table` with a w-NAF window table for the given window size. +pub(crate) fn wnaf_table(table: &mut Vec, mut base: G, window: usize) { + table.truncate(0); + table.reserve(1 << (window - 1)); + + let mut dbl = base; + dbl.double(); + + for _ in 0..(1 << (window - 1)) { + table.push(base); + base.add_assign(&dbl); + } +} + +/// Replaces the contents of `wnaf` with the w-NAF representation of a scalar. +pub(crate) fn wnaf_form(wnaf: &mut Vec, mut c: S, window: usize) { + wnaf.truncate(0); + + while !c.is_zero() { + let mut u; + if c.is_odd() { + u = (c.as_ref()[0] % (1 << (window + 1))) as i64; + + if u > (1 << window) { + u -= 1 << (window + 1); + } + + if u > 0 { + c.sub_noborrow(&S::from(u as u64)); + } else { + c.add_nocarry(&S::from((-u) as u64)); + } + } else { + u = 0; + } + + wnaf.push(u); + + c.div2(); + } +} + +/// Performs w-NAF exponentiation with the provided window table and w-NAF form scalar. +/// +/// This function must be provided a `table` and `wnaf` that were constructed with +/// the same window size; otherwise, it may panic or produce invalid results. +pub(crate) fn wnaf_exp(table: &[G], wnaf: &[i64]) -> G { + let mut result = G::zero(); + + let mut found_one = false; + + for n in wnaf.iter().rev() { + if found_one { + result.double(); + } + + if *n != 0 { + found_one = true; + + if *n > 0 { + result.add_assign(&table[(n / 2) as usize]); + } else { + result.sub_assign(&table[((-n) / 2) as usize]); + } + } + } + + result +} + +/// A "w-ary non-adjacent form" exponentiation context. +#[derive(Debug)] +pub struct Wnaf { + base: B, + scalar: S, + window_size: W, +} + +impl Wnaf<(), Vec, Vec> { + /// Construct a new wNAF context without allocating. + pub fn new() -> Self { + Wnaf { + base: vec![], + scalar: vec![], + window_size: (), + } + } + + /// Given a base and a number of scalars, compute a window table and return a `Wnaf` object that + /// can perform exponentiations with `.scalar(..)`. + pub fn base(&mut self, base: G, num_scalars: usize) -> Wnaf> { + // Compute the appropriate window size based on the number of scalars. + let window_size = G::recommended_wnaf_for_num_scalars(num_scalars); + + // Compute a wNAF table for the provided base and window size. + wnaf_table(&mut self.base, base, window_size); + + // Return a Wnaf object that immutably borrows the computed base storage location, + // but mutably borrows the scalar storage location. + Wnaf { + base: &self.base[..], + scalar: &mut self.scalar, + window_size, + } + } + + /// Given a scalar, compute its wNAF representation and return a `Wnaf` object that can perform + /// exponentiations with `.base(..)`. + pub fn scalar( + &mut self, + scalar: <::Scalar as PrimeField>::Repr, + ) -> Wnaf, &[i64]> { + // Compute the appropriate window size for the scalar. + let window_size = G::recommended_wnaf_for_scalar(scalar); + + // Compute the wNAF form of the scalar. + wnaf_form(&mut self.scalar, scalar, window_size); + + // Return a Wnaf object that mutably borrows the base storage location, but + // immutably borrows the computed wNAF form scalar location. + Wnaf { + base: &mut self.base, + scalar: &self.scalar[..], + window_size, + } + } +} + +impl<'a, G: CurveProjective> Wnaf> { + /// Constructs new space for the scalar representation while borrowing + /// the computed window table, for sending the window table across threads. + pub fn shared(&self) -> Wnaf> { + Wnaf { + base: self.base, + scalar: vec![], + window_size: self.window_size, + } + } +} + +impl<'a, G: CurveProjective> Wnaf, &'a [i64]> { + /// Constructs new space for the window table while borrowing + /// the computed scalar representation, for sending the scalar representation + /// across threads. + pub fn shared(&self) -> Wnaf, &'a [i64]> { + Wnaf { + base: vec![], + scalar: self.scalar, + window_size: self.window_size, + } + } +} + +impl> Wnaf { + /// Performs exponentiation given a base. + pub fn base(&mut self, base: G) -> G + where + B: AsMut>, + { + wnaf_table(self.base.as_mut(), base, self.window_size); + wnaf_exp(self.base.as_mut(), self.scalar.as_ref()) + } +} + +impl>> Wnaf { + /// Performs exponentiation given a scalar. + pub fn scalar( + &mut self, + scalar: <::Scalar as PrimeField>::Repr, + ) -> G + where + B: AsRef<[G]>, + { + wnaf_form(self.scalar.as_mut(), scalar, self.window_size); + wnaf_exp(self.base.as_ref(), self.scalar.as_mut()) + } +} From cc5b83510277632852af67d896a27e0cb40f342b Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Wed, 4 Jul 2018 12:45:08 -0600 Subject: [PATCH 42/60] Start using cargo-clippy for CI. --- src/lib.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fefdae3..c3640c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,15 +1,14 @@ // `clippy` is a code linting tool for improving code quality by catching -// common mistakes or strange code patterns. If the `clippy` feature is -// provided, it is enabled and all compiler warnings are prohibited. -#![cfg_attr(feature = "clippy", deny(warnings))] -#![cfg_attr(feature = "clippy", feature(plugin))] -#![cfg_attr(feature = "clippy", plugin(clippy))] -#![cfg_attr(feature = "clippy", allow(inline_always))] -#![cfg_attr(feature = "clippy", allow(too_many_arguments))] -#![cfg_attr(feature = "clippy", allow(unreadable_literal))] -#![cfg_attr(feature = "clippy", allow(many_single_char_names))] -#![cfg_attr(feature = "clippy", allow(new_without_default_derive))] -#![cfg_attr(feature = "clippy", allow(write_literal))] +// common mistakes or strange code patterns. If the `cargo-clippy` feature +// is provided, all compiler warnings are prohibited. +#![cfg_attr(feature = "cargo-clippy", deny(warnings))] +#![cfg_attr(feature = "cargo-clippy", allow(inline_always))] +#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] +#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))] +#![cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))] +#![cfg_attr(feature = "cargo-clippy", allow(new_without_default_derive))] +#![cfg_attr(feature = "cargo-clippy", allow(write_literal))] + // Force public structures to implement Debug #![deny(missing_debug_implementations)] From 4752a9178154227da20cf230af0159394d80016f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 19:27:11 +0100 Subject: [PATCH 43/60] Remove clippy from dependencies. --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 9fe707f..f170c84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ repository = "https://github.com/ebfull/pairing" [dependencies] rand = "0.4" byteorder = "1" -clippy = { version = "0.0.200", optional = true } ff = "0.3" [features] From c5b883f91ee02db6bef9e225916905f520abdf6c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 3 Jul 2018 09:05:12 +0100 Subject: [PATCH 44/60] Migrate to ff 0.4 --- Cargo.toml | 3 +-- README.md | 8 -------- src/bls12_381/mod.rs | 7 +++++-- src/lib.rs | 7 ++----- 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f170c84..5f16018 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,10 +17,9 @@ repository = "https://github.com/ebfull/pairing" [dependencies] rand = "0.4" byteorder = "1" -ff = "0.3" +ff = { version = "0.4", features = ["derive"] } [features] unstable-features = ["expose-arith"] expose-arith = [] -u128-support = ["ff/u128-support"] default = [] diff --git a/README.md b/README.md index d71d0c5..bf386de 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,6 @@ This is a Rust crate for using pairing-friendly elliptic curves. Currently, only Bring the `pairing` crate into your project just as you normally would. -If you're using a supported platform and the nightly Rust compiler, you can enable the `u128-support` feature for faster arithmetic. - -```toml -[dependencies.pairing] -version = "0.14" -features = ["u128-support"] -``` - ## Security Warnings This library does not make any guarantees about constant-time operations, memory access patterns, or resistance to side-channel attacks. diff --git a/src/bls12_381/mod.rs b/src/bls12_381/mod.rs index c6c13c5..106591e 100644 --- a/src/bls12_381/mod.rs +++ b/src/bls12_381/mod.rs @@ -20,7 +20,7 @@ pub use self::fr::{Fr, FrRepr}; use super::{CurveAffine, Engine}; -use ff::{BitIterator, Field}; +use ff::{BitIterator, Field, ScalarEngine}; // The BLS parameter x for BLS12-381 is -0xd201000000010000 const BLS_X: u64 = 0xd201000000010000; @@ -29,8 +29,11 @@ const BLS_X_IS_NEGATIVE: bool = true; #[derive(Clone, Debug)] pub struct Bls12; -impl Engine for Bls12 { +impl ScalarEngine for Bls12 { type Fr = Fr; +} + +impl Engine for Bls12 { type G1 = G1; type G1Affine = G1Affine; type G2 = G2; diff --git a/src/lib.rs b/src/lib.rs index c3640c4..75af6e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,17 +25,14 @@ pub mod bls12_381; mod wnaf; pub use self::wnaf::Wnaf; -use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField}; +use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, SqrtField}; use std::error::Error; use std::fmt; /// An "engine" is a collection of types (fields, elliptic curve groups, etc.) /// with well-defined relationships. In particular, the G1/G2 curve groups are /// of prime order `r`, and are equipped with a bilinear pairing function. -pub trait Engine: Sized + 'static + Clone { - /// This is the scalar field of the G1/G2 groups. - type Fr: PrimeField + SqrtField; - +pub trait Engine: ScalarEngine { /// The projective representation of an element in G1. type G1: CurveProjective< Engine = Self, From fa8103764a07bd273927447d434de18aace252d3 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 3 Jul 2018 09:08:48 +0100 Subject: [PATCH 45/60] cargo fmt --- src/bls12_381/fq.rs | 18 ++++++++++-------- src/bls12_381/fq2.rs | 10 ++++++---- src/bls12_381/fr.rs | 14 ++++++++------ src/lib.rs | 1 - 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/bls12_381/fq.rs b/src/bls12_381/fq.rs index 2661aa5..fd0d416 100644 --- a/src/bls12_381/fq.rs +++ b/src/bls12_381/fq.rs @@ -1584,14 +1584,16 @@ fn test_fq_is_valid() { 0x17c8be1800b9f059 ])).is_valid() ); - assert!(!Fq(FqRepr([ - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff - ])).is_valid()); + assert!( + !Fq(FqRepr([ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff + ])).is_valid() + ); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); diff --git a/src/bls12_381/fq2.rs b/src/bls12_381/fq2.rs index 7ae159f..363439a 100644 --- a/src/bls12_381/fq2.rs +++ b/src/bls12_381/fq2.rs @@ -263,10 +263,12 @@ fn test_fq2_basics() { ); assert!(Fq2::zero().is_zero()); assert!(!Fq2::one().is_zero()); - assert!(!Fq2 { - c0: Fq::zero(), - c1: Fq::one(), - }.is_zero()); + assert!( + !Fq2 { + c0: Fq::zero(), + c1: Fq::one(), + }.is_zero() + ); } #[test] diff --git a/src/bls12_381/fr.rs b/src/bls12_381/fr.rs index 6e142f0..5e57631 100644 --- a/src/bls12_381/fr.rs +++ b/src/bls12_381/fr.rs @@ -388,12 +388,14 @@ fn test_fr_is_valid() { 0x73eda753299d7d48 ])).is_valid() ); - assert!(!Fr(FrRepr([ - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff - ])).is_valid()); + assert!( + !Fr(FrRepr([ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff + ])).is_valid() + ); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); diff --git a/src/lib.rs b/src/lib.rs index 75af6e2..bbced76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,6 @@ #![cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))] #![cfg_attr(feature = "cargo-clippy", allow(new_without_default_derive))] #![cfg_attr(feature = "cargo-clippy", allow(write_literal))] - // Force public structures to implement Debug #![deny(missing_debug_implementations)] From ef56fabf7ba3ed990a7886836c855298c9c5eefa Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 5 Jul 2018 12:18:56 -0600 Subject: [PATCH 46/60] Update version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3110964..92c2870 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "group" -version = "0.0.0" +version = "0.1.0" authors = [ "Sean Bowe ", "Jack Grigg ", From 7dfc50e7636a9d3da7f128c7d9449e5b8bcedfff Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 12:50:47 +0100 Subject: [PATCH 47/60] Use group crate for curve traits --- Cargo.toml | 1 + benches/bls12_381/ec.rs | 4 +- benches/bls12_381/mod.rs | 2 +- benches/pairing_benches.rs | 1 + src/bls12_381/ec.rs | 30 ++- src/bls12_381/mod.rs | 7 +- src/bls12_381/tests/mod.rs | 2 + src/lib.rs | 203 +----------------- src/tests/curve.rs | 421 ------------------------------------- src/tests/engine.rs | 3 +- src/tests/mod.rs | 1 - src/wnaf.rs | 179 ---------------- 12 files changed, 42 insertions(+), 812 deletions(-) delete mode 100644 src/tests/curve.rs delete mode 100644 src/wnaf.rs diff --git a/Cargo.toml b/Cargo.toml index 5f16018..68971c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ repository = "https://github.com/ebfull/pairing" rand = "0.4" byteorder = "1" ff = { version = "0.4", features = ["derive"] } +group = "0.1" [features] unstable-features = ["expose-arith"] diff --git a/benches/bls12_381/ec.rs b/benches/bls12_381/ec.rs index cbd0590..d8f6618 100644 --- a/benches/bls12_381/ec.rs +++ b/benches/bls12_381/ec.rs @@ -1,8 +1,8 @@ mod g1 { use rand::{Rand, SeedableRng, XorShiftRng}; + use group::CurveProjective; use pairing::bls12_381::*; - use pairing::CurveProjective; #[bench] fn bench_g1_mul_assign(b: &mut ::test::Bencher) { @@ -65,8 +65,8 @@ mod g1 { mod g2 { use rand::{Rand, SeedableRng, XorShiftRng}; + use group::CurveProjective; use pairing::bls12_381::*; - use pairing::CurveProjective; #[bench] fn bench_g2_mul_assign(b: &mut ::test::Bencher) { diff --git a/benches/bls12_381/mod.rs b/benches/bls12_381/mod.rs index 9b46c85..96bcdd5 100644 --- a/benches/bls12_381/mod.rs +++ b/benches/bls12_381/mod.rs @@ -7,7 +7,7 @@ mod fr; use rand::{Rand, SeedableRng, XorShiftRng}; use pairing::bls12_381::*; -use pairing::{CurveAffine, Engine}; +use pairing::{Engine, PairingCurveAffine}; #[bench] fn bench_pairing_g1_preparation(b: &mut ::test::Bencher) { diff --git a/benches/pairing_benches.rs b/benches/pairing_benches.rs index af32a8a..d76e50b 100644 --- a/benches/pairing_benches.rs +++ b/benches/pairing_benches.rs @@ -1,6 +1,7 @@ #![feature(test)] extern crate ff; +extern crate group; extern crate pairing; extern crate rand; extern crate test; diff --git a/src/bls12_381/ec.rs b/src/bls12_381/ec.rs index 37fcbba..f5a6d8f 100644 --- a/src/bls12_381/ec.rs +++ b/src/bls12_381/ec.rs @@ -148,12 +148,9 @@ macro_rules! curve_impl { type Engine = Bls12; type Scalar = $scalarfield; type Base = $basefield; - type Prepared = $prepared; type Projective = $projective; type Uncompressed = $uncompressed; type Compressed = $compressed; - type Pair = $pairing; - type PairingResult = Fq12; fn zero() -> Self { $affine { @@ -182,6 +179,17 @@ macro_rules! curve_impl { } } + fn into_projective(&self) -> $projective { + (*self).into() + } + + } + + impl PairingCurveAffine for $affine { + type Prepared = $prepared; + type Pair = $pairing; + type PairingResult = Fq12; + fn prepare(&self) -> Self::Prepared { $prepared::from_affine(*self) } @@ -190,10 +198,6 @@ macro_rules! curve_impl { self.perform_pairing(other) } - fn into_projective(&self) -> $projective { - (*self).into() - } - } impl Rand for $projective { @@ -624,9 +628,10 @@ pub mod g1 { use super::super::{Bls12, Fq, Fq12, FqRepr, Fr, FrRepr}; use super::g2::G2Affine; use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; + use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; use rand::{Rand, Rng}; use std::fmt; - use {CurveAffine, CurveProjective, EncodedPoint, Engine, GroupDecodingError}; + use {Engine, PairingCurveAffine}; curve_impl!( "G1", @@ -1261,7 +1266,8 @@ pub mod g1 { #[test] fn g1_curve_tests() { - ::tests::curve::curve_tests::(); + use group::tests::curve_tests; + curve_tests::(); } } @@ -1269,9 +1275,10 @@ pub mod g2 { use super::super::{Bls12, Fq, Fq12, Fq2, FqRepr, Fr, FrRepr}; use super::g1::G1Affine; use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; + use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; use rand::{Rand, Rng}; use std::fmt; - use {CurveAffine, CurveProjective, EncodedPoint, Engine, GroupDecodingError}; + use {Engine, PairingCurveAffine}; curve_impl!( "G2", @@ -2014,7 +2021,8 @@ pub mod g2 { #[test] fn g2_curve_tests() { - ::tests::curve::curve_tests::(); + use group::tests::curve_tests; + curve_tests::(); } } diff --git a/src/bls12_381/mod.rs b/src/bls12_381/mod.rs index 106591e..7bc03c6 100644 --- a/src/bls12_381/mod.rs +++ b/src/bls12_381/mod.rs @@ -18,9 +18,10 @@ pub use self::fq2::Fq2; pub use self::fq6::Fq6; pub use self::fr::{Fr, FrRepr}; -use super::{CurveAffine, Engine}; +use super::{Engine, PairingCurveAffine}; use ff::{BitIterator, Field, ScalarEngine}; +use group::CurveAffine; // The BLS parameter x for BLS12-381 is -0xd201000000010000 const BLS_X: u64 = 0xd201000000010000; @@ -46,8 +47,8 @@ impl Engine for Bls12 { where I: IntoIterator< Item = &'a ( - &'a ::Prepared, - &'a ::Prepared, + &'a ::Prepared, + &'a ::Prepared, ), >, { diff --git a/src/bls12_381/tests/mod.rs b/src/bls12_381/tests/mod.rs index bf6c595..6f13661 100644 --- a/src/bls12_381/tests/mod.rs +++ b/src/bls12_381/tests/mod.rs @@ -1,3 +1,5 @@ +use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; + use super::*; use *; diff --git a/src/lib.rs b/src/lib.rs index bbced76..d2e4299 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ extern crate byteorder; #[macro_use] extern crate ff; +extern crate group; extern crate rand; #[cfg(test)] @@ -21,12 +22,8 @@ pub mod tests; pub mod bls12_381; -mod wnaf; -pub use self::wnaf::Wnaf; - use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, SqrtField}; -use std::error::Error; -use std::fmt; +use group::{CurveAffine, CurveProjective}; /// An "engine" is a collection of types (fields, elliptic curve groups, etc.) /// with well-defined relationships. In particular, the G1/G2 curve groups are @@ -42,7 +39,7 @@ pub trait Engine: ScalarEngine { + From; /// The affine representation of an element in G1. - type G1Affine: CurveAffine< + type G1Affine: PairingCurveAffine< Engine = Self, Base = Self::Fq, Scalar = Self::Fr, @@ -62,7 +59,7 @@ pub trait Engine: ScalarEngine { + From; /// The affine representation of an element in G2. - type G2Affine: CurveAffine< + type G2Affine: PairingCurveAffine< Engine = Self, Base = Self::Fqe, Scalar = Self::Fr, @@ -86,8 +83,8 @@ pub trait Engine: ScalarEngine { where I: IntoIterator< Item = &'a ( - &'a ::Prepared, - &'a ::Prepared, + &'a ::Prepared, + &'a ::Prepared, ), >; @@ -106,196 +103,16 @@ pub trait Engine: ScalarEngine { } } -/// Projective representation of an elliptic curve point guaranteed to be -/// in the correct prime order subgroup. -pub trait CurveProjective: - PartialEq - + Eq - + Sized - + Copy - + Clone - + Send - + Sync - + fmt::Debug - + fmt::Display - + rand::Rand - + 'static -{ - type Engine: Engine; - type Scalar: PrimeField + SqrtField; - type Base: SqrtField; - type Affine: CurveAffine; - - /// Returns the additive identity. - fn zero() -> Self; - - /// Returns a fixed generator of unknown exponent. - fn one() -> Self; - - /// Determines if this point is the point at infinity. - fn is_zero(&self) -> bool; - - /// Normalizes a slice of projective elements so that - /// conversion to affine is cheap. - fn batch_normalization(v: &mut [Self]); - - /// Checks if the point is already "normalized" so that - /// cheap affine conversion is possible. - fn is_normalized(&self) -> bool; - - /// Doubles this element. - fn double(&mut self); - - /// Adds another element to this element. - fn add_assign(&mut self, other: &Self); - - /// Subtracts another element from this element. - fn sub_assign(&mut self, other: &Self) { - let mut tmp = *other; - tmp.negate(); - self.add_assign(&tmp); - } - - /// Adds an affine element to this element. - fn add_assign_mixed(&mut self, other: &Self::Affine); - - /// Negates this element. - fn negate(&mut self); - - /// Performs scalar multiplication of this element. - fn mul_assign::Repr>>(&mut self, other: S); - - /// Converts this element into its affine representation. - fn into_affine(&self) -> Self::Affine; - - /// Recommends a wNAF window table size given a scalar. Always returns a number - /// between 2 and 22, inclusive. - fn recommended_wnaf_for_scalar(scalar: ::Repr) -> usize; - - /// Recommends a wNAF window size given the number of scalars you intend to multiply - /// a base by. Always returns a number between 2 and 22, inclusive. - fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize; -} - -/// Affine representation of an elliptic curve point guaranteed to be -/// in the correct prime order subgroup. -pub trait CurveAffine: - Copy + Clone + Sized + Send + Sync + fmt::Debug + fmt::Display + PartialEq + Eq + 'static -{ - type Engine: Engine; - type Scalar: PrimeField + SqrtField; - type Base: SqrtField; - type Projective: CurveProjective; +/// Affine representation of an elliptic curve point that can be used +/// to perform pairings. +pub trait PairingCurveAffine: CurveAffine { type Prepared: Clone + Send + Sync + 'static; - type Uncompressed: EncodedPoint; - type Compressed: EncodedPoint; - type Pair: CurveAffine; + type Pair: PairingCurveAffine; type PairingResult: Field; - /// Returns the additive identity. - fn zero() -> Self; - - /// Returns a fixed generator of unknown exponent. - fn one() -> Self; - - /// Determines if this point represents the point at infinity; the - /// additive identity. - fn is_zero(&self) -> bool; - - /// Negates this element. - fn negate(&mut self); - - /// Performs scalar multiplication of this element with mixed addition. - fn mul::Repr>>(&self, other: S) -> Self::Projective; - /// Prepares this element for pairing purposes. fn prepare(&self) -> Self::Prepared; /// Perform a pairing fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult; - - /// Converts this element into its affine representation. - fn into_projective(&self) -> Self::Projective; - - /// Converts this element into its compressed encoding, so long as it's not - /// the point at infinity. - fn into_compressed(&self) -> Self::Compressed { - ::from_affine(*self) - } - - /// Converts this element into its uncompressed encoding, so long as it's not - /// the point at infinity. - fn into_uncompressed(&self) -> Self::Uncompressed { - ::from_affine(*self) - } -} - -/// An encoded elliptic curve point, which should essentially wrap a `[u8; N]`. -pub trait EncodedPoint: - Sized + Send + Sync + AsRef<[u8]> + AsMut<[u8]> + Clone + Copy + 'static -{ - type Affine: CurveAffine; - - /// Creates an empty representation. - fn empty() -> Self; - - /// Returns the number of bytes consumed by this representation. - fn size() -> usize; - - /// Converts an `EncodedPoint` into a `CurveAffine` element, - /// if the encoding represents a valid element. - fn into_affine(&self) -> Result; - - /// Converts an `EncodedPoint` into a `CurveAffine` element, - /// without guaranteeing that the encoding represents a valid - /// element. This is useful when the caller knows the encoding is - /// valid already. - /// - /// If the encoding is invalid, this can break API invariants, - /// so caution is strongly encouraged. - fn into_affine_unchecked(&self) -> Result; - - /// Creates an `EncodedPoint` from an affine point, as long as the - /// point is not the point at infinity. - fn from_affine(affine: Self::Affine) -> Self; -} - -/// An error that may occur when trying to decode an `EncodedPoint`. -#[derive(Debug)] -pub enum GroupDecodingError { - /// The coordinate(s) do not lie on the curve. - NotOnCurve, - /// The element is not part of the r-order subgroup. - NotInSubgroup, - /// One of the coordinates could not be decoded - CoordinateDecodingError(&'static str, PrimeFieldDecodingError), - /// The compression mode of the encoded element was not as expected - UnexpectedCompressionMode, - /// The encoding contained bits that should not have been set - UnexpectedInformation, -} - -impl Error for GroupDecodingError { - fn description(&self) -> &str { - match *self { - GroupDecodingError::NotOnCurve => "coordinate(s) do not lie on the curve", - GroupDecodingError::NotInSubgroup => "the element is not part of an r-order subgroup", - GroupDecodingError::CoordinateDecodingError(..) => "coordinate(s) could not be decoded", - GroupDecodingError::UnexpectedCompressionMode => { - "encoding has unexpected compression mode" - } - GroupDecodingError::UnexpectedInformation => "encoding has unexpected information", - } - } -} - -impl fmt::Display for GroupDecodingError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - GroupDecodingError::CoordinateDecodingError(description, ref err) => { - write!(f, "{} decoding error: {}", description, err) - } - _ => write!(f, "{}", self.description()), - } - } } diff --git a/src/tests/curve.rs b/src/tests/curve.rs deleted file mode 100644 index bb0406c..0000000 --- a/src/tests/curve.rs +++ /dev/null @@ -1,421 +0,0 @@ -use ff::Field; -use rand::{Rand, Rng, SeedableRng, XorShiftRng}; - -use {CurveAffine, CurveProjective, EncodedPoint}; - -pub fn curve_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - - // Negation edge case with zero. - { - let mut z = G::zero(); - z.negate(); - assert!(z.is_zero()); - } - - // Doubling edge case with zero. - { - let mut z = G::zero(); - z.double(); - assert!(z.is_zero()); - } - - // Addition edge cases with zero - { - let mut r = G::rand(&mut rng); - let rcopy = r; - r.add_assign(&G::zero()); - assert_eq!(r, rcopy); - r.add_assign_mixed(&G::Affine::zero()); - assert_eq!(r, rcopy); - - let mut z = G::zero(); - z.add_assign(&G::zero()); - assert!(z.is_zero()); - z.add_assign_mixed(&G::Affine::zero()); - assert!(z.is_zero()); - - let mut z2 = z; - z2.add_assign(&r); - - z.add_assign_mixed(&r.into_affine()); - - assert_eq!(z, z2); - assert_eq!(z, r); - } - - // Transformations - { - let a = G::rand(&mut rng); - let b = a.into_affine().into_projective(); - let c = a - .into_affine() - .into_projective() - .into_affine() - .into_projective(); - assert_eq!(a, b); - assert_eq!(b, c); - } - - random_addition_tests::(); - random_multiplication_tests::(); - random_doubling_tests::(); - random_negation_tests::(); - random_transformation_tests::(); - random_wnaf_tests::(); - random_encoding_tests::(); -} - -fn random_wnaf_tests() { - use ff::PrimeField; - use wnaf::*; - - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - - { - let mut table = vec![]; - let mut wnaf = vec![]; - - for w in 2..14 { - for _ in 0..100 { - let g = G::rand(&mut rng); - let s = G::Scalar::rand(&mut rng).into_repr(); - let mut g1 = g; - g1.mul_assign(s); - - wnaf_table(&mut table, g, w); - wnaf_form(&mut wnaf, s, w); - let g2 = wnaf_exp(&table, &wnaf); - - assert_eq!(g1, g2); - } - } - } - - { - fn only_compiles_if_send(_: &S) {} - - for _ in 0..100 { - let g = G::rand(&mut rng); - let s = G::Scalar::rand(&mut rng).into_repr(); - let mut g1 = g; - g1.mul_assign(s); - - let g2 = { - let mut wnaf = Wnaf::new(); - wnaf.base(g, 1).scalar(s) - }; - let g3 = { - let mut wnaf = Wnaf::new(); - wnaf.scalar(s).base(g) - }; - let g4 = { - let mut wnaf = Wnaf::new(); - let mut shared = wnaf.base(g, 1).shared(); - - only_compiles_if_send(&shared); - - shared.scalar(s) - }; - let g5 = { - let mut wnaf = Wnaf::new(); - let mut shared = wnaf.scalar(s).shared(); - - only_compiles_if_send(&shared); - - shared.base(g) - }; - - let g6 = { - let mut wnaf = Wnaf::new(); - { - // Populate the vectors. - wnaf.base(rng.gen(), 1).scalar(rng.gen()); - } - wnaf.base(g, 1).scalar(s) - }; - let g7 = { - let mut wnaf = Wnaf::new(); - { - // Populate the vectors. - wnaf.base(rng.gen(), 1).scalar(rng.gen()); - } - wnaf.scalar(s).base(g) - }; - let g8 = { - let mut wnaf = Wnaf::new(); - { - // Populate the vectors. - wnaf.base(rng.gen(), 1).scalar(rng.gen()); - } - let mut shared = wnaf.base(g, 1).shared(); - - only_compiles_if_send(&shared); - - shared.scalar(s) - }; - let g9 = { - let mut wnaf = Wnaf::new(); - { - // Populate the vectors. - wnaf.base(rng.gen(), 1).scalar(rng.gen()); - } - let mut shared = wnaf.scalar(s).shared(); - - only_compiles_if_send(&shared); - - shared.base(g) - }; - - assert_eq!(g1, g2); - assert_eq!(g1, g3); - assert_eq!(g1, g4); - assert_eq!(g1, g5); - assert_eq!(g1, g6); - assert_eq!(g1, g7); - assert_eq!(g1, g8); - assert_eq!(g1, g9); - } - } -} - -fn random_negation_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - - for _ in 0..1000 { - let r = G::rand(&mut rng); - - let s = G::Scalar::rand(&mut rng); - let mut sneg = s; - sneg.negate(); - - let mut t1 = r; - t1.mul_assign(s); - - let mut t2 = r; - t2.mul_assign(sneg); - - let mut t3 = t1; - t3.add_assign(&t2); - assert!(t3.is_zero()); - - let mut t4 = t1; - t4.add_assign_mixed(&t2.into_affine()); - assert!(t4.is_zero()); - - t1.negate(); - assert_eq!(t1, t2); - } -} - -fn random_doubling_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - - for _ in 0..1000 { - let mut a = G::rand(&mut rng); - let mut b = G::rand(&mut rng); - - // 2(a + b) - let mut tmp1 = a; - tmp1.add_assign(&b); - tmp1.double(); - - // 2a + 2b - a.double(); - b.double(); - - let mut tmp2 = a; - tmp2.add_assign(&b); - - let mut tmp3 = a; - tmp3.add_assign_mixed(&b.into_affine()); - - assert_eq!(tmp1, tmp2); - assert_eq!(tmp1, tmp3); - } -} - -fn random_multiplication_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - - for _ in 0..1000 { - let mut a = G::rand(&mut rng); - let mut b = G::rand(&mut rng); - let a_affine = a.into_affine(); - let b_affine = b.into_affine(); - - let s = G::Scalar::rand(&mut rng); - - // s ( a + b ) - let mut tmp1 = a; - tmp1.add_assign(&b); - tmp1.mul_assign(s); - - // sa + sb - a.mul_assign(s); - b.mul_assign(s); - - let mut tmp2 = a; - tmp2.add_assign(&b); - - // Affine multiplication - let mut tmp3 = a_affine.mul(s); - tmp3.add_assign(&b_affine.mul(s)); - - assert_eq!(tmp1, tmp2); - assert_eq!(tmp1, tmp3); - } -} - -fn random_addition_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - - for _ in 0..1000 { - let a = G::rand(&mut rng); - let b = G::rand(&mut rng); - let c = G::rand(&mut rng); - let a_affine = a.into_affine(); - let b_affine = b.into_affine(); - let c_affine = c.into_affine(); - - // a + a should equal the doubling - { - let mut aplusa = a; - aplusa.add_assign(&a); - - let mut aplusamixed = a; - aplusamixed.add_assign_mixed(&a.into_affine()); - - let mut adouble = a; - adouble.double(); - - assert_eq!(aplusa, adouble); - assert_eq!(aplusa, aplusamixed); - } - - let mut tmp = vec![G::zero(); 6]; - - // (a + b) + c - tmp[0] = a; - tmp[0].add_assign(&b); - tmp[0].add_assign(&c); - - // a + (b + c) - tmp[1] = b; - tmp[1].add_assign(&c); - tmp[1].add_assign(&a); - - // (a + c) + b - tmp[2] = a; - tmp[2].add_assign(&c); - tmp[2].add_assign(&b); - - // Mixed addition - - // (a + b) + c - tmp[3] = a_affine.into_projective(); - tmp[3].add_assign_mixed(&b_affine); - tmp[3].add_assign_mixed(&c_affine); - - // a + (b + c) - tmp[4] = b_affine.into_projective(); - tmp[4].add_assign_mixed(&c_affine); - tmp[4].add_assign_mixed(&a_affine); - - // (a + c) + b - tmp[5] = a_affine.into_projective(); - tmp[5].add_assign_mixed(&c_affine); - tmp[5].add_assign_mixed(&b_affine); - - // Comparisons - for i in 0..6 { - for j in 0..6 { - assert_eq!(tmp[i], tmp[j]); - assert_eq!(tmp[i].into_affine(), tmp[j].into_affine()); - } - - assert!(tmp[i] != a); - assert!(tmp[i] != b); - assert!(tmp[i] != c); - - assert!(a != tmp[i]); - assert!(b != tmp[i]); - assert!(c != tmp[i]); - } - } -} - -fn random_transformation_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - - for _ in 0..1000 { - let g = G::rand(&mut rng); - let g_affine = g.into_affine(); - let g_projective = g_affine.into_projective(); - assert_eq!(g, g_projective); - } - - // Batch normalization - for _ in 0..10 { - let mut v = (0..1000).map(|_| G::rand(&mut rng)).collect::>(); - - for i in &v { - assert!(!i.is_normalized()); - } - - use rand::distributions::{IndependentSample, Range}; - let between = Range::new(0, 1000); - // Sprinkle in some normalized points - for _ in 0..5 { - v[between.ind_sample(&mut rng)] = G::zero(); - } - for _ in 0..5 { - let s = between.ind_sample(&mut rng); - v[s] = v[s].into_affine().into_projective(); - } - - let expected_v = v - .iter() - .map(|v| v.into_affine().into_projective()) - .collect::>(); - G::batch_normalization(&mut v); - - for i in &v { - assert!(i.is_normalized()); - } - - assert_eq!(v, expected_v); - } -} - -fn random_encoding_tests() { - let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - - assert_eq!( - G::zero().into_uncompressed().into_affine().unwrap(), - G::zero() - ); - - assert_eq!( - G::zero().into_compressed().into_affine().unwrap(), - G::zero() - ); - - for _ in 0..1000 { - let mut r = G::Projective::rand(&mut rng).into_affine(); - - let uncompressed = r.into_uncompressed(); - let de_uncompressed = uncompressed.into_affine().unwrap(); - assert_eq!(de_uncompressed, r); - - let compressed = r.into_compressed(); - let de_compressed = compressed.into_affine().unwrap(); - assert_eq!(de_compressed, r); - - r.negate(); - - let compressed = r.into_compressed(); - let de_compressed = compressed.into_affine().unwrap(); - assert_eq!(de_compressed, r); - } -} diff --git a/src/tests/engine.rs b/src/tests/engine.rs index 52ff4e0..7b1944d 100644 --- a/src/tests/engine.rs +++ b/src/tests/engine.rs @@ -1,6 +1,7 @@ +use group::{CurveAffine, CurveProjective}; use rand::{Rand, SeedableRng, XorShiftRng}; -use {CurveAffine, CurveProjective, Engine, Field, PrimeField}; +use {Engine, Field, PairingCurveAffine, PrimeField}; pub fn engine_tests() { let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index bc83958..d6ad6a1 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -1,4 +1,3 @@ -pub mod curve; pub mod engine; pub mod field; pub mod repr; diff --git a/src/wnaf.rs b/src/wnaf.rs deleted file mode 100644 index 69c6fd9..0000000 --- a/src/wnaf.rs +++ /dev/null @@ -1,179 +0,0 @@ -use super::{CurveProjective, PrimeField, PrimeFieldRepr}; - -/// Replaces the contents of `table` with a w-NAF window table for the given window size. -pub(crate) fn wnaf_table(table: &mut Vec, mut base: G, window: usize) { - table.truncate(0); - table.reserve(1 << (window - 1)); - - let mut dbl = base; - dbl.double(); - - for _ in 0..(1 << (window - 1)) { - table.push(base); - base.add_assign(&dbl); - } -} - -/// Replaces the contents of `wnaf` with the w-NAF representation of a scalar. -pub(crate) fn wnaf_form(wnaf: &mut Vec, mut c: S, window: usize) { - wnaf.truncate(0); - - while !c.is_zero() { - let mut u; - if c.is_odd() { - u = (c.as_ref()[0] % (1 << (window + 1))) as i64; - - if u > (1 << window) { - u -= 1 << (window + 1); - } - - if u > 0 { - c.sub_noborrow(&S::from(u as u64)); - } else { - c.add_nocarry(&S::from((-u) as u64)); - } - } else { - u = 0; - } - - wnaf.push(u); - - c.div2(); - } -} - -/// Performs w-NAF exponentiation with the provided window table and w-NAF form scalar. -/// -/// This function must be provided a `table` and `wnaf` that were constructed with -/// the same window size; otherwise, it may panic or produce invalid results. -pub(crate) fn wnaf_exp(table: &[G], wnaf: &[i64]) -> G { - let mut result = G::zero(); - - let mut found_one = false; - - for n in wnaf.iter().rev() { - if found_one { - result.double(); - } - - if *n != 0 { - found_one = true; - - if *n > 0 { - result.add_assign(&table[(n / 2) as usize]); - } else { - result.sub_assign(&table[((-n) / 2) as usize]); - } - } - } - - result -} - -/// A "w-ary non-adjacent form" exponentiation context. -#[derive(Debug)] -pub struct Wnaf { - base: B, - scalar: S, - window_size: W, -} - -impl Wnaf<(), Vec, Vec> { - /// Construct a new wNAF context without allocating. - pub fn new() -> Self { - Wnaf { - base: vec![], - scalar: vec![], - window_size: (), - } - } - - /// Given a base and a number of scalars, compute a window table and return a `Wnaf` object that - /// can perform exponentiations with `.scalar(..)`. - pub fn base(&mut self, base: G, num_scalars: usize) -> Wnaf> { - // Compute the appropriate window size based on the number of scalars. - let window_size = G::recommended_wnaf_for_num_scalars(num_scalars); - - // Compute a wNAF table for the provided base and window size. - wnaf_table(&mut self.base, base, window_size); - - // Return a Wnaf object that immutably borrows the computed base storage location, - // but mutably borrows the scalar storage location. - Wnaf { - base: &self.base[..], - scalar: &mut self.scalar, - window_size, - } - } - - /// Given a scalar, compute its wNAF representation and return a `Wnaf` object that can perform - /// exponentiations with `.base(..)`. - pub fn scalar( - &mut self, - scalar: <::Scalar as PrimeField>::Repr, - ) -> Wnaf, &[i64]> { - // Compute the appropriate window size for the scalar. - let window_size = G::recommended_wnaf_for_scalar(scalar); - - // Compute the wNAF form of the scalar. - wnaf_form(&mut self.scalar, scalar, window_size); - - // Return a Wnaf object that mutably borrows the base storage location, but - // immutably borrows the computed wNAF form scalar location. - Wnaf { - base: &mut self.base, - scalar: &self.scalar[..], - window_size, - } - } -} - -impl<'a, G: CurveProjective> Wnaf> { - /// Constructs new space for the scalar representation while borrowing - /// the computed window table, for sending the window table across threads. - pub fn shared(&self) -> Wnaf> { - Wnaf { - base: self.base, - scalar: vec![], - window_size: self.window_size, - } - } -} - -impl<'a, G: CurveProjective> Wnaf, &'a [i64]> { - /// Constructs new space for the window table while borrowing - /// the computed scalar representation, for sending the scalar representation - /// across threads. - pub fn shared(&self) -> Wnaf, &'a [i64]> { - Wnaf { - base: vec![], - scalar: self.scalar, - window_size: self.window_size, - } - } -} - -impl> Wnaf { - /// Performs exponentiation given a base. - pub fn base(&mut self, base: G) -> G - where - B: AsMut>, - { - wnaf_table(self.base.as_mut(), base, self.window_size); - wnaf_exp(self.base.as_mut(), self.scalar.as_ref()) - } -} - -impl>> Wnaf { - /// Performs exponentiation given a scalar. - pub fn scalar( - &mut self, - scalar: <::Scalar as PrimeField>::Repr, - ) -> G - where - B: AsRef<[G]>, - { - wnaf_form(self.scalar.as_mut(), scalar, self.window_size); - wnaf_exp(self.base.as_ref(), self.scalar.as_mut()) - } -} From 3d41ee5abaa4888ff3607689aba007be8856816d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 20:02:51 +0100 Subject: [PATCH 48/60] Remove now-unused imports from root --- src/bls12_381/tests/mod.rs | 1 + src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bls12_381/tests/mod.rs b/src/bls12_381/tests/mod.rs index 6f13661..b5b75a3 100644 --- a/src/bls12_381/tests/mod.rs +++ b/src/bls12_381/tests/mod.rs @@ -1,3 +1,4 @@ +use ff::PrimeFieldRepr; use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; use super::*; diff --git a/src/lib.rs b/src/lib.rs index d2e4299..adabcce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ pub mod tests; pub mod bls12_381; -use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, SqrtField}; +use ff::{Field, PrimeField, ScalarEngine, SqrtField}; use group::{CurveAffine, CurveProjective}; /// An "engine" is a collection of types (fields, elliptic curve groups, etc.) From 718b25c94991895eadbb09d4cf8b5d7e35e0d588 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Jul 2018 16:43:17 +0100 Subject: [PATCH 49/60] Use ff crate for Field traits --- Cargo.toml | 6 +++++- src/domain.rs | 3 +-- src/groth16/generator.rs | 3 +-- src/groth16/mod.rs | 2 +- src/groth16/prover.rs | 3 +-- src/groth16/tests/dummy_engine.rs | 14 +++++++------- src/groth16/tests/mod.rs | 7 ++----- src/groth16/verifier.rs | 2 +- src/lib.rs | 4 +++- src/multiexp.rs | 19 ++++++++----------- tests/mimc.rs | 7 +++---- 11 files changed, 33 insertions(+), 37 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3a9105f..86914bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,12 +11,16 @@ version = "0.1.0" [dependencies] rand = "0.4" bit-vec = "0.4.4" +ff = "0.4" futures = "0.1" futures-cpupool = "0.1" num_cpus = "1" crossbeam = "0.3" -pairing = "0.14" byteorder = "1" +[dependencies.pairing] +git = "https://github.com/ebfull/pairing" +rev = "183a64b08e9dc7067f78624ec161371f1829623e" + [features] default = [] diff --git a/src/domain.rs b/src/domain.rs index ff626e5..886b464 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -10,10 +10,9 @@ //! This allows us to perform polynomial operations in O(n) //! by performing an O(n log n) FFT over such a domain. +use ff::{Field, PrimeField}; use pairing::{ Engine, - Field, - PrimeField, CurveProjective }; diff --git a/src/groth16/generator.rs b/src/groth16/generator.rs index 1eed62d..2b319ea 100644 --- a/src/groth16/generator.rs +++ b/src/groth16/generator.rs @@ -2,10 +2,9 @@ use rand::Rng; use std::sync::Arc; +use ff::{Field, PrimeField}; use pairing::{ Engine, - PrimeField, - Field, Wnaf, CurveProjective, CurveAffine diff --git a/src/groth16/mod.rs b/src/groth16/mod.rs index 3b8d671..a55b6c8 100644 --- a/src/groth16/mod.rs +++ b/src/groth16/mod.rs @@ -486,8 +486,8 @@ mod test_with_bls12_381 { use super::*; use {Circuit, SynthesisError, ConstraintSystem}; + use ff::Field; use rand::{Rand, thread_rng}; - use pairing::{Field}; use pairing::bls12_381::{Bls12, Fr}; #[test] diff --git a/src/groth16/prover.rs b/src/groth16/prover.rs index f21fcce..7e53120 100644 --- a/src/groth16/prover.rs +++ b/src/groth16/prover.rs @@ -4,10 +4,9 @@ use std::sync::Arc; use futures::Future; +use ff::{Field, PrimeField}; use pairing::{ Engine, - PrimeField, - Field, CurveProjective, CurveAffine }; diff --git a/src/groth16/tests/dummy_engine.rs b/src/groth16/tests/dummy_engine.rs index 26c8996..c739f34 100644 --- a/src/groth16/tests/dummy_engine.rs +++ b/src/groth16/tests/dummy_engine.rs @@ -1,13 +1,10 @@ +use ff::{ + Field, LegendreSymbol, PrimeField, PrimeFieldDecodingError, + PrimeFieldRepr, ScalarEngine, SqrtField}; use pairing::{ Engine, - PrimeField, - PrimeFieldRepr, - Field, - SqrtField, - LegendreSymbol, CurveProjective, CurveAffine, - PrimeFieldDecodingError, GroupDecodingError, EncodedPoint }; @@ -263,8 +260,11 @@ impl PrimeField for Fr { #[derive(Clone)] pub struct DummyEngine; -impl Engine for DummyEngine { +impl ScalarEngine for DummyEngine { type Fr = Fr; +} + +impl Engine for DummyEngine { type G1 = Fr; type G1Affine = Fr; type G2 = Fr; diff --git a/src/groth16/tests/mod.rs b/src/groth16/tests/mod.rs index a8e2914..0e05c36 100644 --- a/src/groth16/tests/mod.rs +++ b/src/groth16/tests/mod.rs @@ -1,8 +1,5 @@ -use pairing::{ - Engine, - Field, - PrimeField -}; +use ff::{Field, PrimeField}; +use pairing::Engine; mod dummy_engine; use self::dummy_engine::*; diff --git a/src/groth16/verifier.rs b/src/groth16/verifier.rs index 083e1d0..a4e914b 100644 --- a/src/groth16/verifier.rs +++ b/src/groth16/verifier.rs @@ -1,8 +1,8 @@ +use ff::PrimeField; use pairing::{ Engine, CurveProjective, CurveAffine, - PrimeField }; use super::{ diff --git a/src/lib.rs b/src/lib.rs index fb8d043..2ddb4ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +extern crate ff; extern crate pairing; extern crate rand; extern crate num_cpus; @@ -12,7 +13,8 @@ mod multiexp; pub mod domain; pub mod groth16; -use pairing::{Engine, Field}; +use ff::Field; +use pairing::Engine; use std::ops::{Add, Sub}; use std::fmt; diff --git a/src/multiexp.rs b/src/multiexp.rs index b1dc1f1..2481d86 100644 --- a/src/multiexp.rs +++ b/src/multiexp.rs @@ -1,10 +1,7 @@ +use ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine}; use pairing::{ CurveAffine, CurveProjective, - Engine, - PrimeField, - Field, - PrimeFieldRepr }; use std::sync::Arc; use std::io; @@ -141,7 +138,7 @@ fn multiexp_inner( pool: &Worker, bases: S, density_map: D, - exponents: Arc::Fr as PrimeField>::Repr>>, + exponents: Arc::Fr as PrimeField>::Repr>>, mut skip: u32, c: u32, handle_trivial: bool @@ -167,8 +164,8 @@ fn multiexp_inner( // Create space for the buckets let mut buckets = vec![::Projective::zero(); (1 << c) - 1]; - let zero = ::Fr::zero().into_repr(); - let one = ::Fr::one().into_repr(); + let zero = ::Fr::zero().into_repr(); + let one = ::Fr::one().into_repr(); // Sort the bases into buckets for (&exp, density) in exponents.iter().zip(density_map.as_ref().iter()) { @@ -211,7 +208,7 @@ fn multiexp_inner( skip += c; - if skip >= ::Fr::NUM_BITS { + if skip >= ::Fr::NUM_BITS { // There isn't another region. Box::new(this) } else { @@ -238,7 +235,7 @@ pub fn multiexp( pool: &Worker, bases: S, density_map: D, - exponents: Arc::Fr as PrimeField>::Repr>> + exponents: Arc::Fr as PrimeField>::Repr>> ) -> Box::Projective, Error=SynthesisError>> where for<'a> &'a Q: QueryDensity, D: Send + Sync + 'static + Clone + AsRef, @@ -280,12 +277,12 @@ fn test_with_bls12() { } use rand::{self, Rand}; - use pairing::bls12_381::Bls12; + use pairing::{bls12_381::Bls12, Engine}; const SAMPLES: usize = 1 << 14; let rng = &mut rand::thread_rng(); - let v = Arc::new((0..SAMPLES).map(|_| ::Fr::rand(rng).into_repr()).collect::>()); + let v = Arc::new((0..SAMPLES).map(|_| ::Fr::rand(rng).into_repr()).collect::>()); let g = Arc::new((0..SAMPLES).map(|_| ::G1::rand(rng).into_affine()).collect::>()); let naive = naive_multiexp(g.clone(), v.clone()); diff --git a/tests/mimc.rs b/tests/mimc.rs index d6ff72b..1d554a5 100644 --- a/tests/mimc.rs +++ b/tests/mimc.rs @@ -1,4 +1,5 @@ extern crate bellman; +extern crate ff; extern crate pairing; extern crate rand; @@ -9,10 +10,8 @@ use rand::{thread_rng, Rng}; use std::time::{Duration, Instant}; // Bring in some tools for using pairing-friendly curves -use pairing::{ - Engine, - Field -}; +use ff::Field; +use pairing::Engine; // We're going to use the BLS12-381 pairing-friendly elliptic curve. use pairing::bls12_381::{ From 3e8f2f820253392415f61347d3435086732986a2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 6 Jul 2018 21:24:03 +0100 Subject: [PATCH 50/60] Use group crate for curve traits and wNAF --- Cargo.toml | 5 +++-- src/domain.rs | 10 ++++------ src/groth16/generator.rs | 8 ++------ src/groth16/mod.rs | 8 ++++---- src/groth16/prover.rs | 7 ++----- src/groth16/tests/dummy_engine.rs | 30 ++++++++++++++---------------- src/groth16/verifier.rs | 7 ++----- src/lib.rs | 1 + src/multiexp.rs | 5 +---- 9 files changed, 33 insertions(+), 48 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 86914bb..8abf83e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,13 +14,14 @@ bit-vec = "0.4.4" ff = "0.4" futures = "0.1" futures-cpupool = "0.1" +group = "0.1" num_cpus = "1" crossbeam = "0.3" byteorder = "1" [dependencies.pairing] -git = "https://github.com/ebfull/pairing" -rev = "183a64b08e9dc7067f78624ec161371f1829623e" +git = "https://github.com/str4d/pairing" +rev = "3d41ee5abaa4888ff3607689aba007be8856816d" [features] default = [] diff --git a/src/domain.rs b/src/domain.rs index 886b464..26cb4f9 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -10,11 +10,9 @@ //! This allows us to perform polynomial operations in O(n) //! by performing an O(n log n) FFT over such a domain. -use ff::{Field, PrimeField}; -use pairing::{ - Engine, - CurveProjective -}; +use ff::{Field, PrimeField, ScalarEngine}; +use group::CurveProjective; +use pairing::Engine; use super::{ SynthesisError @@ -188,7 +186,7 @@ impl> EvaluationDomain { } } -pub trait Group: Sized + Copy + Clone + Send + Sync { +pub trait Group: Sized + Copy + Clone + Send + Sync { fn group_zero() -> Self; fn group_mul_assign(&mut self, by: &E::Fr); fn group_add_assign(&mut self, other: &Self); diff --git a/src/groth16/generator.rs b/src/groth16/generator.rs index 2b319ea..f3f3d3a 100644 --- a/src/groth16/generator.rs +++ b/src/groth16/generator.rs @@ -3,12 +3,8 @@ use rand::Rng; use std::sync::Arc; use ff::{Field, PrimeField}; -use pairing::{ - Engine, - Wnaf, - CurveProjective, - CurveAffine -}; +use group::{CurveAffine, CurveProjective, Wnaf}; +use pairing::Engine; use super::{ Parameters, diff --git a/src/groth16/mod.rs b/src/groth16/mod.rs index a55b6c8..620f32e 100644 --- a/src/groth16/mod.rs +++ b/src/groth16/mod.rs @@ -1,7 +1,7 @@ +use group::{CurveAffine, EncodedPoint}; use pairing::{ Engine, - CurveAffine, - EncodedPoint + PairingCurveAffine, }; use ::{ @@ -385,9 +385,9 @@ pub struct PreparedVerifyingKey { /// Pairing result of alpha*beta alpha_g1_beta_g2: E::Fqk, /// -gamma in G2 - neg_gamma_g2: ::Prepared, + neg_gamma_g2: ::Prepared, /// -delta in G2 - neg_delta_g2: ::Prepared, + neg_delta_g2: ::Prepared, /// Copy of IC from `VerifiyingKey`. ic: Vec } diff --git a/src/groth16/prover.rs b/src/groth16/prover.rs index 7e53120..c674622 100644 --- a/src/groth16/prover.rs +++ b/src/groth16/prover.rs @@ -5,11 +5,8 @@ use std::sync::Arc; use futures::Future; use ff::{Field, PrimeField}; -use pairing::{ - Engine, - CurveProjective, - CurveAffine -}; +use group::{CurveAffine, CurveProjective}; +use pairing::Engine; use super::{ ParameterSource, diff --git a/src/groth16/tests/dummy_engine.rs b/src/groth16/tests/dummy_engine.rs index c739f34..d5f37a9 100644 --- a/src/groth16/tests/dummy_engine.rs +++ b/src/groth16/tests/dummy_engine.rs @@ -1,13 +1,8 @@ use ff::{ Field, LegendreSymbol, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, SqrtField}; -use pairing::{ - Engine, - CurveProjective, - CurveAffine, - GroupDecodingError, - EncodedPoint -}; +use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; +use pairing::{Engine, PairingCurveAffine}; use std::cmp::Ordering; use std::fmt; @@ -277,8 +272,8 @@ impl Engine for DummyEngine { fn miller_loop<'a, I>(i: I) -> Self::Fqk where I: IntoIterator::Prepared, - &'a ::Prepared + &'a ::Prepared, + &'a ::Prepared )> { let mut acc = ::zero(); @@ -401,11 +396,8 @@ impl EncodedPoint for FakePoint { } impl CurveAffine for Fr { - type Pair = Fr; - type PairingResult = Fr; type Compressed = FakePoint; type Uncompressed = FakePoint; - type Prepared = Fr; type Projective = Fr; type Base = Fr; type Scalar = Fr; @@ -437,6 +429,16 @@ impl CurveAffine for Fr { res } + fn into_projective(&self) -> Self::Projective { + *self + } +} + +impl PairingCurveAffine for Fr { + type Prepared = Fr; + type Pair = Fr; + type PairingResult = Fr; + fn prepare(&self) -> Self::Prepared { *self } @@ -444,8 +446,4 @@ impl CurveAffine for Fr { fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult { self.mul(*other) } - - fn into_projective(&self) -> Self::Projective { - *self - } } diff --git a/src/groth16/verifier.rs b/src/groth16/verifier.rs index a4e914b..71c7478 100644 --- a/src/groth16/verifier.rs +++ b/src/groth16/verifier.rs @@ -1,9 +1,6 @@ use ff::PrimeField; -use pairing::{ - Engine, - CurveProjective, - CurveAffine, -}; +use group::{CurveAffine, CurveProjective}; +use pairing::{Engine, PairingCurveAffine}; use super::{ Proof, diff --git a/src/lib.rs b/src/lib.rs index 2ddb4ac..6beaddd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ extern crate ff; +extern crate group; extern crate pairing; extern crate rand; extern crate num_cpus; diff --git a/src/multiexp.rs b/src/multiexp.rs index 2481d86..cea13f3 100644 --- a/src/multiexp.rs +++ b/src/multiexp.rs @@ -1,8 +1,5 @@ use ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine}; -use pairing::{ - CurveAffine, - CurveProjective, -}; +use group::{CurveAffine, CurveProjective}; use std::sync::Arc; use std::io; use bit_vec::{self, BitVec}; From 276e09f1fb6c11598a799b815702046de82e5e9f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 6 Jul 2018 21:37:18 +0100 Subject: [PATCH 51/60] Use ff:ScalarEngine instead of pairing::Engine in bellman core --- src/domain.rs | 27 +++++++++++++-------------- src/lib.rs | 37 ++++++++++++++++++------------------- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/domain.rs b/src/domain.rs index 26cb4f9..87a8240 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -12,7 +12,6 @@ use ff::{Field, PrimeField, ScalarEngine}; use group::CurveProjective; -use pairing::Engine; use super::{ SynthesisError @@ -20,7 +19,7 @@ use super::{ use super::multicore::Worker; -pub struct EvaluationDomain> { +pub struct EvaluationDomain> { coeffs: Vec, exp: u32, omega: E::Fr, @@ -29,7 +28,7 @@ pub struct EvaluationDomain> { minv: E::Fr } -impl> EvaluationDomain { +impl> EvaluationDomain { pub fn as_ref(&self) -> &[G] { &self.coeffs } @@ -224,23 +223,23 @@ impl Group for Point { } } -pub struct Scalar(pub E::Fr); +pub struct Scalar(pub E::Fr); -impl PartialEq for Scalar { +impl PartialEq for Scalar { fn eq(&self, other: &Scalar) -> bool { self.0 == other.0 } } -impl Copy for Scalar { } +impl Copy for Scalar { } -impl Clone for Scalar { +impl Clone for Scalar { fn clone(&self) -> Scalar { *self } } -impl Group for Scalar { +impl Group for Scalar { fn group_zero() -> Self { Scalar(E::Fr::zero()) } @@ -255,7 +254,7 @@ impl Group for Scalar { } } -fn best_fft>(a: &mut [T], worker: &Worker, omega: &E::Fr, log_n: u32) +fn best_fft>(a: &mut [T], worker: &Worker, omega: &E::Fr, log_n: u32) { let log_cpus = worker.log_num_cpus(); @@ -266,7 +265,7 @@ fn best_fft>(a: &mut [T], worker: &Worker, omega: &E::Fr, } } -fn serial_fft>(a: &mut [T], omega: &E::Fr, log_n: u32) +fn serial_fft>(a: &mut [T], omega: &E::Fr, log_n: u32) { fn bitreverse(mut n: u32, l: u32) -> u32 { let mut r = 0; @@ -311,7 +310,7 @@ fn serial_fft>(a: &mut [T], omega: &E::Fr, log_n: u32) } } -fn parallel_fft>( +fn parallel_fft>( a: &mut [T], worker: &Worker, omega: &E::Fr, @@ -377,7 +376,7 @@ fn polynomial_arith() { use pairing::bls12_381::Bls12; use rand::{self, Rand}; - fn test_mul(rng: &mut R) + fn test_mul(rng: &mut R) { let worker = Worker::new(); @@ -424,7 +423,7 @@ fn fft_composition() { use pairing::bls12_381::Bls12; use rand; - fn test_comp(rng: &mut R) + fn test_comp(rng: &mut R) { let worker = Worker::new(); @@ -463,7 +462,7 @@ fn parallel_fft_consistency() { use rand::{self, Rand}; use std::cmp::min; - fn test_consistency(rng: &mut R) + fn test_consistency(rng: &mut R) { let worker = Worker::new(); diff --git a/src/lib.rs b/src/lib.rs index 6beaddd..42eccea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,8 +14,7 @@ mod multiexp; pub mod domain; pub mod groth16; -use ff::Field; -use pairing::Engine; +use ff::{Field, ScalarEngine}; use std::ops::{Add, Sub}; use std::fmt; @@ -27,7 +26,7 @@ use std::marker::PhantomData; /// rank-1 quadratic constraint systems. The `Circuit` trait represents a /// circuit that can be synthesized. The `synthesize` method is called during /// CRS generation and during proving. -pub trait Circuit { +pub trait Circuit { /// Synthesize the circuit into a rank-1 quadratic constraint system fn synthesize>( self, @@ -64,21 +63,21 @@ pub enum Index { /// This represents a linear combination of some variables, with coefficients /// in the scalar field of a pairing-friendly elliptic curve group. #[derive(Clone)] -pub struct LinearCombination(Vec<(Variable, E::Fr)>); +pub struct LinearCombination(Vec<(Variable, E::Fr)>); -impl AsRef<[(Variable, E::Fr)]> for LinearCombination { +impl AsRef<[(Variable, E::Fr)]> for LinearCombination { fn as_ref(&self) -> &[(Variable, E::Fr)] { &self.0 } } -impl LinearCombination { +impl LinearCombination { pub fn zero() -> LinearCombination { LinearCombination(vec![]) } } -impl Add<(E::Fr, Variable)> for LinearCombination { +impl Add<(E::Fr, Variable)> for LinearCombination { type Output = LinearCombination; fn add(mut self, (coeff, var): (E::Fr, Variable)) -> LinearCombination { @@ -88,7 +87,7 @@ impl Add<(E::Fr, Variable)> for LinearCombination { } } -impl Sub<(E::Fr, Variable)> for LinearCombination { +impl Sub<(E::Fr, Variable)> for LinearCombination { type Output = LinearCombination; fn sub(self, (mut coeff, var): (E::Fr, Variable)) -> LinearCombination { @@ -98,7 +97,7 @@ impl Sub<(E::Fr, Variable)> for LinearCombination { } } -impl Add for LinearCombination { +impl Add for LinearCombination { type Output = LinearCombination; fn add(self, other: Variable) -> LinearCombination { @@ -106,7 +105,7 @@ impl Add for LinearCombination { } } -impl Sub for LinearCombination { +impl Sub for LinearCombination { type Output = LinearCombination; fn sub(self, other: Variable) -> LinearCombination { @@ -114,7 +113,7 @@ impl Sub for LinearCombination { } } -impl<'a, E: Engine> Add<&'a LinearCombination> for LinearCombination { +impl<'a, E: ScalarEngine> Add<&'a LinearCombination> for LinearCombination { type Output = LinearCombination; fn add(mut self, other: &'a LinearCombination) -> LinearCombination { @@ -126,7 +125,7 @@ impl<'a, E: Engine> Add<&'a LinearCombination> for LinearCombination { } } -impl<'a, E: Engine> Sub<&'a LinearCombination> for LinearCombination { +impl<'a, E: ScalarEngine> Sub<&'a LinearCombination> for LinearCombination { type Output = LinearCombination; fn sub(mut self, other: &'a LinearCombination) -> LinearCombination { @@ -138,7 +137,7 @@ impl<'a, E: Engine> Sub<&'a LinearCombination> for LinearCombination { } } -impl<'a, E: Engine> Add<(E::Fr, &'a LinearCombination)> for LinearCombination { +impl<'a, E: ScalarEngine> Add<(E::Fr, &'a LinearCombination)> for LinearCombination { type Output = LinearCombination; fn add(mut self, (coeff, other): (E::Fr, &'a LinearCombination)) -> LinearCombination { @@ -152,7 +151,7 @@ impl<'a, E: Engine> Add<(E::Fr, &'a LinearCombination)> for LinearCombination } } -impl<'a, E: Engine> Sub<(E::Fr, &'a LinearCombination)> for LinearCombination { +impl<'a, E: ScalarEngine> Sub<(E::Fr, &'a LinearCombination)> for LinearCombination { type Output = LinearCombination; fn sub(mut self, (coeff, other): (E::Fr, &'a LinearCombination)) -> LinearCombination { @@ -222,7 +221,7 @@ impl fmt::Display for SynthesisError { /// Represents a constraint system which can have new variables /// allocated and constrains between them formed. -pub trait ConstraintSystem: Sized { +pub trait ConstraintSystem: Sized { /// Represents the type of the "root" of this constraint system /// so that nested namespaces can minimize indirection. type Root: ConstraintSystem; @@ -294,9 +293,9 @@ pub trait ConstraintSystem: Sized { /// This is a "namespaced" constraint system which borrows a constraint system (pushing /// a namespace context) and, when dropped, pops out of the namespace context. -pub struct Namespace<'a, E: Engine, CS: ConstraintSystem + 'a>(&'a mut CS, PhantomData); +pub struct Namespace<'a, E: ScalarEngine, CS: ConstraintSystem + 'a>(&'a mut CS, PhantomData); -impl<'cs, E: Engine, CS: ConstraintSystem> ConstraintSystem for Namespace<'cs, E, CS> { +impl<'cs, E: ScalarEngine, CS: ConstraintSystem> ConstraintSystem for Namespace<'cs, E, CS> { type Root = CS::Root; fn one() -> Variable { @@ -359,7 +358,7 @@ impl<'cs, E: Engine, CS: ConstraintSystem> ConstraintSystem for Namespace< } } -impl<'a, E: Engine, CS: ConstraintSystem> Drop for Namespace<'a, E, CS> { +impl<'a, E: ScalarEngine, CS: ConstraintSystem> Drop for Namespace<'a, E, CS> { fn drop(&mut self) { self.get_root().pop_namespace() } @@ -367,7 +366,7 @@ impl<'a, E: Engine, CS: ConstraintSystem> Drop for Namespace<'a, E, CS> { /// Convenience implementation of ConstraintSystem for mutable references to /// constraint systems. -impl<'cs, E: Engine, CS: ConstraintSystem> ConstraintSystem for &'cs mut CS { +impl<'cs, E: ScalarEngine, CS: ConstraintSystem> ConstraintSystem for &'cs mut CS { type Root = CS::Root; fn one() -> Variable { From 4272cfa5b0dceac471bef115955e1534be84a018 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 6 Jul 2018 21:51:22 +0100 Subject: [PATCH 52/60] =?UTF-8?q?Make=20pairing=20and=20groth16=20optional?= =?UTF-8?q?=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 9 ++++++++- src/domain.rs | 3 +++ src/lib.rs | 2 ++ src/multiexp.rs | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 8abf83e..3a77fea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,13 @@ byteorder = "1" [dependencies.pairing] git = "https://github.com/str4d/pairing" rev = "3d41ee5abaa4888ff3607689aba007be8856816d" +optional = true [features] -default = [] +groth16 = ["pairing"] +default = ["groth16"] + +[[test]] +name = "mimc" +path = "tests/mimc.rs" +required-features = ["groth16"] diff --git a/src/domain.rs b/src/domain.rs index 87a8240..4606ce5 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -371,6 +371,7 @@ fn parallel_fft>( // Test multiplying various (low degree) polynomials together and // comparing with naive evaluations. +#[cfg(feature = "pairing")] #[test] fn polynomial_arith() { use pairing::bls12_381::Bls12; @@ -418,6 +419,7 @@ fn polynomial_arith() { test_mul::(rng); } +#[cfg(feature = "pairing")] #[test] fn fft_composition() { use pairing::bls12_381::Bls12; @@ -456,6 +458,7 @@ fn fft_composition() { test_comp::(rng); } +#[cfg(feature = "pairing")] #[test] fn parallel_fft_consistency() { use pairing::bls12_381::Bls12; diff --git a/src/lib.rs b/src/lib.rs index 42eccea..f6d7163 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ extern crate ff; extern crate group; +#[cfg(feature = "pairing")] extern crate pairing; extern crate rand; extern crate num_cpus; @@ -12,6 +13,7 @@ extern crate byteorder; pub mod multicore; mod multiexp; pub mod domain; +#[cfg(feature = "groth16")] pub mod groth16; use ff::{Field, ScalarEngine}; diff --git a/src/multiexp.rs b/src/multiexp.rs index cea13f3..d24572b 100644 --- a/src/multiexp.rs +++ b/src/multiexp.rs @@ -255,6 +255,7 @@ pub fn multiexp( multiexp_inner(pool, bases, density_map, exponents, 0, c, true) } +#[cfg(feature = "pairing")] #[test] fn test_with_bls12() { fn naive_multiexp( From 9f7e5fa3ced0c104188bed497eb1c480107722bd Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 10 Nov 2018 00:31:14 +1300 Subject: [PATCH 53/60] Dependency updates after pairing update --- Cargo.lock | 366 +++----------------------------------- sapling-crypto/Cargo.toml | 4 - 2 files changed, 21 insertions(+), 349 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c5ab7fc..e9452e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,22 +28,6 @@ dependencies = [ "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "aho-corasick" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "arrayvec" version = "0.4.7" @@ -52,27 +36,6 @@ dependencies = [ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "backtrace" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "bellman" version = "0.1.0" @@ -92,11 +55,6 @@ name = "bit-vec" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "1.0.1" @@ -130,61 +88,6 @@ name = "byteorder" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "cargo_metadata" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cc" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cfg-if" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "clippy" -version = "0.0.200" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy_lints 0.0.200 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clippy_lints" -version = "0.0.200" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "constant_time_eq" version = "0.1.3" @@ -204,16 +107,26 @@ dependencies = [ ] [[package]] -name = "either" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "error-chain" -version = "0.11.0" +name = "ff" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ff_derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ff_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -269,14 +182,6 @@ dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "getopts" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "hex-literal" version = "0.1.1" @@ -294,34 +199,6 @@ dependencies = [ "proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "if_chain" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "itertools" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itoa" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "lazy_static" version = "1.0.0" @@ -348,19 +225,6 @@ dependencies = [ "zip32 0.0.0", ] -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nodrop" version = "0.1.12" @@ -406,15 +270,10 @@ name = "pairing" version = "0.14.2" dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.200 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "proc-macro-hack" version = "0.4.0" @@ -436,20 +295,6 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "pulldown-cmark" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quine-mc_cluskey" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "quote" version = "0.6.8" @@ -483,26 +328,6 @@ name = "redox_syscall" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "regex" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rust-crypto" version = "0.2.36" @@ -515,29 +340,11 @@ dependencies = [ "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rustc-demangle" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ryu" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "sapling-crypto" version = "0.0.1" @@ -552,45 +359,6 @@ dependencies = [ "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde_derive" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "stream-cipher" version = "0.1.1" @@ -609,14 +377,6 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread_local" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "time" version = "0.1.40" @@ -627,62 +387,16 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "toml" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "ucd-util" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-width" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "url" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "utf8-ranges" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi" version = "0.3.4" @@ -746,28 +460,18 @@ dependencies = [ "checksum aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6fb1737cdc8da3db76e90ca817a194249a38fcb500c2e6ecec39b29448aa873" "checksum aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67cc03b0a090a05cb01e96998a01905d7ceedce1bc23b756c0bb7faa0682ccb1" "checksum aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6810b7fb9f2bb4f76f05ac1c170b8dde285b6308955dc3afd89710268c958d9e" -"checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" -"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)" = "" "checksum block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "370424437b9459f3dfd68428ed9376ddfe03d8b70ede29cc533b3557df186ab4" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" -"checksum cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1efca0b863ca03ed4c109fb1c55e0bc4bbeb221d3e103d86251046b06a526bd0" -"checksum cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4a6007c146fdd28d4512a794b07ffe9d8e89e6bf86e2e0c4ddff2e1fb54a0007" -"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" -"checksum clippy 0.0.200 (registry+https://github.com/rust-lang/crates.io-index)" = "927a1f79af10deb103df108347f23c6b7fa1731c953d6fb24d68be1748a0993f" -"checksum clippy_lints 0.0.200 (registry+https://github.com/rust-lang/crates.io-index)" = "d2432663f6bdb90255dcf9df5ca504f99b575bb471281591138f62f9d31f863b" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "00a49051fef47a72c9623101b19bd71924a45cca838826caae3eaa4d00772603" -"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" -"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eec81e2e423086589b224dbcfbab70e3732913de25479d05165b20d4aaed05f4" +"checksum ff_derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70335090ee115d5716416ca38980cce7752f40923f41d22cf5a69a6269f9e2a2" "checksum fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3371c82bfbd984f624cab093f55e7336f5a6e589f8518e1258f54f011b89ad" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" @@ -775,58 +479,30 @@ dependencies = [ "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" -"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" "checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec" -"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" -"checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3eceac7784c5dc97c2d6edf30259b4e153e6e2b42b3c85e9a6e9f45d06caef6e" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" "checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892" "checksum proc-macro2 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b331c6ad3411474cd55540398dc7ad89fc41488e64ec71fdecc9c9b86de96fb0" -"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" -"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" -"checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" -"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "22d340507cea0b7e6632900a176101fea959c7065d93ba555072da90aaaafc87" -"checksum serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "234fc8b737737b148ccd625175fc6390f5e4dacfdaa543cb93a3430d984a9119" -"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae" "checksum stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30dc6118470d69ce0fdcf7e6f95e95853f7f4f72f80d835d4519577c323814ab" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" -"checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" -"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" -"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/sapling-crypto/Cargo.toml b/sapling-crypto/Cargo.toml index 6e802f2..393c01f 100644 --- a/sapling-crypto/Cargo.toml +++ b/sapling-crypto/Cargo.toml @@ -25,7 +25,3 @@ rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" [dev-dependencies] hex-literal = "0.1" rust-crypto = "0.2" - -[features] -default = ["u128-support"] -u128-support = ["pairing/u128-support"] From 88746e76fa95a71d41c22f49a5e85dd7a91829cb Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 11 Nov 2018 10:35:06 +1300 Subject: [PATCH 54/60] Cargo.lock changes after pairing update --- Cargo.lock | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index e9452e1..2b448b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -182,6 +182,15 @@ dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "group" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hex-literal" version = "0.1.1" @@ -271,6 +280,7 @@ version = "0.14.2" dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "group 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -479,6 +489,7 @@ dependencies = [ "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" +"checksum group 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5fa874cb11ddaf7cf45b511138f24169985d61d8760779426016230d11101d1a" "checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" From 22ccd1bceb7d1f4051757352560963cef16b2e93 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 11 Nov 2018 10:52:08 +1300 Subject: [PATCH 55/60] Update sapling-crypto crate to use ff crate --- Cargo.lock | 1 + sapling-crypto/Cargo.toml | 1 + sapling-crypto/src/circuit/boolean.rs | 10 +++------- sapling-crypto/src/circuit/ecc.rs | 8 +++----- sapling-crypto/src/circuit/lookup.rs | 4 +++- sapling-crypto/src/circuit/multieq.rs | 7 ++----- sapling-crypto/src/circuit/multipack.rs | 3 ++- sapling-crypto/src/circuit/num.rs | 11 +++-------- sapling-crypto/src/circuit/pedersen_hash.rs | 2 +- sapling-crypto/src/circuit/sapling/mod.rs | 10 +++------- sapling-crypto/src/circuit/sprout/mod.rs | 3 ++- sapling-crypto/src/circuit/test/mod.rs | 10 +++------- sapling-crypto/src/circuit/uint32.rs | 9 +++------ sapling-crypto/src/group_hash.rs | 2 +- sapling-crypto/src/jubjub/edwards.rs | 8 +------- sapling-crypto/src/jubjub/fs.rs | 8 +++++--- sapling-crypto/src/jubjub/mod.rs | 8 ++------ sapling-crypto/src/jubjub/montgomery.rs | 8 +------- sapling-crypto/src/jubjub/tests.rs | 2 +- sapling-crypto/src/lib.rs | 1 + sapling-crypto/src/pedersen_hash.rs | 2 +- sapling-crypto/src/primitives/mod.rs | 6 +----- sapling-crypto/src/redjubjub.rs | 2 +- 23 files changed, 45 insertions(+), 81 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c477d52..fa0511c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -365,6 +365,7 @@ dependencies = [ "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/sapling-crypto/Cargo.toml b/sapling-crypto/Cargo.toml index 393c01f..626919f 100644 --- a/sapling-crypto/Cargo.toml +++ b/sapling-crypto/Cargo.toml @@ -14,6 +14,7 @@ features = ["expose-arith"] [dependencies] bellman = { path = "../bellman" } +ff = "0.4" rand = "0.4" digest = "0.7" byteorder = "1" diff --git a/sapling-crypto/src/circuit/boolean.rs b/sapling-crypto/src/circuit/boolean.rs index 08f407e..2fe6ef1 100644 --- a/sapling-crypto/src/circuit/boolean.rs +++ b/sapling-crypto/src/circuit/boolean.rs @@ -1,9 +1,5 @@ -use pairing::{ - Engine, - Field, - PrimeField, - BitIterator -}; +use ff::{BitIterator, Field, PrimeField}; +use pairing::Engine; use bellman::{ ConstraintSystem, @@ -806,8 +802,8 @@ impl From for Boolean { #[cfg(test)] mod test { use bellman::{ConstraintSystem}; + use ff::{Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; - use pairing::{Field, PrimeField}; use ::circuit::test::*; use super::{ AllocatedBit, diff --git a/sapling-crypto/src/circuit/ecc.rs b/sapling-crypto/src/circuit/ecc.rs index 71f1caa..1071649 100644 --- a/sapling-crypto/src/circuit/ecc.rs +++ b/sapling-crypto/src/circuit/ecc.rs @@ -1,7 +1,5 @@ -use pairing::{ - Engine, - Field -}; +use ff::Field; +use pairing::Engine; use bellman::{ SynthesisError, @@ -751,8 +749,8 @@ impl MontgomeryPoint { mod test { use bellman::{ConstraintSystem}; use rand::{XorShiftRng, SeedableRng, Rand, Rng}; + use ff::{BitIterator, Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; - use pairing::{BitIterator, Field, PrimeField}; use ::circuit::test::*; use ::jubjub::{ montgomery, diff --git a/sapling-crypto/src/circuit/lookup.rs b/sapling-crypto/src/circuit/lookup.rs index 1ffc7f7..272f5f6 100644 --- a/sapling-crypto/src/circuit/lookup.rs +++ b/sapling-crypto/src/circuit/lookup.rs @@ -1,4 +1,6 @@ -use pairing::{Engine, Field}; +use ff::Field; +use pairing::Engine; + use super::*; use super::num::{ AllocatedNum, diff --git a/sapling-crypto/src/circuit/multieq.rs b/sapling-crypto/src/circuit/multieq.rs index 0f9c755..4cfc3b8 100644 --- a/sapling-crypto/src/circuit/multieq.rs +++ b/sapling-crypto/src/circuit/multieq.rs @@ -1,8 +1,5 @@ -use pairing::{ - Engine, - Field, - PrimeField -}; +use ff::{Field, PrimeField}; +use pairing::Engine; use bellman::{ SynthesisError, diff --git a/sapling-crypto/src/circuit/multipack.rs b/sapling-crypto/src/circuit/multipack.rs index 54d4138..bf1b046 100644 --- a/sapling-crypto/src/circuit/multipack.rs +++ b/sapling-crypto/src/circuit/multipack.rs @@ -1,4 +1,5 @@ -use pairing::{Engine, Field, PrimeField}; +use ff::{Field, PrimeField}; +use pairing::Engine; use bellman::{ConstraintSystem, SynthesisError}; use super::boolean::{Boolean}; use super::num::Num; diff --git a/sapling-crypto/src/circuit/num.rs b/sapling-crypto/src/circuit/num.rs index 53a2f6c..919d921 100644 --- a/sapling-crypto/src/circuit/num.rs +++ b/sapling-crypto/src/circuit/num.rs @@ -1,10 +1,5 @@ -use pairing::{ - Engine, - Field, - PrimeField, - PrimeFieldRepr, - BitIterator -}; +use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr}; +use pairing::Engine; use bellman::{ SynthesisError, @@ -462,8 +457,8 @@ impl Num { mod test { use rand::{SeedableRng, Rand, Rng, XorShiftRng}; use bellman::{ConstraintSystem}; + use ff::{BitIterator, Field, PrimeField}; use pairing::bls12_381::{Bls12, Fr}; - use pairing::{Field, PrimeField, BitIterator}; use ::circuit::test::*; use super::{AllocatedNum, Boolean}; diff --git a/sapling-crypto/src/circuit/pedersen_hash.rs b/sapling-crypto/src/circuit/pedersen_hash.rs index eb1745f..297a0e0 100644 --- a/sapling-crypto/src/circuit/pedersen_hash.rs +++ b/sapling-crypto/src/circuit/pedersen_hash.rs @@ -116,8 +116,8 @@ mod test { use super::*; use ::circuit::test::*; use ::circuit::boolean::{Boolean, AllocatedBit}; + use ff::PrimeField; use pairing::bls12_381::{Bls12, Fr}; - use pairing::PrimeField; #[test] fn test_pedersen_hash_constraints() { diff --git a/sapling-crypto/src/circuit/sapling/mod.rs b/sapling-crypto/src/circuit/sapling/mod.rs index 650e162..e84b94a 100644 --- a/sapling-crypto/src/circuit/sapling/mod.rs +++ b/sapling-crypto/src/circuit/sapling/mod.rs @@ -1,8 +1,4 @@ -use pairing::{ - PrimeField, - PrimeFieldRepr, - Field, -}; +use ff::{Field, PrimeField, PrimeFieldRepr}; use bellman::{ SynthesisError, @@ -602,7 +598,7 @@ impl<'a, E: JubjubEngine> Circuit for Output<'a, E> { #[test] fn test_input_circuit_with_bls12_381() { - use pairing::{Field, BitIterator}; + use ff::{BitIterator, Field}; use pairing::bls12_381::*; use rand::{SeedableRng, Rng, XorShiftRng}; use ::circuit::test::*; @@ -734,7 +730,7 @@ fn test_input_circuit_with_bls12_381() { #[test] fn test_output_circuit_with_bls12_381() { - use pairing::{Field}; + use ff::Field; use pairing::bls12_381::*; use rand::{SeedableRng, Rng, XorShiftRng}; use ::circuit::test::*; diff --git a/sapling-crypto/src/circuit/sprout/mod.rs b/sapling-crypto/src/circuit/sprout/mod.rs index 586de8c..7027b4a 100644 --- a/sapling-crypto/src/circuit/sprout/mod.rs +++ b/sapling-crypto/src/circuit/sprout/mod.rs @@ -1,4 +1,5 @@ -use pairing::{Engine, Field}; +use ff::Field; +use pairing::Engine; use bellman::{ConstraintSystem, SynthesisError, Circuit, LinearCombination}; use circuit::boolean::{ AllocatedBit, diff --git a/sapling-crypto/src/circuit/test/mod.rs b/sapling-crypto/src/circuit/test/mod.rs index 12fe0ca..18a77ba 100644 --- a/sapling-crypto/src/circuit/test/mod.rs +++ b/sapling-crypto/src/circuit/test/mod.rs @@ -1,9 +1,5 @@ -use pairing::{ - Engine, - Field, - PrimeField, - PrimeFieldRepr -}; +use ff::{Field, PrimeField, PrimeFieldRepr}; +use pairing::Engine; use bellman::{ LinearCombination, @@ -445,8 +441,8 @@ impl ConstraintSystem for TestConstraintSystem { #[test] fn test_cs() { + use ff::PrimeField; use pairing::bls12_381::{Bls12, Fr}; - use pairing::PrimeField; let mut cs = TestConstraintSystem::::new(); assert!(cs.is_satisfied()); diff --git a/sapling-crypto/src/circuit/uint32.rs b/sapling-crypto/src/circuit/uint32.rs index fb0bfa9..4e66091 100644 --- a/sapling-crypto/src/circuit/uint32.rs +++ b/sapling-crypto/src/circuit/uint32.rs @@ -1,8 +1,5 @@ -use pairing::{ - Engine, - Field, - PrimeField -}; +use ff::{Field, PrimeField}; +use pairing::Engine; use bellman::{ SynthesisError, @@ -415,8 +412,8 @@ mod test { use rand::{XorShiftRng, SeedableRng, Rng}; use ::circuit::boolean::{Boolean}; use super::{UInt32}; + use ff::Field; use pairing::bls12_381::{Bls12}; - use pairing::{Field}; use ::circuit::test::*; use bellman::{ConstraintSystem}; use circuit::multieq::MultiEq; diff --git a/sapling-crypto/src/group_hash.rs b/sapling-crypto/src/group_hash.rs index 25e65f9..43e87e8 100644 --- a/sapling-crypto/src/group_hash.rs +++ b/sapling-crypto/src/group_hash.rs @@ -4,7 +4,7 @@ use jubjub::{ edwards }; -use pairing::{ +use ff::{ PrimeField }; diff --git a/sapling-crypto/src/jubjub/edwards.rs b/sapling-crypto/src/jubjub/edwards.rs index e91455c..49018fe 100644 --- a/sapling-crypto/src/jubjub/edwards.rs +++ b/sapling-crypto/src/jubjub/edwards.rs @@ -1,10 +1,4 @@ -use pairing::{ - Field, - SqrtField, - PrimeField, - PrimeFieldRepr, - BitIterator -}; +use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; use super::{ JubjubEngine, diff --git a/sapling-crypto/src/jubjub/fs.rs b/sapling-crypto/src/jubjub/fs.rs index eb10e65..6a51573 100644 --- a/sapling-crypto/src/jubjub/fs.rs +++ b/sapling-crypto/src/jubjub/fs.rs @@ -1,7 +1,9 @@ use byteorder::{ByteOrder, LittleEndian}; -use pairing::{BitIterator, Field, PrimeField, SqrtField, PrimeFieldRepr, PrimeFieldDecodingError, LegendreSymbol}; -use pairing::LegendreSymbol::*; -use pairing::{adc, sbb, mac_with_carry}; +use ff::{ + adc, mac_with_carry, sbb, BitIterator, Field, + LegendreSymbol::{self, *}, + PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField, +}; use super::ToUniform; diff --git a/sapling-crypto/src/jubjub/mod.rs b/sapling-crypto/src/jubjub/mod.rs index 51a000a..e46fac5 100644 --- a/sapling-crypto/src/jubjub/mod.rs +++ b/sapling-crypto/src/jubjub/mod.rs @@ -17,12 +17,8 @@ //! the Montgomery curve forms a group isomorphism, allowing points //! to be freely converted between the two forms. -use pairing::{ - Engine, - Field, - PrimeField, - SqrtField -}; +use ff::{Field, PrimeField, SqrtField}; +use pairing::Engine; use group_hash::group_hash; diff --git a/sapling-crypto/src/jubjub/montgomery.rs b/sapling-crypto/src/jubjub/montgomery.rs index 18d0fcb..76203eb 100644 --- a/sapling-crypto/src/jubjub/montgomery.rs +++ b/sapling-crypto/src/jubjub/montgomery.rs @@ -1,10 +1,4 @@ -use pairing::{ - Field, - SqrtField, - PrimeField, - PrimeFieldRepr, - BitIterator -}; +use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; use super::{ JubjubEngine, diff --git a/sapling-crypto/src/jubjub/tests.rs b/sapling-crypto/src/jubjub/tests.rs index 421a8f7..eb7e36b 100644 --- a/sapling-crypto/src/jubjub/tests.rs +++ b/sapling-crypto/src/jubjub/tests.rs @@ -6,7 +6,7 @@ use super::{ edwards }; -use pairing::{ +use ff::{ Field, PrimeField, PrimeFieldRepr, diff --git a/sapling-crypto/src/lib.rs b/sapling-crypto/src/lib.rs index 27d306c..ae37573 100644 --- a/sapling-crypto/src/lib.rs +++ b/sapling-crypto/src/lib.rs @@ -2,6 +2,7 @@ extern crate pairing; extern crate bellman; extern crate blake2_rfc; extern crate digest; +extern crate ff; extern crate rand; extern crate byteorder; diff --git a/sapling-crypto/src/pedersen_hash.rs b/sapling-crypto/src/pedersen_hash.rs index 0590a5c..aacca37 100644 --- a/sapling-crypto/src/pedersen_hash.rs +++ b/sapling-crypto/src/pedersen_hash.rs @@ -1,5 +1,5 @@ +use ff::{Field, PrimeField, PrimeFieldRepr}; use jubjub::*; -use pairing::*; #[derive(Copy, Clone)] pub enum Personalization { diff --git a/sapling-crypto/src/primitives/mod.rs b/sapling-crypto/src/primitives/mod.rs index 26dafab..849aaf2 100644 --- a/sapling-crypto/src/primitives/mod.rs +++ b/sapling-crypto/src/primitives/mod.rs @@ -1,8 +1,4 @@ -use pairing::{ - Field, - PrimeField, - PrimeFieldRepr -}; +use ff::{Field, PrimeField, PrimeFieldRepr}; use constants; diff --git a/sapling-crypto/src/redjubjub.rs b/sapling-crypto/src/redjubjub.rs index dfae28c..e159179 100644 --- a/sapling-crypto/src/redjubjub.rs +++ b/sapling-crypto/src/redjubjub.rs @@ -1,7 +1,7 @@ //! Implementation of RedJubjub, a specialization of RedDSA to the Jubjub curve. //! See section 5.4.6 of the Sapling protocol specification. -use pairing::{Field, PrimeField, PrimeFieldRepr}; +use ff::{Field, PrimeField, PrimeFieldRepr}; use rand::{Rng, Rand}; use std::io::{self, Read, Write}; From 2e408957db69de8ea752b8cea5b559237846a634 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 11 Nov 2018 10:54:08 +1300 Subject: [PATCH 56/60] Update zip32 crate to use ff crate --- Cargo.lock | 1 + zip32/Cargo.toml | 1 + zip32/src/lib.rs | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index fa0511c..3715c7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -463,6 +463,7 @@ dependencies = [ "aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", diff --git a/zip32/Cargo.toml b/zip32/Cargo.toml index 031d636..49ae186 100644 --- a/zip32/Cargo.toml +++ b/zip32/Cargo.toml @@ -14,6 +14,7 @@ repository = "https://github.com/zcash-hackworks/zip32" [dependencies] aes = "0.2" byteorder = "1" +ff = "0.4" fpe = "0.1" lazy_static = "1.0" pairing = { path = "../pairing" } diff --git a/zip32/src/lib.rs b/zip32/src/lib.rs index 5b322db..f26ccad 100644 --- a/zip32/src/lib.rs +++ b/zip32/src/lib.rs @@ -1,6 +1,7 @@ extern crate aes; extern crate blake2_rfc; extern crate byteorder; +extern crate ff; extern crate fpe; #[macro_use] extern crate lazy_static; @@ -10,8 +11,9 @@ extern crate sapling_crypto; use aes::Aes256; use blake2_rfc::blake2b::{Blake2b, Blake2bResult}; use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt}; +use ff::{Field, PrimeField, PrimeFieldRepr}; use fpe::ff1::{BinaryNumeralString, FF1}; -use pairing::{bls12_381::Bls12, Field, PrimeField, PrimeFieldRepr}; +use pairing::bls12_381::Bls12; use sapling_crypto::{ jubjub::{ edwards, FixedGenerators, JubjubBls12, JubjubEngine, JubjubParams, ToUniform, Unknown, From 538de482f32ab3a687042fef4cb7cd554cdd9f78 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 6 Jan 2019 09:31:20 +0000 Subject: [PATCH 57/60] Update zcash_primitives crate to use ff crate --- Cargo.lock | 1 + zcash_primitives/Cargo.toml | 1 + zcash_primitives/src/lib.rs | 1 + zcash_primitives/src/transaction/components.rs | 6 ++---- zcash_primitives/src/transaction/sighash.rs | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3715c7f..28ddb78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -435,6 +435,7 @@ version = "0.0.0" dependencies = [ "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index bf6c03f..ac03334 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -7,6 +7,7 @@ authors = [ [dependencies] byteorder = "1" +ff = "0.4" lazy_static = "1" pairing = { path = "../pairing" } rand = "0.4" diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index 5f4dd05..6a84cc3 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -3,6 +3,7 @@ extern crate lazy_static; extern crate blake2_rfc; extern crate byteorder; +extern crate ff; extern crate pairing; extern crate rand; extern crate sapling_crypto; diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index 21dbd46..39b468d 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -1,8 +1,6 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use pairing::{ - bls12_381::{Bls12, Fr, FrRepr}, - PrimeField, PrimeFieldRepr, -}; +use ff::{PrimeField, PrimeFieldRepr}; +use pairing::bls12_381::{Bls12, Fr, FrRepr}; use sapling_crypto::{ jubjub::{edwards, Unknown}, redjubjub::{PublicKey, Signature}, diff --git a/zcash_primitives/src/transaction/sighash.rs b/zcash_primitives/src/transaction/sighash.rs index e5dcde0..85302ee 100644 --- a/zcash_primitives/src/transaction/sighash.rs +++ b/zcash_primitives/src/transaction/sighash.rs @@ -1,6 +1,6 @@ use blake2_rfc::blake2b::Blake2b; use byteorder::{LittleEndian, WriteBytesExt}; -use pairing::{PrimeField, PrimeFieldRepr}; +use ff::{PrimeField, PrimeFieldRepr}; use super::{ components::{Amount, Script, TxOut}, From 00983c48cddd69211d1387e0e5df55b1284de158 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 6 Jan 2019 09:32:50 +0000 Subject: [PATCH 58/60] Update zcash_proofs crate to use ff crate --- Cargo.lock | 1 + zcash_proofs/Cargo.toml | 1 + zcash_proofs/src/lib.rs | 1 + zcash_proofs/src/sapling/prover.rs | 6 ++---- zcash_proofs/src/sapling/verifier.rs | 6 ++---- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28ddb78..ed73746 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -448,6 +448,7 @@ version = "0.0.0" dependencies = [ "bellman 0.1.0", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index 68a4a45..88cc5fb 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -8,6 +8,7 @@ authors = [ [dependencies] bellman = { path = "../bellman" } byteorder = "1" +ff = "0.4" pairing = { path = "../pairing" } rand = "0.4" sapling-crypto = { path = "../sapling-crypto" } diff --git a/zcash_proofs/src/lib.rs b/zcash_proofs/src/lib.rs index bdebdd6..55ae761 100644 --- a/zcash_proofs/src/lib.rs +++ b/zcash_proofs/src/lib.rs @@ -1,5 +1,6 @@ extern crate bellman; extern crate byteorder; +extern crate ff; extern crate pairing; extern crate rand; extern crate sapling_crypto; diff --git a/zcash_proofs/src/sapling/prover.rs b/zcash_proofs/src/sapling/prover.rs index f43dae7..3a3511c 100644 --- a/zcash_proofs/src/sapling/prover.rs +++ b/zcash_proofs/src/sapling/prover.rs @@ -2,10 +2,8 @@ use bellman::groth16::{ create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof, }; use byteorder::{LittleEndian, ReadBytesExt}; -use pairing::{ - bls12_381::{Bls12, Fr, FrRepr}, - Field, PrimeField, PrimeFieldRepr, -}; +use ff::{Field, PrimeField, PrimeFieldRepr}; +use pairing::bls12_381::{Bls12, Fr, FrRepr}; use rand::{OsRng, Rand}; use sapling_crypto::{ circuit::{ diff --git a/zcash_proofs/src/sapling/verifier.rs b/zcash_proofs/src/sapling/verifier.rs index e9a5f2f..e83c426 100644 --- a/zcash_proofs/src/sapling/verifier.rs +++ b/zcash_proofs/src/sapling/verifier.rs @@ -1,8 +1,6 @@ use bellman::groth16::{verify_proof, PreparedVerifyingKey, Proof}; -use pairing::{ - bls12_381::{Bls12, Fr}, - Field, -}; +use ff::Field; +use pairing::bls12_381::{Bls12, Fr}; use sapling_crypto::{ circuit::multipack, jubjub::{edwards, FixedGenerators, JubjubBls12, Unknown}, From 07955092f335cb28ca4fe0a7cb0fb5f3bf2198cb Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 3 Jan 2019 22:05:06 +0000 Subject: [PATCH 59/60] Update librustzcash crate to use ff crate --- Cargo.lock | 1 + librustzcash/Cargo.toml | 1 + librustzcash/src/rustzcash.rs | 7 +++---- librustzcash/src/tests/key_agreement.rs | 2 +- librustzcash/src/tests/key_components.rs | 3 ++- librustzcash/src/tests/signatures.rs | 3 ++- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed73746..4ad85ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,6 +227,7 @@ dependencies = [ "bellman 0.1.0", "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", diff --git a/librustzcash/Cargo.toml b/librustzcash/Cargo.toml index bb42b6c..7476fdd 100644 --- a/librustzcash/Cargo.toml +++ b/librustzcash/Cargo.toml @@ -15,6 +15,7 @@ crate-type = ["staticlib"] [dependencies] bellman = { path = "../bellman" } +ff = "0.4" libc = "0.2" pairing = { path = "../pairing" } lazy_static = "1" diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index b77b6b2..f264690 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -1,6 +1,7 @@ extern crate bellman; extern crate blake2_rfc; extern crate byteorder; +extern crate ff; extern crate libc; extern crate pairing; extern crate rand; @@ -13,10 +14,8 @@ mod hashreader; #[macro_use] extern crate lazy_static; -use pairing::{ - bls12_381::{Bls12, Fr, FrRepr}, - BitIterator, PrimeField, PrimeFieldRepr, -}; +use ff::{BitIterator, PrimeField, PrimeFieldRepr}; +use pairing::bls12_381::{Bls12, Fr, FrRepr}; use sapling_crypto::{ circuit::multipack, diff --git a/librustzcash/src/tests/key_agreement.rs b/librustzcash/src/tests/key_agreement.rs index 01657d1..a72abf0 100644 --- a/librustzcash/src/tests/key_agreement.rs +++ b/librustzcash/src/tests/key_agreement.rs @@ -1,5 +1,5 @@ +use ff::{PrimeField, PrimeFieldRepr}; use pairing::bls12_381::Bls12; -use pairing::{PrimeField, PrimeFieldRepr}; use rand::{OsRng, Rng}; use sapling_crypto::jubjub::{edwards, JubjubBls12}; use sapling_crypto::primitives::{Diversifier, ViewingKey}; diff --git a/librustzcash/src/tests/key_components.rs b/librustzcash/src/tests/key_components.rs index d63c4d4..90c08eb 100644 --- a/librustzcash/src/tests/key_components.rs +++ b/librustzcash/src/tests/key_components.rs @@ -1,4 +1,5 @@ -use pairing::{bls12_381::Bls12, PrimeField, PrimeFieldRepr}; +use ff::{PrimeField, PrimeFieldRepr}; +use pairing::bls12_381::Bls12; use sapling_crypto::{ jubjub::{fs::FsRepr, FixedGenerators, JubjubEngine, JubjubParams}, primitives::{Diversifier, ProofGenerationKey}, diff --git a/librustzcash/src/tests/signatures.rs b/librustzcash/src/tests/signatures.rs index 23fc75b..2b28437 100644 --- a/librustzcash/src/tests/signatures.rs +++ b/librustzcash/src/tests/signatures.rs @@ -1,4 +1,5 @@ -use pairing::{bls12_381::Bls12, PrimeField, PrimeFieldRepr}; +use ff::{PrimeField, PrimeFieldRepr}; +use pairing::bls12_381::Bls12; use sapling_crypto::{ jubjub::{FixedGenerators, JubjubEngine}, redjubjub::{PrivateKey, PublicKey, Signature}, From 482bef87f07782f87cc5f60b293699205276173b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 6 Jan 2019 09:50:07 +0000 Subject: [PATCH 60/60] Add ff and group crates to Cargo workspace --- Cargo.lock | 28 +++++++++++----------------- Cargo.toml | 2 ++ bellman/Cargo.toml | 4 ++-- group/Cargo.toml | 2 +- librustzcash/Cargo.toml | 2 +- pairing/Cargo.toml | 4 ++-- pairing/src/lib.rs | 1 - sapling-crypto/Cargo.toml | 2 +- zcash_primitives/Cargo.toml | 2 +- zcash_proofs/Cargo.toml | 2 +- zip32/Cargo.toml | 2 +- 11 files changed, 23 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ad85ce..a754c35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,10 +43,10 @@ dependencies = [ "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "group 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "group 0.1.0", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -111,17 +111,15 @@ dependencies = [ [[package]] name = "ff" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ff_derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff_derive 0.3.0", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ff_derive" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-bigint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -187,9 +185,8 @@ dependencies = [ [[package]] name = "group" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -227,7 +224,7 @@ dependencies = [ "bellman 0.1.0", "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", @@ -282,8 +279,8 @@ name = "pairing" version = "0.14.2" dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "group 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0", + "group 0.1.0", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -366,7 +363,7 @@ dependencies = [ "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -436,7 +433,7 @@ version = "0.0.0" dependencies = [ "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -449,7 +446,7 @@ version = "0.0.0" dependencies = [ "bellman 0.1.0", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0", "pairing 0.14.2", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "sapling-crypto 0.0.1", @@ -466,7 +463,7 @@ dependencies = [ "aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0", "fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", @@ -487,8 +484,6 @@ dependencies = [ "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "00a49051fef47a72c9623101b19bd71924a45cca838826caae3eaa4d00772603" -"checksum ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eec81e2e423086589b224dbcfbab70e3732913de25479d05165b20d4aaed05f4" -"checksum ff_derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70335090ee115d5716416ca38980cce7752f40923f41d22cf5a69a6269f9e2a2" "checksum fpe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3371c82bfbd984f624cab093f55e7336f5a6e589f8518e1258f54f011b89ad" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" @@ -496,7 +491,6 @@ dependencies = [ "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" -"checksum group 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5fa874cb11ddaf7cf45b511138f24169985d61d8760779426016230d11101d1a" "checksum hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4da5f0e01bd8a71a224a4eedecaacfcabda388dbb7a80faf04d3514287572d95" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" diff --git a/Cargo.toml b/Cargo.toml index 3d1363d..f25ea72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,8 @@ [workspace] members = [ "bellman", + "ff", + "group", "librustzcash", "pairing", "sapling-crypto", diff --git a/bellman/Cargo.toml b/bellman/Cargo.toml index 6812a7f..9ba6de4 100644 --- a/bellman/Cargo.toml +++ b/bellman/Cargo.toml @@ -11,10 +11,10 @@ version = "0.1.0" [dependencies] rand = "0.4" bit-vec = "0.4.4" -ff = "0.4" +ff = { path = "../ff" } futures = "0.1" futures-cpupool = "0.1" -group = "0.1" +group = { path = "../group" } num_cpus = "1" crossbeam = "0.3" pairing = { path = "../pairing", optional = true } diff --git a/group/Cargo.toml b/group/Cargo.toml index 92c2870..ad3f84d 100644 --- a/group/Cargo.toml +++ b/group/Cargo.toml @@ -13,5 +13,5 @@ homepage = "https://github.com/ebfull/group" repository = "https://github.com/ebfull/group" [dependencies] -ff = "0.4" +ff = { path = "../ff" } rand = "0.4" diff --git a/librustzcash/Cargo.toml b/librustzcash/Cargo.toml index 7476fdd..c2ab7ff 100644 --- a/librustzcash/Cargo.toml +++ b/librustzcash/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["staticlib"] [dependencies] bellman = { path = "../bellman" } -ff = "0.4" +ff = { path = "../ff" } libc = "0.2" pairing = { path = "../pairing" } lazy_static = "1" diff --git a/pairing/Cargo.toml b/pairing/Cargo.toml index 68971c3..3446f46 100644 --- a/pairing/Cargo.toml +++ b/pairing/Cargo.toml @@ -17,8 +17,8 @@ repository = "https://github.com/ebfull/pairing" [dependencies] rand = "0.4" byteorder = "1" -ff = { version = "0.4", features = ["derive"] } -group = "0.1" +ff = { path = "../ff", features = ["derive"] } +group = { path = "../group" } [features] unstable-features = ["expose-arith"] diff --git a/pairing/src/lib.rs b/pairing/src/lib.rs index adabcce..686938f 100644 --- a/pairing/src/lib.rs +++ b/pairing/src/lib.rs @@ -12,7 +12,6 @@ #![deny(missing_debug_implementations)] extern crate byteorder; -#[macro_use] extern crate ff; extern crate group; extern crate rand; diff --git a/sapling-crypto/Cargo.toml b/sapling-crypto/Cargo.toml index 626919f..d985219 100644 --- a/sapling-crypto/Cargo.toml +++ b/sapling-crypto/Cargo.toml @@ -14,7 +14,7 @@ features = ["expose-arith"] [dependencies] bellman = { path = "../bellman" } -ff = "0.4" +ff = { path = "../ff" } rand = "0.4" digest = "0.7" byteorder = "1" diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index ac03334..01e5243 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -7,7 +7,7 @@ authors = [ [dependencies] byteorder = "1" -ff = "0.4" +ff = { path = "../ff" } lazy_static = "1" pairing = { path = "../pairing" } rand = "0.4" diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index 88cc5fb..ac1fd6b 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -8,7 +8,7 @@ authors = [ [dependencies] bellman = { path = "../bellman" } byteorder = "1" -ff = "0.4" +ff = { path = "../ff" } pairing = { path = "../pairing" } rand = "0.4" sapling-crypto = { path = "../sapling-crypto" } diff --git a/zip32/Cargo.toml b/zip32/Cargo.toml index 49ae186..0cee23d 100644 --- a/zip32/Cargo.toml +++ b/zip32/Cargo.toml @@ -14,7 +14,7 @@ repository = "https://github.com/zcash-hackworks/zip32" [dependencies] aes = "0.2" byteorder = "1" -ff = "0.4" +ff = { path = "../ff" } fpe = "0.1" lazy_static = "1.0" pairing = { path = "../pairing" }