From 96116e20e5049f9f69073c459828ece002b86f86 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 7 Dec 2021 14:27:02 +0000 Subject: [PATCH 1/5] Annotate docs with required feature flags --- src/arithmetic.rs | 1 + src/arithmetic/curves.rs | 3 +++ src/arithmetic/fields.rs | 5 +++++ src/curves.rs | 1 + src/fields/fp.rs | 6 ++++++ src/fields/fq.rs | 5 +++++ 6 files changed, 21 insertions(+) diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 0fef7f5..8e711d2 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -17,6 +17,7 @@ pub use fields::*; /// 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$. diff --git a/src/arithmetic/curves.rs b/src/arithmetic/curves.rs index d954893..4bd128f 100644 --- a/src/arithmetic/curves.rs +++ b/src/arithmetic/curves.rs @@ -23,6 +23,7 @@ use std::{ /// Currently requires the `std` feature flag because of `hash_to_curve`, and /// `CurveAffine::{read, write}`. #[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub trait CurveExt: PrimeCurve::AffineExt> + group::Group::ScalarExt> @@ -90,6 +91,7 @@ pub trait CurveExt: /// This trait is the affine counterpart to `Curve` and is used for /// serialization, storage in memory, and inspection of $x$ and $y$ coordinates. #[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub trait CurveAffine: PrimeCurveAffine< Scalar = ::ScalarExt, @@ -145,6 +147,7 @@ pub trait CurveAffine: /// The affine coordinates of a point on an elliptic curve. #[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[derive(Clone, Copy, Debug, Default)] pub struct Coordinates { pub(crate) x: C::Base, diff --git a/src/arithmetic/fields.rs b/src/arithmetic/fields.rs index dbea4f8..ce98a0f 100644 --- a/src/arithmetic/fields.rs +++ b/src/arithmetic/fields.rs @@ -20,6 +20,7 @@ const_assert!(size_of::() >= 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]; @@ -65,6 +66,7 @@ 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 + Ord + Group { /// Modulus of the field written as a string for display purposes const MODULUS: &'static str; @@ -119,6 +121,7 @@ pub trait FieldExt: SqrtRatio + From + Ord + Group { /// /// `tm1d2` should be set to `(t - 1) // 2`, where `t = (modulus - 1) >> F::S`. #[cfg(not(feature = "std"))] +#[cfg_attr(docsrs, doc(cfg(not(feature = "std"))))] pub(crate) fn sqrt_tonelli_shanks>( f: &F, tm1d2: S, @@ -165,6 +168,7 @@ pub(crate) fn sqrt_tonelli_shanks>( /// Parameters for a perfect hash function used in square root computation. #[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[derive(Debug)] struct SqrtHasher { hash_xor: u32, @@ -186,6 +190,7 @@ impl SqrtHasher { /// Tables used for square root computation. #[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[derive(Debug)] pub struct SqrtTables { hasher: SqrtHasher, diff --git a/src/curves.rs b/src/curves.rs index 8661033..7a0db20 100644 --- a/src/curves.rs +++ b/src/curves.rs @@ -103,6 +103,7 @@ macro_rules! new_curve_impl { } #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl group::WnafGroup for $name { fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize { // Copied from bls12_381::g1, should be updated. diff --git a/src/fields/fp.rs b/src/fields/fp.rs index d27928f..d56dd3f 100644 --- a/src/fields/fp.rs +++ b/src/fields/fp.rs @@ -225,6 +225,7 @@ const ROOT_OF_UNITY: Fp = Fp::from_raw([ /// 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, @@ -464,6 +465,7 @@ 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; @@ -623,6 +625,7 @@ type ReprBits = [u32; 8]; type ReprBits = [u64; 4]; #[cfg(feature = "bits")] +#[cfg_attr(docsrs, doc(cfg(feature = "bits")))] impl PrimeFieldBits for Fp { type ReprBits = ReprBits; @@ -666,10 +669,12 @@ impl PrimeFieldBits for Fp { #[cfg(feature = "std")] lazy_static! { // The perfect hash parameters are found by `squareroottab.sage` in zcash/pasta. + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] static ref FP_TABLES: SqrtTables = 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; @@ -721,6 +726,7 @@ impl SqrtRatio for Fp { } #[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl FieldExt for Fp { const MODULUS: &'static str = "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001"; diff --git a/src/fields/fq.rs b/src/fields/fq.rs index f7111be..5b100fe 100644 --- a/src/fields/fq.rs +++ b/src/fields/fq.rs @@ -225,6 +225,7 @@ const ROOT_OF_UNITY: Fq = Fq::from_raw([ /// 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, @@ -464,6 +465,7 @@ 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; @@ -666,10 +668,12 @@ impl PrimeFieldBits for Fq { #[cfg(feature = "std")] lazy_static! { // The perfect hash parameters are found by `squareroottab.sage` in zcash/pasta. + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] static ref FQ_TABLES: SqrtTables = 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; @@ -721,6 +725,7 @@ impl SqrtRatio for Fq { } #[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl FieldExt for Fq { const MODULUS: &'static str = "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001"; From 314b1bcb94fb75bc4f0f9eebc07a26c4e904ee13 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 22 Dec 2021 04:22:14 +0000 Subject: [PATCH 2/5] Place `SqrtTables` behind a `sqrt-tables` feature flag This enables the crate to be compiled without the tables, instead using a simple fallback for `SqrtRatio::sqrt_ratio`. --- Cargo.toml | 3 +- src/arithmetic/fields.rs | 63 ++++++++++++++++++++++++++++++---------- src/fields/fp.rs | 17 +++++++---- src/fields/fq.rs | 17 +++++++---- 4 files changed, 72 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 50b86c2..15f4922 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,7 @@ subtle = { version = "2.3", default-features = false } lazy_static = { version = "1.4.0", optional = true } [features] -default = ["bits", "std"] +default = ["bits", "sqrt-table", "std"] bits = ["ff/bits"] +sqrt-table = ["std"] std = ["group/alloc", "lazy_static", "rand/getrandom"] diff --git a/src/arithmetic/fields.rs b/src/arithmetic/fields.rs index ce98a0f..4110858 100644 --- a/src/arithmetic/fields.rs +++ b/src/arithmetic/fields.rs @@ -4,16 +4,16 @@ use core::mem::size_of; use static_assertions::const_assert; -use subtle::Choice; - -#[cfg(not(feature = "std"))] -use subtle::CtOption; +use subtle::{Choice, ConditionallySelectable, CtOption}; #[cfg(feature = "std")] use super::Group; #[cfg(feature = "std")] -use std::{assert, boxed::Box, convert::TryInto, marker::PhantomData, vec::Vec}; +use std::assert; + +#[cfg(feature = "sqrt-table")] +use std::{boxed::Box, convert::TryInto, marker::PhantomData, vec::Vec}; const_assert!(size_of::() >= 4); @@ -55,7 +55,40 @@ pub trait SqrtRatio: ff::PrimeField { /// implementation of the SSWU hash-to-curve algorithm. /// /// The choice of root from sqrt is unspecified. - fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self); + fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) { + // General implementation: + // + // a = num * inv0(div) + // = { 0 if div is zero + // { num/div otherwise + // + // b = G_S * a + // = { 0 if div is zero + // { G_S*num/div otherwise + // + // Since G_S is non-square, a and b are either both zero (and both square), or + // only one them is square. We can therefore choose the square root to return + // based on whether a is square, but for the boolean output we need to handle the + // num != 0 && div == 0 case specifically. + + let a = div.invert().unwrap_or_else(Self::zero) * num; + let b = a * Self::root_of_unity(); + let sqrt_a = a.sqrt(); + let sqrt_b = b.sqrt(); + + let num_is_zero = num.is_zero(); + let div_is_zero = div.is_zero(); + let is_square = sqrt_a.is_some(); + let is_nonsquare = sqrt_b.is_some(); + assert!(bool::from( + num_is_zero | div_is_zero | (is_square ^ is_nonsquare) + )); + + ( + is_square & !(!num_is_zero & div_is_zero), + CtOption::conditional_select(&sqrt_b, &sqrt_a, is_square).unwrap(), + ) + } /// Equivalent to `Self::sqrt_ratio(self, one())`. fn sqrt_alt(&self) -> (Choice, Self) { @@ -120,13 +153,13 @@ pub trait FieldExt: SqrtRatio + From + Ord + Group { /// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) /// /// `tm1d2` should be set to `(t - 1) // 2`, where `t = (modulus - 1) >> F::S`. -#[cfg(not(feature = "std"))] -#[cfg_attr(docsrs, doc(cfg(not(feature = "std"))))] +#[cfg(not(feature = "sqrt-table"))] +#[cfg_attr(docsrs, doc(cfg(not(feature = "sqrt-table"))))] pub(crate) fn sqrt_tonelli_shanks>( f: &F, tm1d2: S, ) -> CtOption { - use subtle::{ConditionallySelectable, ConstantTimeEq}; + use subtle::ConstantTimeEq; // w = self^((t - 1) // 2) let w = f.pow_vartime(tm1d2); @@ -167,8 +200,8 @@ pub(crate) fn sqrt_tonelli_shanks>( } /// Parameters for a perfect hash function used in square root computation. -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(feature = "sqrt-table")] +#[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))] #[derive(Debug)] struct SqrtHasher { hash_xor: u32, @@ -176,7 +209,7 @@ struct SqrtHasher { marker: PhantomData, } -#[cfg(feature = "std")] +#[cfg(feature = "sqrt-table")] impl SqrtHasher { /// Returns a perfect hash of x for use with SqrtTables::inv. fn hash(&self, x: &F) -> usize { @@ -189,8 +222,8 @@ impl SqrtHasher { } /// Tables used for square root computation. -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(feature = "sqrt-table")] +#[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))] #[derive(Debug)] pub struct SqrtTables { hasher: SqrtHasher, @@ -201,7 +234,7 @@ pub struct SqrtTables { g3: Box<[F; 129]>, } -#[cfg(feature = "std")] +#[cfg(feature = "sqrt-table")] impl SqrtTables { /// Build tables given parameters for the perfect hash. pub fn new(hash_xor: u32, hash_mod: usize) -> Self { diff --git a/src/fields/fp.rs b/src/fields/fp.rs index d56dd3f..9b51453 100644 --- a/src/fields/fp.rs +++ b/src/fields/fp.rs @@ -6,7 +6,7 @@ use ff::PrimeField; use rand::RngCore; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; -#[cfg(feature = "std")] +#[cfg(feature = "sqrt-table")] use lazy_static::lazy_static; #[cfg(feature = "bits")] @@ -15,7 +15,10 @@ use ff::{FieldBits, PrimeFieldBits}; use crate::arithmetic::{adc, mac, sbb}; #[cfg(feature = "std")] -use crate::arithmetic::{FieldExt, Group, SqrtRatio, SqrtTables}; +use crate::arithmetic::{FieldExt, Group, SqrtRatio}; + +#[cfg(feature = "sqrt-table")] +use crate::arithmetic::SqrtTables; /// This represents an element of $\mathbb{F}_p$ where /// @@ -516,13 +519,13 @@ impl ff::Field for Fp { /// Computes the square root of this element, if it exists. fn sqrt(&self) -> CtOption { - #[cfg(feature = "std")] + #[cfg(feature = "sqrt-table")] { let (is_square, res) = FP_TABLES.sqrt_alt(self); CtOption::new(res, is_square) } - #[cfg(not(feature = "std"))] + #[cfg(not(feature = "sqrt-table"))] crate::arithmetic::sqrt_tonelli_shanks(self, &T_MINUS1_OVER2) } @@ -666,10 +669,10 @@ impl PrimeFieldBits for Fp { } } -#[cfg(feature = "std")] +#[cfg(feature = "sqrt-table")] lazy_static! { // The perfect hash parameters are found by `squareroottab.sage` in zcash/pasta. - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))] static ref FP_TABLES: SqrtTables = SqrtTables::new(0x11BE, 1098); } @@ -716,10 +719,12 @@ impl SqrtRatio for Fp { tmp.0[0] as u32 } + #[cfg(feature = "sqrt-table")] fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) { FP_TABLES.sqrt_ratio(num, div) } + #[cfg(feature = "sqrt-table")] fn sqrt_alt(&self) -> (Choice, Self) { FP_TABLES.sqrt_alt(self) } diff --git a/src/fields/fq.rs b/src/fields/fq.rs index 5b100fe..61b0683 100644 --- a/src/fields/fq.rs +++ b/src/fields/fq.rs @@ -6,7 +6,7 @@ use ff::PrimeField; use rand::RngCore; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; -#[cfg(feature = "std")] +#[cfg(feature = "sqrt-table")] use lazy_static::lazy_static; #[cfg(feature = "bits")] @@ -15,7 +15,10 @@ use ff::{FieldBits, PrimeFieldBits}; use crate::arithmetic::{adc, mac, sbb}; #[cfg(feature = "std")] -use crate::arithmetic::{FieldExt, Group, SqrtRatio, SqrtTables}; +use crate::arithmetic::{FieldExt, Group, SqrtRatio}; + +#[cfg(feature = "sqrt-table")] +use crate::arithmetic::SqrtTables; /// This represents an element of $\mathbb{F}_q$ where /// @@ -516,13 +519,13 @@ impl ff::Field for Fq { /// Computes the square root of this element, if it exists. fn sqrt(&self) -> CtOption { - #[cfg(feature = "std")] + #[cfg(feature = "sqrt-table")] { let (is_square, res) = FQ_TABLES.sqrt_alt(self); CtOption::new(res, is_square) } - #[cfg(not(feature = "std"))] + #[cfg(not(feature = "sqrt-table"))] crate::arithmetic::sqrt_tonelli_shanks(self, &T_MINUS1_OVER2) } @@ -665,10 +668,10 @@ impl PrimeFieldBits for Fq { } } -#[cfg(feature = "std")] +#[cfg(feature = "sqrt-table")] lazy_static! { // The perfect hash parameters are found by `squareroottab.sage` in zcash/pasta. - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))] static ref FQ_TABLES: SqrtTables = SqrtTables::new(0x116A9E, 1206); } @@ -715,10 +718,12 @@ impl SqrtRatio for Fq { tmp.0[0] as u32 } + #[cfg(feature = "sqrt-table")] fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) { FQ_TABLES.sqrt_ratio(num, div) } + #[cfg(feature = "sqrt-table")] fn sqrt_alt(&self) -> (Choice, Self) { FQ_TABLES.sqrt_alt(self) } From ab03c3d5e13e50edc71b26de8fc504febeaabf24 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 22 Dec 2021 04:59:49 +0000 Subject: [PATCH 3/5] 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. --- Cargo.toml | 7 ++++--- src/arithmetic.rs | 3 --- src/arithmetic/fields.rs | 14 +++++--------- src/fields/fp.rs | 23 ++--------------------- src/fields/fq.rs | 23 ++--------------------- src/lib.rs | 3 +++ 6 files changed, 16 insertions(+), 57 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 15f4922..db355e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 8e711d2..e96a074 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -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$. diff --git a/src/arithmetic/fields.rs b/src/arithmetic/fields.rs index 4110858..c44f46a 100644 --- a/src/arithmetic/fields.rs +++ b/src/arithmetic/fields.rs @@ -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::() >= 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 + Ord + Group { /// Modulus of the field written as a string for display purposes const MODULUS: &'static str; @@ -238,7 +234,7 @@ pub struct SqrtTables { impl SqrtTables { /// 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, diff --git a/src/fields/fp.rs b/src/fields/fp.rs index 9b51453..17be5d6 100644 --- a/src/fields/fp.rs +++ b/src/fields/fp.rs @@ -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 = 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])); diff --git a/src/fields/fq.rs b/src/fields/fq.rs index 61b0683..618bf54 100644 --- a/src/fields/fq.rs +++ b/src/fields/fq.rs @@ -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 = 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])); diff --git a/src/lib.rs b/src/lib.rs index add7d5d..c87d047 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; From f874d292384962b6b194ca4d48b39ca485e379bd Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 22 Dec 2021 05:15:06 +0000 Subject: [PATCH 4/5] Remove `FieldExt::rand` This removes a dependency on the `getrandom` crate in no-std mode, which doesn't work on some no-std targets that `getrandom` doesn't support. --- CHANGELOG.md | 1 + Cargo.toml | 2 +- src/arithmetic/fields.rs | 5 ----- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5df23a..768dde2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to Rust's notion of - `FieldExt::from_u64` (use `From for ff::PrimeField` instead). - `FieldExt::{from_bytes, read, to_bytes, write}` (use `ff::PrimeField::{from_repr, to_repr}` instead). + - `FieldExt::rand` (use `ff::Field::random` instead). ## [0.2.1] - 2021-09-17 ### Changed diff --git a/Cargo.toml b/Cargo.toml index db355e1..bbbe635 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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, features = ["getrandom"] } +rand = { version = "0.8", default-features = false } static_assertions = "1.1.0" subtle = { version = "2.3", default-features = false } diff --git a/src/arithmetic/fields.rs b/src/arithmetic/fields.rs index c44f46a..ab3a1c2 100644 --- a/src/arithmetic/fields.rs +++ b/src/arithmetic/fields.rs @@ -112,11 +112,6 @@ pub trait FieldExt: SqrtRatio + From + Ord + Group { /// Element of multiplicative order $3$. const ZETA: Self; - /// This computes a random element of the field using system randomness. - fn rand() -> Self { - Self::random(rand::rngs::OsRng) - } - /// Obtains a field element congruent to the integer `v`. fn from_u128(v: u128) -> Self; From c10960351da804b5b31f011250254c37922d3156 Mon Sep 17 00:00:00 2001 From: str4d Date: Sat, 25 Dec 2021 12:20:18 +0000 Subject: [PATCH 5/5] Fix typo in code comment Co-authored-by: Daira Hopwood --- src/arithmetic/fields.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arithmetic/fields.rs b/src/arithmetic/fields.rs index ab3a1c2..3f47a89 100644 --- a/src/arithmetic/fields.rs +++ b/src/arithmetic/fields.rs @@ -65,7 +65,7 @@ pub trait SqrtRatio: ff::PrimeField { // { G_S*num/div otherwise // // Since G_S is non-square, a and b are either both zero (and both square), or - // only one them is square. We can therefore choose the square root to return + // only one of them is square. We can therefore choose the square root to return // based on whether a is square, but for the boolean output we need to handle the // num != 0 && div == 0 case specifically.