Merge pull request #170 from tarcieri/alloc-cleanups

Unify `alloc` and `std` cargo features
This commit is contained in:
Henry de Valence 2018-07-23 10:38:26 -07:00 committed by GitHub
commit d6adeb54cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 66 additions and 25 deletions

View file

@ -15,16 +15,18 @@ env:
- TEST_COMMAND=test EXTRA_FLAGS='' FEATURES='serde'
# Tests building without std. We have to select a backend, so we select the one
# most likely to be useful in an embedded environment.
- TEST_COMMAND=build EXTRA_FLAGS=--no-default-features FEATURES='u32_backend'
- TEST_COMMAND=build EXTRA_FLAGS='--no-default-features' FEATURES='u32_backend'
# Tests no_std+alloc usage using the most embedded-friendly backend
- TEST_COMMAND=test EXTRA_FLAGS='--lib --no-default-features' FEATURES='alloc u32_backend'
matrix:
exclude:
# Test the avx2 backend only on nightly
- rust: stable
env: TEST_COMMAND=test EXTRA_FLAGS='--no-default-features' FEATURES='std avx2_backend'
# Test no_std only on nightly.
# Test no_std+alloc only on nightly
- rust: stable
env: TEST_COMMAND=build EXTRA_FLAGS=--no-default-features FEATURES='u32_backend'
env: TEST_COMMAND=test EXTRA_FLAGS='--lib --no-default-features' FEATURES='alloc u32_backend'
script:
- cargo $TEST_COMMAND --features="$FEATURES" $EXTRA_FLAGS

View file

@ -61,7 +61,7 @@ serde = { version = "1.0", optional = true }
[features]
nightly = ["subtle/nightly", "clear_on_drop/nightly"]
default = ["std", "u64_backend"]
std = ["subtle/std", "rand/std"]
std = ["alloc", "subtle/std", "rand/std"]
alloc = []
yolocrypto = []

View file

@ -1,9 +1,12 @@
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
#![cfg_attr(feature = "nightly", feature(cfg_target_feature))]
#![cfg_attr(all(feature = "nightly", feature = "avx2_backend"), feature(stdsimd))]
#![allow(unused_variables)]
#![allow(non_snake_case)]
#![allow(dead_code)]
#[cfg(all(feature = "alloc", not(feature = "std")))]
extern crate alloc;
extern crate byteorder;
extern crate clear_on_drop;
extern crate core;
@ -53,6 +56,8 @@ mod field;
mod curve_models;
#[path = "src/backend/mod.rs"]
mod backend;
#[path = "src/prelude.rs"]
mod prelude;
#[path = "src/scalar_mul/mod.rs"]
mod scalar_mul;

View file

