mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-05 20:10:32 +00:00
Merge pull request #26 from zcash/no-std-field-traits
Remove field traits from behind `std` feature flag
This commit is contained in:
commit
93c6a18e92
9 changed files with 86 additions and 66 deletions
|
|
@ -21,6 +21,7 @@ and this project adheres to Rust's notion of
|
||||||
- `FieldExt::from_u64` (use `From<u64> for ff::PrimeField` instead).
|
- `FieldExt::from_u64` (use `From<u64> for ff::PrimeField` instead).
|
||||||
- `FieldExt::{from_bytes, read, to_bytes, write}`
|
- `FieldExt::{from_bytes, read, to_bytes, write}`
|
||||||
(use `ff::PrimeField::{from_repr, to_repr}` instead).
|
(use `ff::PrimeField::{from_repr, to_repr}` instead).
|
||||||
|
- `FieldExt::rand` (use `ff::Field::random` instead).
|
||||||
|
|
||||||
## [0.2.1] - 2021-09-17
|
## [0.2.1] - 2021-09-17
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ subtle = { version = "2.3", default-features = false }
|
||||||
lazy_static = { version = "1.4.0", optional = true }
|
lazy_static = { version = "1.4.0", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["bits", "std"]
|
default = ["bits", "sqrt-table", "std"]
|
||||||
|
alloc = ["group/alloc"]
|
||||||
bits = ["ff/bits"]
|
bits = ["ff/bits"]
|
||||||
std = ["group/alloc", "lazy_static", "rand/getrandom"]
|
sqrt-table = ["alloc", "lazy_static"]
|
||||||
|
std = ["alloc"]
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,11 @@ mod fields;
|
||||||
pub(crate) use fields::*;
|
pub(crate) use fields::*;
|
||||||
|
|
||||||
pub use curves::*;
|
pub use curves::*;
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use fields::*;
|
pub use fields::*;
|
||||||
|
|
||||||
/// This represents an element of a group with basic operations that can be
|
/// This represents an element of a group with basic operations that can be
|
||||||
/// performed. This allows an FFT implementation (for example) to operate
|
/// performed. This allows an FFT implementation (for example) to operate
|
||||||
/// generically over either a field or elliptic curve group.
|
/// generically over either a field or elliptic curve group.
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub trait Group: Copy + Clone + Send + Sync + 'static {
|
pub trait Group: Copy + Clone + Send + Sync + 'static {
|
||||||
/// The group is assumed to be of prime order $p$. `Scalar` is the
|
/// The group is assumed to be of prime order $p$. `Scalar` is the
|
||||||
/// associated scalar field of size $p$.
|
/// associated scalar field of size $p$.
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ use std::{
|
||||||
/// Currently requires the `std` feature flag because of `hash_to_curve`, and
|
/// Currently requires the `std` feature flag because of `hash_to_curve`, and
|
||||||
/// `CurveAffine::{read, write}`.
|
/// `CurveAffine::{read, write}`.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
pub trait CurveExt:
|
pub trait CurveExt:
|
||||||
PrimeCurve<Affine = <Self as CurveExt>::AffineExt>
|
PrimeCurve<Affine = <Self as CurveExt>::AffineExt>
|
||||||
+ group::Group<Scalar = <Self as CurveExt>::ScalarExt>
|
+ group::Group<Scalar = <Self as CurveExt>::ScalarExt>
|
||||||
|
|
@ -90,6 +91,7 @@ pub trait CurveExt:
|
||||||
/// This trait is the affine counterpart to `Curve` and is used for
|
/// This trait is the affine counterpart to `Curve` and is used for
|
||||||
/// serialization, storage in memory, and inspection of $x$ and $y$ coordinates.
|
/// serialization, storage in memory, and inspection of $x$ and $y$ coordinates.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
pub trait CurveAffine:
|
pub trait CurveAffine:
|
||||||
PrimeCurveAffine<
|
PrimeCurveAffine<
|
||||||
Scalar = <Self as CurveAffine>::ScalarExt,
|
Scalar = <Self as CurveAffine>::ScalarExt,
|
||||||
|
|
@ -145,6 +147,7 @@ pub trait CurveAffine:
|
||||||
|
|
||||||
/// The affine coordinates of a point on an elliptic curve.
|
/// The affine coordinates of a point on an elliptic curve.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub struct Coordinates<C: CurveAffine> {
|
pub struct Coordinates<C: CurveAffine> {
|
||||||
pub(crate) x: C::Base,
|
pub(crate) x: C::Base,
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,21 @@
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
|
|
||||||
use static_assertions::const_assert;
|
use static_assertions::const_assert;
|
||||||
use subtle::Choice;
|
use subtle::{Choice, ConditionallySelectable, CtOption};
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
use subtle::CtOption;
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
use super::Group;
|
use super::Group;
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
use core::assert;
|
||||||
use std::{assert, boxed::Box, convert::TryInto, marker::PhantomData, vec::Vec};
|
|
||||||
|
#[cfg(feature = "sqrt-table")]
|
||||||
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
|
#[cfg(feature = "sqrt-table")]
|
||||||
|
use core::{convert::TryInto, marker::PhantomData};
|
||||||
|
|
||||||
const_assert!(size_of::<usize>() >= 4);
|
const_assert!(size_of::<usize>() >= 4);
|
||||||
|
|
||||||
/// A trait that exposes additional operations related to calculating square roots of
|
/// A trait that exposes additional operations related to calculating square roots of
|
||||||
/// prime-order finite fields.
|
/// prime-order finite fields.
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub trait SqrtRatio: ff::PrimeField {
|
pub trait SqrtRatio: ff::PrimeField {
|
||||||
/// The value $(T-1)/2$ such that $2^S \cdot T = p - 1$ with $T$ odd.
|
/// The value $(T-1)/2$ such that $2^S \cdot T = p - 1$ with $T$ odd.
|
||||||
const T_MINUS1_OVER2: [u64; 4];
|
const T_MINUS1_OVER2: [u64; 4];
|
||||||
|
|
@ -54,7 +53,40 @@ pub trait SqrtRatio: ff::PrimeField {
|
||||||
/// implementation of the SSWU hash-to-curve algorithm.
|
/// implementation of the SSWU hash-to-curve algorithm.
|
||||||
///
|
///
|
||||||
/// The choice of root from sqrt is unspecified.
|
/// 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 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.
|
||||||
|
|
||||||
|
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())`.
|
/// Equivalent to `Self::sqrt_ratio(self, one())`.
|
||||||
fn sqrt_alt(&self) -> (Choice, Self) {
|
fn sqrt_alt(&self) -> (Choice, Self) {
|
||||||
|
|
@ -64,7 +96,6 @@ pub trait SqrtRatio: ff::PrimeField {
|
||||||
|
|
||||||
/// This trait is a common interface for dealing with elements of a finite
|
/// This trait is a common interface for dealing with elements of a finite
|
||||||
/// field.
|
/// field.
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub trait FieldExt: SqrtRatio + From<bool> + Ord + Group<Scalar = Self> {
|
pub trait FieldExt: SqrtRatio + From<bool> + Ord + Group<Scalar = Self> {
|
||||||
/// Modulus of the field written as a string for display purposes
|
/// Modulus of the field written as a string for display purposes
|
||||||
const MODULUS: &'static str;
|
const MODULUS: &'static str;
|
||||||
|
|
@ -81,11 +112,6 @@ pub trait FieldExt: SqrtRatio + From<bool> + Ord + Group<Scalar = Self> {
|
||||||
/// Element of multiplicative order $3$.
|
/// Element of multiplicative order $3$.
|
||||||
const ZETA: Self;
|
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`.
|
/// Obtains a field element congruent to the integer `v`.
|
||||||
fn from_u128(v: u128) -> Self;
|
fn from_u128(v: u128) -> Self;
|
||||||
|
|
||||||
|
|
@ -118,12 +144,13 @@ pub trait FieldExt: SqrtRatio + From<bool> + Ord + Group<Scalar = Self> {
|
||||||
/// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
|
/// 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`.
|
/// `tm1d2` should be set to `(t - 1) // 2`, where `t = (modulus - 1) >> F::S`.
|
||||||
#[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: ff::PrimeField, S: AsRef<[u64]>>(
|
pub(crate) fn sqrt_tonelli_shanks<F: ff::PrimeField, S: AsRef<[u64]>>(
|
||||||
f: &F,
|
f: &F,
|
||||||
tm1d2: S,
|
tm1d2: S,
|
||||||
) -> CtOption<F> {
|
) -> CtOption<F> {
|
||||||
use subtle::{ConditionallySelectable, ConstantTimeEq};
|
use subtle::ConstantTimeEq;
|
||||||
|
|
||||||
// w = self^((t - 1) // 2)
|
// w = self^((t - 1) // 2)
|
||||||
let w = f.pow_vartime(tm1d2);
|
let w = f.pow_vartime(tm1d2);
|
||||||
|
|
@ -164,7 +191,8 @@ pub(crate) fn sqrt_tonelli_shanks<F: ff::PrimeField, S: AsRef<[u64]>>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parameters for a perfect hash function used in square root computation.
|
/// Parameters for a perfect hash function used in square root computation.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SqrtHasher<F: FieldExt> {
|
struct SqrtHasher<F: FieldExt> {
|
||||||
hash_xor: u32,
|
hash_xor: u32,
|
||||||
|
|
@ -172,7 +200,7 @@ struct SqrtHasher<F: FieldExt> {
|
||||||
marker: PhantomData<F>,
|
marker: PhantomData<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
impl<F: FieldExt> SqrtHasher<F> {
|
impl<F: FieldExt> SqrtHasher<F> {
|
||||||
/// Returns a perfect hash of x for use with SqrtTables::inv.
|
/// Returns a perfect hash of x for use with SqrtTables::inv.
|
||||||
fn hash(&self, x: &F) -> usize {
|
fn hash(&self, x: &F) -> usize {
|
||||||
|
|
@ -185,7 +213,8 @@ impl<F: FieldExt> SqrtHasher<F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tables used for square root computation.
|
/// Tables used for square root computation.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SqrtTables<F: FieldExt> {
|
pub struct SqrtTables<F: FieldExt> {
|
||||||
hasher: SqrtHasher<F>,
|
hasher: SqrtHasher<F>,
|
||||||
|
|
@ -196,11 +225,11 @@ pub struct SqrtTables<F: FieldExt> {
|
||||||
g3: Box<[F; 129]>,
|
g3: Box<[F; 129]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
impl<F: FieldExt> SqrtTables<F> {
|
impl<F: FieldExt> SqrtTables<F> {
|
||||||
/// Build tables given parameters for the perfect hash.
|
/// Build tables given parameters for the perfect hash.
|
||||||
pub fn new(hash_xor: u32, hash_mod: usize) -> Self {
|
pub fn new(hash_xor: u32, hash_mod: usize) -> Self {
|
||||||
use std::vec;
|
use alloc::vec;
|
||||||
|
|
||||||
let hasher = SqrtHasher {
|
let hasher = SqrtHasher {
|
||||||
hash_xor,
|
hash_xor,
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ macro_rules! new_curve_impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||||
impl group::WnafGroup for $name {
|
impl group::WnafGroup for $name {
|
||||||
fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize {
|
fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize {
|
||||||
// Copied from bls12_381::g1, should be updated.
|
// Copied from bls12_381::g1, should be updated.
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,16 @@ use ff::PrimeField;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
#[cfg(feature = "bits")]
|
#[cfg(feature = "bits")]
|
||||||
use ff::{FieldBits, PrimeFieldBits};
|
use ff::{FieldBits, PrimeFieldBits};
|
||||||
|
|
||||||
use crate::arithmetic::{adc, mac, sbb};
|
use crate::arithmetic::{adc, mac, sbb, FieldExt, Group, SqrtRatio};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
use crate::arithmetic::{FieldExt, Group, SqrtRatio, SqrtTables};
|
use crate::arithmetic::SqrtTables;
|
||||||
|
|
||||||
/// This represents an element of $\mathbb{F}_p$ where
|
/// This represents an element of $\mathbb{F}_p$ where
|
||||||
///
|
///
|
||||||
|
|
@ -224,7 +224,6 @@ const ROOT_OF_UNITY: Fp = Fp::from_raw([
|
||||||
/// GENERATOR^{2^s} where t * 2^s + 1 = p
|
/// GENERATOR^{2^s} where t * 2^s + 1 = p
|
||||||
/// with t odd. In other words, this
|
/// with t odd. In other words, this
|
||||||
/// is a t root of unity.
|
/// is a t root of unity.
|
||||||
#[cfg(feature = "std")]
|
|
||||||
const DELTA: Fp = Fp::from_raw([
|
const DELTA: Fp = Fp::from_raw([
|
||||||
0x6a6ccd20dd7b9ba2,
|
0x6a6ccd20dd7b9ba2,
|
||||||
0xf5e4f3f13eee5636,
|
0xf5e4f3f13eee5636,
|
||||||
|
|
@ -463,7 +462,6 @@ impl<'a> From<&'a Fp> for [u8; 32] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl Group for Fp {
|
impl Group for Fp {
|
||||||
type Scalar = Fp;
|
type Scalar = Fp;
|
||||||
|
|
||||||
|
|
@ -514,13 +512,13 @@ impl ff::Field for Fp {
|
||||||
|
|
||||||
/// Computes the square root of this element, if it exists.
|
/// Computes the square root of this element, if it exists.
|
||||||
fn sqrt(&self) -> CtOption<Self> {
|
fn sqrt(&self) -> CtOption<Self> {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
{
|
{
|
||||||
let (is_square, res) = FP_TABLES.sqrt_alt(self);
|
let (is_square, res) = FP_TABLES.sqrt_alt(self);
|
||||||
CtOption::new(res, is_square)
|
CtOption::new(res, is_square)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "sqrt-table"))]
|
||||||
crate::arithmetic::sqrt_tonelli_shanks(self, &T_MINUS1_OVER2)
|
crate::arithmetic::sqrt_tonelli_shanks(self, &T_MINUS1_OVER2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -623,6 +621,7 @@ type ReprBits = [u32; 8];
|
||||||
type ReprBits = [u64; 4];
|
type ReprBits = [u64; 4];
|
||||||
|
|
||||||
#[cfg(feature = "bits")]
|
#[cfg(feature = "bits")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "bits")))]
|
||||||
impl PrimeFieldBits for Fp {
|
impl PrimeFieldBits for Fp {
|
||||||
type ReprBits = ReprBits;
|
type ReprBits = ReprBits;
|
||||||
|
|
||||||
|
|
@ -663,13 +662,13 @@ impl PrimeFieldBits for Fp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
// The perfect hash parameters are found by `squareroottab.sage` in zcash/pasta.
|
// The perfect hash parameters are found by `squareroottab.sage` in zcash/pasta.
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))]
|
||||||
static ref FP_TABLES: SqrtTables<Fp> = SqrtTables::new(0x11BE, 1098);
|
static ref FP_TABLES: SqrtTables<Fp> = SqrtTables::new(0x11BE, 1098);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl SqrtRatio for Fp {
|
impl SqrtRatio for Fp {
|
||||||
const T_MINUS1_OVER2: [u64; 4] = T_MINUS1_OVER2;
|
const T_MINUS1_OVER2: [u64; 4] = T_MINUS1_OVER2;
|
||||||
|
|
||||||
|
|
@ -711,16 +710,17 @@ impl SqrtRatio for Fp {
|
||||||
tmp.0[0] as u32
|
tmp.0[0] as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "sqrt-table")]
|
||||||
fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
|
fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
|
||||||
FP_TABLES.sqrt_ratio(num, div)
|
FP_TABLES.sqrt_ratio(num, div)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "sqrt-table")]
|
||||||
fn sqrt_alt(&self) -> (Choice, Self) {
|
fn sqrt_alt(&self) -> (Choice, Self) {
|
||||||
FP_TABLES.sqrt_alt(self)
|
FP_TABLES.sqrt_alt(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl FieldExt for Fp {
|
impl FieldExt for Fp {
|
||||||
const MODULUS: &'static str =
|
const MODULUS: &'static str =
|
||||||
"0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001";
|
"0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001";
|
||||||
|
|
@ -770,7 +770,7 @@ impl FieldExt for Fp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(test, feature = "std"))]
|
#[cfg(test)]
|
||||||
use ff::Field;
|
use ff::Field;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -788,7 +788,6 @@ fn test_inv() {
|
||||||
assert_eq!(inv, INV);
|
assert_eq!(inv, INV);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sqrt() {
|
fn test_sqrt() {
|
||||||
// NB: TWO_INV is standing in as a "random" field element
|
// NB: TWO_INV is standing in as a "random" field element
|
||||||
|
|
@ -796,7 +795,6 @@ fn test_sqrt() {
|
||||||
assert!(v == Fp::TWO_INV || (-v) == Fp::TWO_INV);
|
assert!(v == Fp::TWO_INV || (-v) == Fp::TWO_INV);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pow_by_t_minus1_over2() {
|
fn test_pow_by_t_minus1_over2() {
|
||||||
// NB: TWO_INV is standing in as a "random" field element
|
// NB: TWO_INV is standing in as a "random" field element
|
||||||
|
|
@ -804,7 +802,6 @@ fn test_pow_by_t_minus1_over2() {
|
||||||
assert!(v == ff::Field::pow_vartime(&Fp::TWO_INV, &T_MINUS1_OVER2));
|
assert!(v == ff::Field::pow_vartime(&Fp::TWO_INV, &T_MINUS1_OVER2));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sqrt_ratio_and_alt() {
|
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
|
// (true, sqrt(num/div)), if num and div are nonzero and num/div is a square in the field
|
||||||
|
|
@ -851,7 +848,6 @@ fn test_sqrt_ratio_and_alt() {
|
||||||
assert!(v == expected);
|
assert!(v == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_zeta() {
|
fn test_zeta() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -867,7 +863,6 @@ fn test_zeta() {
|
||||||
assert!(c == Fp::one());
|
assert!(c == Fp::one());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_root_of_unity() {
|
fn test_root_of_unity() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -876,19 +871,16 @@ fn test_root_of_unity() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_inv_root_of_unity() {
|
fn test_inv_root_of_unity() {
|
||||||
assert_eq!(Fp::ROOT_OF_UNITY_INV, Fp::root_of_unity().invert().unwrap());
|
assert_eq!(Fp::ROOT_OF_UNITY_INV, Fp::root_of_unity().invert().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_inv_2() {
|
fn test_inv_2() {
|
||||||
assert_eq!(Fp::TWO_INV, Fp::from(2).invert().unwrap());
|
assert_eq!(Fp::TWO_INV, Fp::from(2).invert().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delta() {
|
fn test_delta() {
|
||||||
assert_eq!(Fp::DELTA, GENERATOR.pow(&[1u64 << Fp::S, 0, 0, 0]));
|
assert_eq!(Fp::DELTA, GENERATOR.pow(&[1u64 << Fp::S, 0, 0, 0]));
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,16 @@ use ff::PrimeField;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
#[cfg(feature = "bits")]
|
#[cfg(feature = "bits")]
|
||||||
use ff::{FieldBits, PrimeFieldBits};
|
use ff::{FieldBits, PrimeFieldBits};
|
||||||
|
|
||||||
use crate::arithmetic::{adc, mac, sbb};
|
use crate::arithmetic::{adc, mac, sbb, FieldExt, Group, SqrtRatio};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
use crate::arithmetic::{FieldExt, Group, SqrtRatio, SqrtTables};
|
use crate::arithmetic::SqrtTables;
|
||||||
|
|
||||||
/// This represents an element of $\mathbb{F}_q$ where
|
/// This represents an element of $\mathbb{F}_q$ where
|
||||||
///
|
///
|
||||||
|
|
@ -224,7 +224,6 @@ const ROOT_OF_UNITY: Fq = Fq::from_raw([
|
||||||
/// GENERATOR^{2^s} where t * 2^s + 1 = q
|
/// GENERATOR^{2^s} where t * 2^s + 1 = q
|
||||||
/// with t odd. In other words, this
|
/// with t odd. In other words, this
|
||||||
/// is a t root of unity.
|
/// is a t root of unity.
|
||||||
#[cfg(feature = "std")]
|
|
||||||
const DELTA: Fq = Fq::from_raw([
|
const DELTA: Fq = Fq::from_raw([
|
||||||
0x8494392472d1683c,
|
0x8494392472d1683c,
|
||||||
0xe3ac3376541d1140,
|
0xe3ac3376541d1140,
|
||||||
|
|
@ -463,7 +462,6 @@ impl<'a> From<&'a Fq> for [u8; 32] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl Group for Fq {
|
impl Group for Fq {
|
||||||
type Scalar = Fq;
|
type Scalar = Fq;
|
||||||
|
|
||||||
|
|
@ -514,13 +512,13 @@ impl ff::Field for Fq {
|
||||||
|
|
||||||
/// Computes the square root of this element, if it exists.
|
/// Computes the square root of this element, if it exists.
|
||||||
fn sqrt(&self) -> CtOption<Self> {
|
fn sqrt(&self) -> CtOption<Self> {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
{
|
{
|
||||||
let (is_square, res) = FQ_TABLES.sqrt_alt(self);
|
let (is_square, res) = FQ_TABLES.sqrt_alt(self);
|
||||||
CtOption::new(res, is_square)
|
CtOption::new(res, is_square)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "sqrt-table"))]
|
||||||
crate::arithmetic::sqrt_tonelli_shanks(self, &T_MINUS1_OVER2)
|
crate::arithmetic::sqrt_tonelli_shanks(self, &T_MINUS1_OVER2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -663,13 +661,13 @@ impl PrimeFieldBits for Fq {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
// The perfect hash parameters are found by `squareroottab.sage` in zcash/pasta.
|
// The perfect hash parameters are found by `squareroottab.sage` in zcash/pasta.
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))]
|
||||||
static ref FQ_TABLES: SqrtTables<Fq> = SqrtTables::new(0x116A9E, 1206);
|
static ref FQ_TABLES: SqrtTables<Fq> = SqrtTables::new(0x116A9E, 1206);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl SqrtRatio for Fq {
|
impl SqrtRatio for Fq {
|
||||||
const T_MINUS1_OVER2: [u64; 4] = T_MINUS1_OVER2;
|
const T_MINUS1_OVER2: [u64; 4] = T_MINUS1_OVER2;
|
||||||
|
|
||||||
|
|
@ -711,16 +709,17 @@ impl SqrtRatio for Fq {
|
||||||
tmp.0[0] as u32
|
tmp.0[0] as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "sqrt-table")]
|
||||||
fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
|
fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
|
||||||
FQ_TABLES.sqrt_ratio(num, div)
|
FQ_TABLES.sqrt_ratio(num, div)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "sqrt-table")]
|
||||||
fn sqrt_alt(&self) -> (Choice, Self) {
|
fn sqrt_alt(&self) -> (Choice, Self) {
|
||||||
FQ_TABLES.sqrt_alt(self)
|
FQ_TABLES.sqrt_alt(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl FieldExt for Fq {
|
impl FieldExt for Fq {
|
||||||
const MODULUS: &'static str =
|
const MODULUS: &'static str =
|
||||||
"0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001";
|
"0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001";
|
||||||
|
|
@ -770,7 +769,7 @@ impl FieldExt for Fq {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(test, feature = "std"))]
|
#[cfg(test)]
|
||||||
use ff::Field;
|
use ff::Field;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -788,7 +787,6 @@ fn test_inv() {
|
||||||
assert_eq!(inv, INV);
|
assert_eq!(inv, INV);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sqrt() {
|
fn test_sqrt() {
|
||||||
// NB: TWO_INV is standing in as a "random" field element
|
// NB: TWO_INV is standing in as a "random" field element
|
||||||
|
|
@ -796,7 +794,6 @@ fn test_sqrt() {
|
||||||
assert!(v == Fq::TWO_INV || (-v) == Fq::TWO_INV);
|
assert!(v == Fq::TWO_INV || (-v) == Fq::TWO_INV);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pow_by_t_minus1_over2() {
|
fn test_pow_by_t_minus1_over2() {
|
||||||
// NB: TWO_INV is standing in as a "random" field element
|
// NB: TWO_INV is standing in as a "random" field element
|
||||||
|
|
@ -804,7 +801,6 @@ fn test_pow_by_t_minus1_over2() {
|
||||||
assert!(v == ff::Field::pow_vartime(&Fq::TWO_INV, &T_MINUS1_OVER2));
|
assert!(v == ff::Field::pow_vartime(&Fq::TWO_INV, &T_MINUS1_OVER2));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sqrt_ratio_and_alt() {
|
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
|
// (true, sqrt(num/div)), if num and div are nonzero and num/div is a square in the field
|
||||||
|
|
@ -851,7 +847,6 @@ fn test_sqrt_ratio_and_alt() {
|
||||||
assert!(v == expected);
|
assert!(v == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_zeta() {
|
fn test_zeta() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -866,7 +861,6 @@ fn test_zeta() {
|
||||||
assert!(c == Fq::one());
|
assert!(c == Fq::one());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_root_of_unity() {
|
fn test_root_of_unity() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -875,19 +869,16 @@ fn test_root_of_unity() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_inv_root_of_unity() {
|
fn test_inv_root_of_unity() {
|
||||||
assert_eq!(Fq::ROOT_OF_UNITY_INV, Fq::root_of_unity().invert().unwrap());
|
assert_eq!(Fq::ROOT_OF_UNITY_INV, Fq::root_of_unity().invert().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_inv_2() {
|
fn test_inv_2() {
|
||||||
assert_eq!(Fq::TWO_INV, Fq::from(2).invert().unwrap());
|
assert_eq!(Fq::TWO_INV, Fq::from(2).invert().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delta() {
|
fn test_delta() {
|
||||||
assert_eq!(Fq::DELTA, GENERATOR.pow(&[1u64 << Fq::S, 0, 0, 0]));
|
assert_eq!(Fq::DELTA, GENERATOR.pow(&[1u64 << Fq::S, 0, 0, 0]));
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
#[cfg(any(feature = "std", test))]
|
#[cfg(any(feature = "std", test))]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue