Remove field traits from behind std feature flag

Now that we have a default implementation of `SqrtRatio::sqrt_ratio`, we
can use it and `FieldExt` in no-std environments.

We introduce an `alloc` feature flag to form a common feature dependency
between `std` and `sqrt-table`. It is currently unused directly, but
will be used after `CurveAffine` is refactored to remove the `std`
dependency.

Closes zcash/pasta_curves#25.
This commit is contained in:
Jack Grigg 2021-12-22 04:59:49 +00:00
parent 314b1bcb94
commit ab03c3d5e1
6 changed files with 16 additions and 57 deletions

View file

@ -44,7 +44,7 @@ required-features = ["std"]
blake2b_simd = { version = "0.5", default-features = false }
ff = { version = "0.11", default-features = false }
group = { version = "0.11", default-features = false }
rand = { version = "0.8", default-features = false }
rand = { version = "0.8", default-features = false, features = ["getrandom"] }
static_assertions = "1.1.0"
subtle = { version = "2.3", default-features = false }
@ -53,6 +53,7 @@ lazy_static = { version = "1.4.0", optional = true }
[features]
default = ["bits", "sqrt-table", "std"]
alloc = ["group/alloc"]
bits = ["ff/bits"]
sqrt-table = ["std"]
std = ["group/alloc", "lazy_static", "rand/getrandom"]
sqrt-table = ["alloc", "lazy_static"]
std = ["alloc"]

View file

@ -10,14 +10,11 @@ mod fields;
pub(crate) use fields::*;
pub use curves::*;
#[cfg(feature = "std")]
pub use fields::*;
/// This represents an element of a group with basic operations that can be
/// performed. This allows an FFT implementation (for example) to operate
/// generically over either a field or elliptic curve group.
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub trait Group: Copy + Clone + Send + Sync + 'static {
/// The group is assumed to be of prime order $p$. `Scalar` is the
/// associated scalar field of size $p$.

View file

@ -6,21 +6,19 @@ use core::mem::size_of;
use static_assertions::const_assert;
use subtle::{Choice, ConditionallySelectable, CtOption};
#[cfg(feature = "std")]
use super::Group;
#[cfg(feature = "std")]
use std::assert;
use core::assert;
#[cfg(feature = "sqrt-table")]
use std::{boxed::Box, convert::TryInto, marker::PhantomData, vec::Vec};
use alloc::{boxed::Box, vec::Vec};
#[cfg(feature = "sqrt-table")]
use core::{convert::TryInto, marker::PhantomData};
const_assert!(size_of::<usize>() >= 4);
/// A trait that exposes additional operations related to calculating square roots of
/// prime-order finite fields.
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub trait SqrtRatio: ff::PrimeField {
/// The value $(T-1)/2$ such that $2^S \cdot T = p - 1$ with $T$ odd.
const T_MINUS1_OVER2: [u64; 4];
@ -98,8 +96,6 @@ pub trait SqrtRatio: ff::PrimeField {
/// This trait is a common interface for dealing with elements of a finite
/// field.
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub trait FieldExt: SqrtRatio + From<bool> + Ord + Group<Scalar = Self> {
/// Modulus of the field written as a string for display purposes
const MODULUS: &'static str;
@ -238,7 +234,7 @@ pub struct SqrtTables<F: FieldExt> {
impl<F: FieldExt> SqrtTables<F> {
/// Build tables given parameters for the perfect hash.
pub fn new(hash_xor: u32, hash_mod: usize) -> Self {
use std::vec;
use alloc::vec;
let hasher = SqrtHasher {
hash_xor,

View file

@ -12,10 +12,7 @@ use lazy_static::lazy_static;
#[cfg(feature = "bits")]
use ff::{FieldBits, PrimeFieldBits};
use crate::arithmetic::{adc, mac, sbb};
#[cfg(feature = "std")]
use crate::arithmetic::{FieldExt, Group, SqrtRatio};
use crate::arithmetic::{adc, mac, sbb, FieldExt, Group, SqrtRatio};
#[cfg(feature = "sqrt-table")]
use crate::arithmetic::SqrtTables;
@ -227,8 +224,6 @@ const ROOT_OF_UNITY: Fp = Fp::from_raw([
/// GENERATOR^{2^s} where t * 2^s + 1 = p
/// with t odd. In other words, this
/// is a t root of unity.
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
const DELTA: Fp = Fp::from_raw([
0x6a6ccd20dd7b9ba2,
0xf5e4f3f13eee5636,
@ -467,8 +462,6 @@ impl<'a> From<&'a Fp> for [u8; 32] {
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Group for Fp {
type Scalar = Fp;
@ -676,8 +669,6 @@ lazy_static! {
static ref FP_TABLES: SqrtTables<Fp> = SqrtTables::new(0x11BE, 1098);
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl SqrtRatio for Fp {
const T_MINUS1_OVER2: [u64; 4] = T_MINUS1_OVER2;
@ -730,8 +721,6 @@ impl SqrtRatio for Fp {
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl FieldExt for Fp {
const MODULUS: &'static str =
"0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001";
@ -781,7 +770,7 @@ impl FieldExt for Fp {
}
}
#[cfg(all(test, feature = "std"))]
#[cfg(test)]
use ff::Field;
#[test]
@ -799,7 +788,6 @@ fn test_inv() {
assert_eq!(inv, INV);
}
#[cfg(feature = "std")]
#[test]
fn test_sqrt() {
// NB: TWO_INV is standing in as a "random" field element
@ -807,7 +795,6 @@ fn test_sqrt() {
assert!(v == Fp::TWO_INV || (-v) == Fp::TWO_INV);
}
#[cfg(feature = "std")]
#[test]
fn test_pow_by_t_minus1_over2() {
// NB: TWO_INV is standing in as a "random" field element
@ -815,7 +802,6 @@ fn test_pow_by_t_minus1_over2() {
assert!(v == ff::Field::pow_vartime(&Fp::TWO_INV, &T_MINUS1_OVER2));
}
#[cfg(feature = "std")]
#[test]
fn test_sqrt_ratio_and_alt() {
// (true, sqrt(num/div)), if num and div are nonzero and num/div is a square in the field
@ -862,7 +848,6 @@ fn test_sqrt_ratio_and_alt() {
assert!(v == expected);
}
#[cfg(feature = "std")]
#[test]
fn test_zeta() {
assert_eq!(
@ -878,7 +863,6 @@ fn test_zeta() {
assert!(c == Fp::one());
}
#[cfg(feature = "std")]
#[test]
fn test_root_of_unity() {
assert_eq!(
@ -887,19 +871,16 @@ fn test_root_of_unity() {
);
}
#[cfg(feature = "std")]
#[test]
fn test_inv_root_of_unity() {
assert_eq!(Fp::ROOT_OF_UNITY_INV, Fp::root_of_unity().invert().unwrap());
}
#[cfg(feature = "std")]
#[test]
fn test_inv_2() {
assert_eq!(Fp::TWO_INV, Fp::from(2).invert().unwrap());
}
#[cfg(feature = "std")]
#[test]
fn test_delta() {
assert_eq!(Fp::DELTA, GENERATOR.pow(&[1u64 << Fp::S, 0, 0, 0]));

View file

@ -12,10 +12,7 @@ use lazy_static::lazy_static;
#[cfg(feature = "bits")]
use ff::{FieldBits, PrimeFieldBits};
use crate::arithmetic::{adc, mac, sbb};
#[cfg(feature = "std")]
use crate::arithmetic::{FieldExt, Group, SqrtRatio};
use crate::arithmetic::{adc, mac, sbb, FieldExt, Group, SqrtRatio};
#[cfg(feature = "sqrt-table")]
use crate::arithmetic::SqrtTables;
@ -227,8 +224,6 @@ const ROOT_OF_UNITY: Fq = Fq::from_raw([
/// GENERATOR^{2^s} where t * 2^s + 1 = q
/// with t odd. In other words, this
/// is a t root of unity.
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
const DELTA: Fq = Fq::from_raw([
0x8494392472d1683c,
0xe3ac3376541d1140,
@ -467,8 +462,6 @@ impl<'a> From<&'a Fq> for [u8; 32] {
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl Group for Fq {
type Scalar = Fq;
@ -675,8 +668,6 @@ lazy_static! {
static ref FQ_TABLES: SqrtTables<Fq> = SqrtTables::new(0x116A9E, 1206);
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl SqrtRatio for Fq {
const T_MINUS1_OVER2: [u64; 4] = T_MINUS1_OVER2;
@ -729,8 +720,6 @@ impl SqrtRatio for Fq {
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl FieldExt for Fq {
const MODULUS: &'static str =
"0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001";
@ -780,7 +769,7 @@ impl FieldExt for Fq {
}
}
#[cfg(all(test, feature = "std"))]
#[cfg(test)]
use ff::Field;
#[test]
@ -798,7 +787,6 @@ fn test_inv() {
assert_eq!(inv, INV);
}
#[cfg(feature = "std")]
#[test]
fn test_sqrt() {
// NB: TWO_INV is standing in as a "random" field element
@ -806,7 +794,6 @@ fn test_sqrt() {
assert!(v == Fq::TWO_INV || (-v) == Fq::TWO_INV);
}
#[cfg(feature = "std")]
#[test]
fn test_pow_by_t_minus1_over2() {
// NB: TWO_INV is standing in as a "random" field element
@ -814,7 +801,6 @@ fn test_pow_by_t_minus1_over2() {
assert!(v == ff::Field::pow_vartime(&Fq::TWO_INV, &T_MINUS1_OVER2));
}
#[cfg(feature = "std")]
#[test]
fn test_sqrt_ratio_and_alt() {
// (true, sqrt(num/div)), if num and div are nonzero and num/div is a square in the field
@ -861,7 +847,6 @@ fn test_sqrt_ratio_and_alt() {
assert!(v == expected);
}
#[cfg(feature = "std")]
#[test]
fn test_zeta() {
assert_eq!(
@ -876,7 +861,6 @@ fn test_zeta() {
assert!(c == Fq::one());
}
#[cfg(feature = "std")]
#[test]
fn test_root_of_unity() {
assert_eq!(
@ -885,19 +869,16 @@ fn test_root_of_unity() {
);
}
#[cfg(feature = "std")]
#[test]
fn test_inv_root_of_unity() {
assert_eq!(Fq::ROOT_OF_UNITY_INV, Fq::root_of_unity().invert().unwrap());
}
#[cfg(feature = "std")]
#[test]
fn test_inv_2() {
assert_eq!(Fq::TWO_INV, Fq::from(2).invert().unwrap());
}
#[cfg(feature = "std")]
#[test]
fn test_delta() {
assert_eq!(Fq::DELTA, GENERATOR.pow(&[1u64 << Fq::S, 0, 0, 0]));

View file

@ -9,6 +9,9 @@
#![deny(missing_docs)]
#![deny(unsafe_code)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(any(feature = "std", test))]
#[macro_use]
extern crate std;