@ -20,6 +20,9 @@ use scalar::Scalar;
use scalar_mul::window::{LookupTable, NafLookupTable5};
use traits::{Identity, MultiscalarMul, VartimeMultiscalarMul};
#[allow(unused_imports)]
use prelude::*;
/// Multiscalar multiplication using interleaved window / Straus'
/// method. See the `Straus` struct in the serial backend for more
/// details.
@ -30,7 +33,7 @@ use traits::{Identity, MultiscalarMul, VartimeMultiscalarMul};
/// point representation on the fly.
pub struct Straus {}
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(feature = "alloc")]
impl MultiscalarMul for Straus {
type Point = EdwardsPoint;
@ -68,7 +71,7 @@ impl MultiscalarMul for Straus {
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(feature = "alloc")]
impl VartimeMultiscalarMul for Straus {
type Point = EdwardsPoint;

View file

@ -21,6 +21,12 @@
//! `32bit` since identifiers can't start with letters, and the backends
//! do use `u32`/`u64`, so this seems like a least-bad option.
#[cfg(not(any(feature = "u32_backend", feature = "u64_backend", feature = "avx2_backend")))]
compile_error!(
"no curve25519-dalek backend cargo feature enabled! \
please enable one of: u32_backend, u64_backend, avx2_backend"
);
#[cfg(feature = "u32_backend")]
pub mod u32;

View file

@ -90,9 +90,6 @@
// affine and projective cakes and eat both of them too.
#![allow(non_snake_case)]
#[cfg(feature = "alloc")]
use alloc::Vec;
use core::fmt::Debug;
use core::iter::Iterator;
use core::ops::{Add, Sub, Neg};
@ -118,6 +115,9 @@ use curve_models::CompletedPoint;
use curve_models::AffineNielsPoint;
use curve_models::ProjectiveNielsPoint;
#[allow(unused_imports)]
use prelude::*;
use scalar_mul::window::LookupTable;
use traits::{Identity, IsIdentity};
@ -526,7 +526,7 @@ impl<'a, 'b> Mul<&'b EdwardsPoint> for &'a Scalar {
// These use the iterator's size hint and the target settings to
// forward to a specific backend implementation.
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(feature = "alloc")]
impl MultiscalarMul for EdwardsPoint {
type Point = EdwardsPoint;
@ -555,7 +555,7 @@ impl MultiscalarMul for EdwardsPoint {
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(feature = "alloc")]
impl VartimeMultiscalarMul for EdwardsPoint {
type Point = EdwardsPoint;

View file

@ -145,7 +145,7 @@ impl FieldElement {
///
/// This function is most efficient when the batch size (slice
/// length) is a power of 2.
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(feature = "alloc")]
pub fn batch_invert(inputs: &mut [FieldElement]) {
// First, compute the product of all inputs using a product
// tree:

View file

@ -8,10 +8,9 @@
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
// - Henry de Valence <hdevalence@hdevalence.ca>
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![no_std]
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
#![cfg_attr(feature = "nightly", feature(cfg_target_feature))]
#![cfg_attr(feature = "nightly", feature(external_doc))]
#![cfg_attr(all(feature = "nightly", feature = "avx2_backend"), feature(stdsimd))]
@ -32,11 +31,14 @@
// External dependencies:
//------------------------------------------------------------------------
#[cfg(feature = "std")]
extern crate core;
#[cfg(feature = "alloc")]
#[cfg(all(feature = "alloc", not(feature = "std")))]
#[macro_use]
extern crate alloc;
#[cfg(feature = "std")]
#[macro_use]
extern crate std;
extern crate rand;
extern crate clear_on_drop;
extern crate byteorder;
@ -94,5 +96,8 @@ pub(crate) mod backend;
// Internal curve models which are not part of the public API.
pub(crate) mod curve_models;
// Crate-local prelude (for alloc-dependent features like `Vec`)
pub(crate) mod prelude;
// Implementations of scalar mul algorithms live here
pub(crate) mod scalar_mul;

View file

@ -284,6 +284,7 @@ mod test {
use constants;
use super::*;
#[cfg(feature = "rand")]
use rand::rngs::OsRng;
/// Test Montgomery -> Edwards on the X/Ed25519 basepoint
@ -337,6 +338,7 @@ mod test {
assert_eq!(u18, u18_unred);
}
#[cfg(feature = "rand")]
#[test]
fn montgomery_ladder_matches_edwards_scalarmult() {
let mut csprng: OsRng = OsRng::new().unwrap();

8
src/prelude.rs Normal file
View file

@ -0,0 +1,8 @@
//! Crate-local prelude (for alloc-dependent features like `Vec`)
// TODO: switch to alloc::prelude
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::vec::Vec;
#[cfg(feature = "std")]
pub use std::vec::Vec;

View file

@ -188,6 +188,9 @@ use subtle::Choice;
use edwards::EdwardsPoint;
use edwards::EdwardsBasepointTable;
#[allow(unused_imports)]
use prelude::*;
use scalar::Scalar;
use curve_models::CompletedPoint;
@ -420,7 +423,7 @@ impl RistrettoPoint {
/// }
/// # }
/// ```
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(feature = "alloc")]
pub fn double_and_compress_batch<'a, I>(points: I) -> Vec<CompressedRistretto>
where I: IntoIterator<Item = &'a RistrettoPoint>
{
@ -794,7 +797,7 @@ define_mul_variants!(LHS = Scalar, RHS = RistrettoPoint, Output = RistrettoPoint
// These use iterator combinators to unwrap the underlying points and
// forward to the EdwardsPoint implementations.
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(feature = "alloc")]
impl MultiscalarMul for RistrettoPoint {
type Point = RistrettoPoint;
@ -812,7 +815,7 @@ impl MultiscalarMul for RistrettoPoint {
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(feature = "alloc")]
impl VartimeMultiscalarMul for RistrettoPoint {
type Point = RistrettoPoint;
@ -937,6 +940,7 @@ impl Debug for RistrettoPoint {
#[cfg(all(test, feature = "stage2_build"))]
mod test {
#[cfg(feature = "rand")]
use rand::rngs::OsRng;
use scalar::Scalar;
@ -1072,6 +1076,7 @@ mod test {
}
}
#[cfg(feature = "rand")]
#[test]
fn four_torsion_random() {
let mut rng = OsRng::new().unwrap();
@ -1134,6 +1139,7 @@ mod test {
}
}
#[cfg(feature = "rand")]
#[test]
fn random_roundtrip() {
let mut rng = OsRng::new().unwrap();
@ -1146,6 +1152,7 @@ mod test {
}
}
#[cfg(feature = "rand")]
#[test]
fn double_and_compress_1024_random_points() {
let mut rng = OsRng::new().unwrap();
@ -1160,6 +1167,7 @@ mod test {
}
}
#[cfg(feature = "rand")]
#[test]
fn random_is_valid() {
let mut rng = OsRng::new().unwrap();

View file

@ -328,7 +328,6 @@ impl Scalar {
/// # Returns
///
/// A random scalar within /l.
#[cfg(feature = "std")]
pub fn random<T: Rng + CryptoRng>(rng: &mut T) -> Self {
let mut scalar_bytes = [0u8; 64];
rng.fill(&mut scalar_bytes);
@ -460,7 +459,7 @@ impl Scalar {
/// assert_eq!(scalars[3], Scalar::from_u64(11).invert());
/// # }
/// ```
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(feature = "alloc")]
pub fn batch_invert(inputs: &mut [Scalar]) -> Scalar {
// This code is essentially identical to the FieldElement
// implementation, and is documented there. Unfortunately,

View file

@ -19,6 +19,9 @@ use scalar::Scalar;
use traits::MultiscalarMul;
use traits::VartimeMultiscalarMul;
#[allow(unused_imports)]
use prelude::*;
/// Perform multiscalar multiplication by the interleaved window
/// method, also known as Straus' method (since it was apparently
/// [first published][solution] by Straus in 1964, as a solution to [a
@ -42,7 +45,7 @@ use traits::VartimeMultiscalarMul;
/// [problem]: https://www.jstor.org/stable/2312273
pub struct Straus {}
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(feature = "alloc")]
impl MultiscalarMul for Straus {
type Point = EdwardsPoint;
@ -139,7 +142,7 @@ impl MultiscalarMul for Straus {
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(feature = "alloc")]
impl VartimeMultiscalarMul for Straus {
type Point = EdwardsPoint;