From 635c4cdd560bc0c8b262e6bf809dc709da8bcd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Zieli=C5=84ski?= Date: Tue, 21 Jan 2020 14:44:14 +0100 Subject: [PATCH] Making bn no_std. Exposing miller_loop_batch and final_exponentiation. (#16) --- Cargo.toml | 11 +++++++---- src/arith.rs | 2 +- src/fields/fp.rs | 8 ++++---- src/fields/fq12.rs | 5 ++--- src/fields/fq2.rs | 5 ++--- src/fields/fq6.rs | 2 +- src/fields/mod.rs | 4 ++-- src/groups/mod.rs | 22 +++++++++++----------- src/lib.rs | 31 +++++++++++++++++++++++++------ 9 files changed, 55 insertions(+), 35 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f74738b..f31bcaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,12 +16,15 @@ default = ["rustc-serialize"] name = "api" [dependencies] -rand = { version = "0.5", features = ["i128_support"] } +rand = { version = "0.5", features = ["i128_support"], default-features = false } rustc-serialize = { version = "0.3", optional = true } -byteorder = { version = "1.0", features = ["i128"] } +byteorder = { version = "1.0", features = ["i128"], default-features = false } crunchy = "0.2.1" -lazy_static = "*" -rustc-hex = "2" +lazy_static = { version = "1.4.0", features = ["spin_no_std"] } +rustc-hex = { version = "2", default-features = false } + +[dev-dependencies] +rand = { version = "0.5", features = ["i128_support"] } [dev-dependencies.bincode] version = "0.6" diff --git a/src/arith.rs b/src/arith.rs index ca98e8a..0f47a3c 100644 --- a/src/arith.rs +++ b/src/arith.rs @@ -1,4 +1,4 @@ -use std::cmp::Ordering; +use core::cmp::Ordering; use rand::Rng; #[cfg(feature = "rustc-serialize")] diff --git a/src/fields/fp.rs b/src/fields/fp.rs index ab0d489..f867296 100644 --- a/src/fields/fp.rs +++ b/src/fields/fp.rs @@ -1,12 +1,12 @@ +use alloc::vec::Vec; +use core::ops::{Add, Mul, Neg, Sub}; use rand::Rng; -use std::ops::{Add, Mul, Neg, Sub}; -use super::FieldElement; +use fields::FieldElement; +use arith::{U256, U512}; #[cfg(feature = "rustc-serialize")] use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; -use arith::{U256, U512}; - macro_rules! field_impl { ($name:ident, $modulus:expr, $rsquared:expr, $rcubed:expr, $one:expr, $inv:expr) => { #[derive(Copy, Clone, PartialEq, Eq, Debug)] diff --git a/src/fields/fq12.rs b/src/fields/fq12.rs index d239486..9939fa0 100644 --- a/src/fields/fq12.rs +++ b/src/fields/fq12.rs @@ -1,7 +1,6 @@ -use fields::{const_fq, FieldElement, Fq, Fq2, Fq6}; -use std::ops::{Add, Mul, Neg, Sub}; +use core::ops::{Add, Mul, Neg, Sub}; use rand::Rng; - +use fields::{const_fq, FieldElement, Fq, Fq2, Fq6}; use arith::U256; fn frobenius_coeffs_c1(power: usize) -> Fq2 { diff --git a/src/fields/fq2.rs b/src/fields/fq2.rs index b793cea..3e05a57 100644 --- a/src/fields/fq2.rs +++ b/src/fields/fq2.rs @@ -1,7 +1,6 @@ -use fields::{const_fq, FieldElement, Fq}; -use std::ops::{Add, Mul, Neg, Sub}; +use core::ops::{Add, Mul, Neg, Sub}; use rand::Rng; - +use fields::{const_fq, FieldElement, Fq}; use arith::{U256, U512}; #[cfg(feature = "rustc-serialize")] diff --git a/src/fields/fq6.rs b/src/fields/fq6.rs index b4b1e0c..0d2e597 100644 --- a/src/fields/fq6.rs +++ b/src/fields/fq6.rs @@ -1,5 +1,5 @@ use fields::{const_fq, FieldElement, Fq, Fq2}; -use std::ops::{Add, Mul, Neg, Sub}; +use core::ops::{Add, Mul, Neg, Sub}; use rand::Rng; fn frobenius_coeffs_c1(n: usize) -> Fq2 { diff --git a/src/fields/mod.rs b/src/fields/mod.rs index bd60b3e..071cb28 100644 --- a/src/fields/mod.rs +++ b/src/fields/mod.rs @@ -5,8 +5,8 @@ mod fq12; use arith::U256; use rand::Rng; -use std::ops::{Add, Mul, Neg, Sub}; -use std::fmt::Debug; +use core::ops::{Add, Mul, Neg, Sub}; +use alloc::fmt::Debug; pub use self::fp::{const_fq, Fq, Fr}; pub use self::fq2::{Fq2, fq2_nonresidue}; diff --git a/src/groups/mod.rs b/src/groups/mod.rs index ae2b307..c07d238 100644 --- a/src/groups/mod.rs +++ b/src/groups/mod.rs @@ -1,8 +1,8 @@ -use std::ops::{Add, Mul, Neg, Sub}; use fields::{const_fq, FieldElement, Fq, Fq12, Fq2, Fr, fq2_nonresidue}; use arith::U256; -use std::fmt; +use core::{fmt, ops::{Add, Mul, Neg, Sub}}; use rand::Rng; +use alloc::vec::Vec; #[cfg(feature = "rustc-serialize")] use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -661,7 +661,7 @@ impl G2Precomp { } } -fn miller_loop_batch(g2_precomputes: &Vec, g1_vec: &Vec>) -> Fq12 { +pub fn miller_loop_batch(g2_precomputes: &Vec, g1_vec: &Vec>) -> Fq12 { let mut f = Fq12::one(); let mut idx = 0; @@ -957,8 +957,8 @@ pub fn pairing(p: &G1, q: &G2) -> Fq12 { } pub fn pairing_batch(ps: &[G1], qs: &[G2]) -> Fq12 { - let mut p_affines: Vec> = vec![]; - let mut q_precomputes: Vec = vec![]; + let mut p_affines: Vec> = Vec::new(); + let mut q_precomputes: Vec = Vec::new(); for (p, q) in ps.into_iter().zip(qs.into_iter()) { let p_affine = p.to_affine(); @@ -1088,8 +1088,8 @@ fn predefined_pair() { #[test] fn test_batch_bilinearity_empty() { - let p_vec : Vec = vec![]; - let q_vec : Vec = vec![]; + let p_vec : Vec = Vec::new(); + let q_vec : Vec = Vec::new(); let r = pairing_batch(&p_vec, &q_vec); assert_eq!(r, Fq12::one()); } @@ -1125,10 +1125,10 @@ fn test_batch_bilinearity_fifty() { ]; let mut rng = StdRng::from_seed(seed); - let mut p_vec : Vec = vec![]; - let mut q_vec : Vec = vec![]; - let mut sp_vec : Vec = vec![]; - let mut sq_vec : Vec = vec![]; + let mut p_vec : Vec = Vec::new(); + let mut q_vec : Vec = Vec::new(); + let mut sp_vec : Vec = Vec::new(); + let mut sq_vec : Vec = Vec::new(); for _ in 0..50 { let p = G1::random(&mut rng); diff --git a/src/lib.rs b/src/lib.rs index c2457b4..308973b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,7 @@ +#![no_std] + +#[macro_use] +extern crate alloc; extern crate byteorder; #[macro_use] extern crate crunchy; @@ -13,7 +17,8 @@ mod groups; use fields::FieldElement; use groups::{GroupElement, G1Params, G2Params, GroupParams}; -use std::ops::{Add, Mul, Neg, Sub}; +use alloc::vec::Vec; +use core::ops::{Add, Mul, Neg, Sub}; use rand::Rng; #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -115,6 +120,7 @@ pub enum CurveError { InvalidEncoding, NotMember, Field(FieldError), + ToAffineConversion, } impl From for CurveError { @@ -599,8 +605,11 @@ impl Gt { pub fn pow(&self, exp: Fr) -> Self { Gt(self.0.pow(exp.0)) } - pub fn inverse(&self) -> Self { - Gt(self.0.inverse().unwrap()) + pub fn inverse(&self) -> Option { + self.0.inverse().map(Gt) + } + pub fn final_exponentiation(&self) -> Option { + self.0.final_exponentiation().map(Gt) } } @@ -617,8 +626,8 @@ pub fn pairing(p: G1, q: G2) -> Gt { } pub fn pairing_batch(pairs: &[(G1, G2)]) -> Gt { - let mut ps : Vec = vec![]; - let mut qs : Vec = vec![]; + let mut ps : Vec = Vec::new(); + let mut qs : Vec = Vec::new(); for (p, q) in pairs { ps.push(p.0); qs.push(q.0); @@ -626,6 +635,16 @@ pub fn pairing_batch(pairs: &[(G1, G2)]) -> Gt { Gt(groups::pairing_batch(&ps, &qs)) } +pub fn miller_loop_batch(pairs: &[(G2, G1)]) -> Result { + let mut ps : Vec = Vec::new(); + let mut qs : Vec> = Vec::new(); + for (p, q) in pairs { + ps.push(p.0.to_affine().ok_or(CurveError::ToAffineConversion)?.precompute()); + qs.push(q.0.to_affine().ok_or(CurveError::ToAffineConversion)?); + } + Ok(Gt(groups::miller_loop_batch(&ps, &qs))) +} + #[derive(Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "rustc-serialize", derive(RustcDecodable, RustcEncodable))] #[repr(C)] @@ -666,7 +685,7 @@ impl From for G2 { #[cfg(test)] mod tests { extern crate rustc_hex as hex; - + use alloc::vec::Vec; use super::{G1, Fq, G2, Fq2}; fn hex(s: &'static str) -> Vec {