mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-04 20:03:39 +00:00
Merge pull request #55 from zcash/fieldext-finale
Remove `FieldExt` and `Group` traits
This commit is contained in:
commit
85e2664209
10 changed files with 77 additions and 189 deletions
|
|
@ -10,10 +10,11 @@ and this project adheres to Rust's notion of
|
||||||
- Migrated to `ff 0.13`, `group 0.13`.
|
- Migrated to `ff 0.13`, `group 0.13`.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- `pasta_curves::arithmetic::SqrtRatio` (use `ff::Field::{sqrt_ratio, sqrt_alt}`
|
- `pasta_curves::arithmetic`:
|
||||||
instead).
|
- `FieldExt` (use `ff::PrimeField` or `ff::WithSmallOrderMulGroup` instead).
|
||||||
- `pasta_curves::arithmetic::SqrtTables` (from public API, as it isn't suitable
|
- `Group`
|
||||||
for generic usage).
|
- `SqrtRatio` (use `ff::Field::{sqrt_ratio, sqrt_alt}` instead).
|
||||||
|
- `SqrtTables` (from public API, as it isn't suitable for generic usage).
|
||||||
|
|
||||||
## [0.4.1] - 2022-10-13
|
## [0.4.1] - 2022-10-13
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
|
|
@ -74,4 +74,4 @@ uninline-portable = []
|
||||||
serde = ["hex", "serde_crate"]
|
serde = ["hex", "serde_crate"]
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
ff = { git = "https://github.com/zkcrypto/ff.git", rev = "c070ffbaea8cb17e57f817a91ed0e364ff679b7c" }
|
ff = { git = "https://github.com/zkcrypto/ff.git", rev = "054a4d2daf9a9540d4c436fa51f0222e997ad15c" }
|
||||||
|
|
|
||||||
|
|
@ -8,25 +8,4 @@ mod curves;
|
||||||
mod fields;
|
mod fields;
|
||||||
|
|
||||||
pub use curves::*;
|
pub use curves::*;
|
||||||
pub use fields::*;
|
pub(crate) 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.
|
|
||||||
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$.
|
|
||||||
type Scalar: FieldExt;
|
|
||||||
|
|
||||||
/// Returns the additive identity of the group.
|
|
||||||
fn group_zero() -> Self;
|
|
||||||
|
|
||||||
/// Adds `rhs` to this group element.
|
|
||||||
fn group_add(&mut self, rhs: &Self);
|
|
||||||
|
|
||||||
/// Subtracts `rhs` from this group element.
|
|
||||||
fn group_sub(&mut self, rhs: &Self);
|
|
||||||
|
|
||||||
/// Scales this group element by a scalar.
|
|
||||||
fn group_scale(&mut self, by: &Self::Scalar);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,6 @@ use group::prime::{PrimeCurve, PrimeCurveAffine};
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
use super::{FieldExt, Group};
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
|
|
@ -28,12 +25,11 @@ pub trait CurveExt:
|
||||||
+ ConditionallySelectable
|
+ ConditionallySelectable
|
||||||
+ ConstantTimeEq
|
+ ConstantTimeEq
|
||||||
+ From<<Self as PrimeCurve>::Affine>
|
+ From<<Self as PrimeCurve>::Affine>
|
||||||
+ Group<Scalar = <Self as group::Group>::Scalar>
|
|
||||||
{
|
{
|
||||||
/// The scalar field of this elliptic curve.
|
/// The scalar field of this elliptic curve.
|
||||||
type ScalarExt: FieldExt;
|
type ScalarExt: ff::WithSmallOrderMulGroup<3>;
|
||||||
/// The base field over which this elliptic curve is constructed.
|
/// The base field over which this elliptic curve is constructed.
|
||||||
type Base: FieldExt;
|
type Base: ff::WithSmallOrderMulGroup<3>;
|
||||||
/// The affine version of the curve
|
/// The affine version of the curve
|
||||||
type AffineExt: CurveAffine<CurveExt = Self, ScalarExt = <Self as CurveExt>::ScalarExt>
|
type AffineExt: CurveAffine<CurveExt = Self, ScalarExt = <Self as CurveExt>::ScalarExt>
|
||||||
+ Mul<Self::ScalarExt, Output = Self>
|
+ Mul<Self::ScalarExt, Output = Self>
|
||||||
|
|
@ -103,9 +99,9 @@ pub trait CurveAffine:
|
||||||
+ From<<Self as PrimeCurveAffine>::Curve>
|
+ From<<Self as PrimeCurveAffine>::Curve>
|
||||||
{
|
{
|
||||||
/// The scalar field of this elliptic curve.
|
/// The scalar field of this elliptic curve.
|
||||||
type ScalarExt: FieldExt;
|
type ScalarExt: ff::WithSmallOrderMulGroup<3> + Ord;
|
||||||
/// The base field over which this elliptic curve is constructed.
|
/// The base field over which this elliptic curve is constructed.
|
||||||
type Base: FieldExt;
|
type Base: ff::WithSmallOrderMulGroup<3> + Ord;
|
||||||
/// The projective form of the curve
|
/// The projective form of the curve
|
||||||
type CurveExt: CurveExt<AffineExt = Self, ScalarExt = <Self as CurveAffine>::ScalarExt>;
|
type CurveExt: CurveExt<AffineExt = Self, ScalarExt = <Self as CurveAffine>::ScalarExt>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ use core::mem::size_of;
|
||||||
|
|
||||||
use static_assertions::const_assert;
|
use static_assertions::const_assert;
|
||||||
|
|
||||||
use super::Group;
|
|
||||||
|
|
||||||
#[cfg(feature = "sqrt-table")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
#[cfg(feature = "sqrt-table")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
|
|
@ -30,48 +28,18 @@ pub(crate) trait SqrtTableHelpers: ff::PrimeField {
|
||||||
fn get_lower_32(&self) -> u32;
|
fn get_lower_32(&self) -> u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait is a common interface for dealing with elements of a finite
|
|
||||||
/// field.
|
|
||||||
pub trait FieldExt: ff::PrimeField + From<bool> + Ord + Group<Scalar = Self> {
|
|
||||||
/// Modulus of the field written as a string for display purposes
|
|
||||||
const MODULUS: &'static str;
|
|
||||||
|
|
||||||
/// Inverse of `PrimeField::ROOT_OF_UNITY`
|
|
||||||
const ROOT_OF_UNITY_INV: Self;
|
|
||||||
|
|
||||||
/// Generator of the $t-order$ multiplicative subgroup
|
|
||||||
const DELTA: Self;
|
|
||||||
|
|
||||||
/// Inverse of $2$ in the field.
|
|
||||||
const TWO_INV: Self;
|
|
||||||
|
|
||||||
/// Element of multiplicative order $3$.
|
|
||||||
const ZETA: Self;
|
|
||||||
|
|
||||||
/// Obtains a field element congruent to the integer `v`.
|
|
||||||
fn from_u128(v: u128) -> Self;
|
|
||||||
|
|
||||||
/// Obtains a field element that is congruent to the provided little endian
|
|
||||||
/// byte representation of an integer.
|
|
||||||
fn from_bytes_wide(bytes: &[u8; 64]) -> Self;
|
|
||||||
|
|
||||||
/// Gets the lower 128 bits of this field element when expressed
|
|
||||||
/// canonically.
|
|
||||||
fn get_lower_128(&self) -> u128;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parameters for a perfect hash function used in square root computation.
|
/// Parameters for a perfect hash function used in square root computation.
|
||||||
#[cfg(feature = "sqrt-table")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SqrtHasher<F: FieldExt> {
|
struct SqrtHasher<F: SqrtTableHelpers> {
|
||||||
hash_xor: u32,
|
hash_xor: u32,
|
||||||
hash_mod: usize,
|
hash_mod: usize,
|
||||||
marker: PhantomData<F>,
|
marker: PhantomData<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "sqrt-table")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
impl<F: FieldExt + SqrtTableHelpers> SqrtHasher<F> {
|
impl<F: SqrtTableHelpers> 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 {
|
||||||
// This is just the simplest constant-time perfect hash construction that could
|
// This is just the simplest constant-time perfect hash construction that could
|
||||||
|
|
@ -86,7 +54,7 @@ impl<F: FieldExt + SqrtTableHelpers> SqrtHasher<F> {
|
||||||
#[cfg(feature = "sqrt-table")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct SqrtTables<F: FieldExt> {
|
pub(crate) struct SqrtTables<F: SqrtTableHelpers> {
|
||||||
hasher: SqrtHasher<F>,
|
hasher: SqrtHasher<F>,
|
||||||
inv: Vec<u8>,
|
inv: Vec<u8>,
|
||||||
g0: Box<[F; 256]>,
|
g0: Box<[F; 256]>,
|
||||||
|
|
@ -96,7 +64,7 @@ pub(crate) struct SqrtTables<F: FieldExt> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "sqrt-table")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
impl<F: FieldExt + SqrtTableHelpers> SqrtTables<F> {
|
impl<F: SqrtTableHelpers> 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 alloc::vec;
|
use alloc::vec;
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,13 @@ use group::{
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
use ff::WithSmallOrderMulGroup;
|
||||||
|
|
||||||
use super::{Fp, Fq};
|
use super::{Fp, Fq};
|
||||||
use crate::arithmetic::Group;
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use crate::arithmetic::{Coordinates, CurveAffine, CurveExt, FieldExt};
|
use crate::arithmetic::{Coordinates, CurveAffine, CurveExt};
|
||||||
|
|
||||||
macro_rules! new_curve_impl {
|
macro_rules! new_curve_impl {
|
||||||
(($($privacy:tt)*), $name:ident, $name_affine:ident, $iso:ident, $base:ident, $scalar:ident,
|
(($($privacy:tt)*), $name:ident, $name_affine:ident, $iso:ident, $base:ident, $scalar:ident,
|
||||||
|
|
@ -783,23 +785,6 @@ macro_rules! new_curve_impl {
|
||||||
impl_binops_multiplicative!($name, $scalar);
|
impl_binops_multiplicative!($name, $scalar);
|
||||||
impl_binops_multiplicative_mixed!($name_affine, $scalar, $name);
|
impl_binops_multiplicative_mixed!($name_affine, $scalar, $name);
|
||||||
|
|
||||||
impl Group for $name {
|
|
||||||
type Scalar = $scalar;
|
|
||||||
|
|
||||||
fn group_zero() -> Self {
|
|
||||||
Self::identity()
|
|
||||||
}
|
|
||||||
fn group_add(&mut self, rhs: &Self) {
|
|
||||||
*self += *rhs;
|
|
||||||
}
|
|
||||||
fn group_sub(&mut self, rhs: &Self) {
|
|
||||||
*self -= *rhs;
|
|
||||||
}
|
|
||||||
fn group_scale(&mut self, by: &Self::Scalar) {
|
|
||||||
*self *= *by;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gpu")]
|
#[cfg(feature = "gpu")]
|
||||||
impl ec_gpu::GpuName for $name_affine {
|
impl ec_gpu::GpuName for $name_affine {
|
||||||
fn name() -> alloc::string::String {
|
fn name() -> alloc::string::String {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops::{Add, Mul, Neg, Sub};
|
use core::ops::{Add, Mul, Neg, Sub};
|
||||||
|
|
||||||
use ff::{Field, PrimeField};
|
use ff::{Field, FromUniformBytes, PrimeField, WithSmallOrderMulGroup};
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@ 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, FieldExt, Group, SqrtTableHelpers};
|
use crate::arithmetic::{adc, mac, sbb, SqrtTableHelpers};
|
||||||
|
|
||||||
#[cfg(feature = "sqrt-table")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
use crate::arithmetic::SqrtTables;
|
use crate::arithmetic::SqrtTables;
|
||||||
|
|
@ -475,23 +475,6 @@ impl<'a> From<&'a Fp> for [u8; 32] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Group for Fp {
|
|
||||||
type Scalar = Fp;
|
|
||||||
|
|
||||||
fn group_zero() -> Self {
|
|
||||||
Self::zero()
|
|
||||||
}
|
|
||||||
fn group_add(&mut self, rhs: &Self) {
|
|
||||||
*self += *rhs;
|
|
||||||
}
|
|
||||||
fn group_sub(&mut self, rhs: &Self) {
|
|
||||||
*self -= *rhs;
|
|
||||||
}
|
|
||||||
fn group_scale(&mut self, by: &Self::Scalar) {
|
|
||||||
*self *= *by;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ff::Field for Fp {
|
impl ff::Field for Fp {
|
||||||
const ZERO: Self = Self::zero();
|
const ZERO: Self = Self::zero();
|
||||||
const ONE: Self = Self::one();
|
const ONE: Self = Self::one();
|
||||||
|
|
@ -580,11 +563,30 @@ impl ff::Field for Fp {
|
||||||
impl ff::PrimeField for Fp {
|
impl ff::PrimeField for Fp {
|
||||||
type Repr = [u8; 32];
|
type Repr = [u8; 32];
|
||||||
|
|
||||||
|
const MODULUS: &'static str =
|
||||||
|
"0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001";
|
||||||
|
const TWO_INV: Self = Fp::from_raw([
|
||||||
|
0xcc96987680000001,
|
||||||
|
0x11234c7e04a67c8d,
|
||||||
|
0x0000000000000000,
|
||||||
|
0x2000000000000000,
|
||||||
|
]);
|
||||||
const NUM_BITS: u32 = 255;
|
const NUM_BITS: u32 = 255;
|
||||||
const CAPACITY: u32 = 254;
|
const CAPACITY: u32 = 254;
|
||||||
const MULTIPLICATIVE_GENERATOR: Self = GENERATOR;
|
const MULTIPLICATIVE_GENERATOR: Self = GENERATOR;
|
||||||
const S: u32 = S;
|
const S: u32 = S;
|
||||||
const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
|
const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
|
||||||
|
const ROOT_OF_UNITY_INV: Self = Fp::from_raw([
|
||||||
|
0xf0b87c7db2ce91f6,
|
||||||
|
0x84a0a1d8859f066f,
|
||||||
|
0xb4ed8e647196dad1,
|
||||||
|
0x2cd5282c53116b5c,
|
||||||
|
]);
|
||||||
|
const DELTA: Self = DELTA;
|
||||||
|
|
||||||
|
fn from_u128(v: u128) -> Self {
|
||||||
|
Fp::from_raw([v as u64, (v >> 64) as u64, 0, 0])
|
||||||
|
}
|
||||||
|
|
||||||
fn from_repr(repr: Self::Repr) -> CtOption<Self> {
|
fn from_repr(repr: Self::Repr) -> CtOption<Self> {
|
||||||
let mut tmp = Fp([0, 0, 0, 0]);
|
let mut tmp = Fp([0, 0, 0, 0]);
|
||||||
|
|
@ -726,36 +728,19 @@ impl SqrtTableHelpers for Fp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FieldExt for Fp {
|
impl WithSmallOrderMulGroup<3> for Fp {
|
||||||
const MODULUS: &'static str =
|
|
||||||
"0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001";
|
|
||||||
const ROOT_OF_UNITY_INV: Self = Fp::from_raw([
|
|
||||||
0xf0b87c7db2ce91f6,
|
|
||||||
0x84a0a1d8859f066f,
|
|
||||||
0xb4ed8e647196dad1,
|
|
||||||
0x2cd5282c53116b5c,
|
|
||||||
]);
|
|
||||||
const DELTA: Self = DELTA;
|
|
||||||
const TWO_INV: Self = Fp::from_raw([
|
|
||||||
0xcc96987680000001,
|
|
||||||
0x11234c7e04a67c8d,
|
|
||||||
0x0000000000000000,
|
|
||||||
0x2000000000000000,
|
|
||||||
]);
|
|
||||||
const ZETA: Self = Fp::from_raw([
|
const ZETA: Self = Fp::from_raw([
|
||||||
0x1dad5ebdfdfe4ab9,
|
0x1dad5ebdfdfe4ab9,
|
||||||
0x1d1f8bd237ad3149,
|
0x1d1f8bd237ad3149,
|
||||||
0x2caad5dc57aab1b0,
|
0x2caad5dc57aab1b0,
|
||||||
0x12ccca834acdba71,
|
0x12ccca834acdba71,
|
||||||
]);
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
fn from_u128(v: u128) -> Self {
|
impl FromUniformBytes<64> for Fp {
|
||||||
Fp::from_raw([v as u64, (v >> 64) as u64, 0, 0])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a 512-bit little endian integer into
|
/// Converts a 512-bit little endian integer into
|
||||||
/// a `Fp` by reducing by the modulus.
|
/// a `Fp` by reducing by the modulus.
|
||||||
fn from_bytes_wide(bytes: &[u8; 64]) -> Fp {
|
fn from_uniform_bytes(bytes: &[u8; 64]) -> Fp {
|
||||||
Fp::from_u512([
|
Fp::from_u512([
|
||||||
u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
|
u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
|
||||||
u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
|
u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
|
||||||
|
|
@ -767,12 +752,6 @@ impl FieldExt for Fp {
|
||||||
u64::from_le_bytes(bytes[56..64].try_into().unwrap()),
|
u64::from_le_bytes(bytes[56..64].try_into().unwrap()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_lower_128(&self) -> u128 {
|
|
||||||
let tmp = Fp::montgomery_reduce(self.0[0], self.0[1], self.0[2], self.0[3], 0, 0, 0, 0);
|
|
||||||
|
|
||||||
u128::from(tmp.0[0]) | (u128::from(tmp.0[1]) << 64)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gpu")]
|
#[cfg(feature = "gpu")]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops::{Add, Mul, Neg, Sub};
|
use core::ops::{Add, Mul, Neg, Sub};
|
||||||
|
|
||||||
use ff::{Field, PrimeField};
|
use ff::{Field, FromUniformBytes, PrimeField, WithSmallOrderMulGroup};
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@ 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, FieldExt, Group, SqrtTableHelpers};
|
use crate::arithmetic::{adc, mac, sbb, SqrtTableHelpers};
|
||||||
|
|
||||||
#[cfg(feature = "sqrt-table")]
|
#[cfg(feature = "sqrt-table")]
|
||||||
use crate::arithmetic::SqrtTables;
|
use crate::arithmetic::SqrtTables;
|
||||||
|
|
@ -475,23 +475,6 @@ impl<'a> From<&'a Fq> for [u8; 32] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Group for Fq {
|
|
||||||
type Scalar = Fq;
|
|
||||||
|
|
||||||
fn group_zero() -> Self {
|
|
||||||
Self::zero()
|
|
||||||
}
|
|
||||||
fn group_add(&mut self, rhs: &Self) {
|
|
||||||
*self += *rhs;
|
|
||||||
}
|
|
||||||
fn group_sub(&mut self, rhs: &Self) {
|
|
||||||
*self -= *rhs;
|
|
||||||
}
|
|
||||||
fn group_scale(&mut self, by: &Self::Scalar) {
|
|
||||||
*self *= *by;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ff::Field for Fq {
|
impl ff::Field for Fq {
|
||||||
const ZERO: Self = Self::zero();
|
const ZERO: Self = Self::zero();
|
||||||
const ONE: Self = Self::one();
|
const ONE: Self = Self::one();
|
||||||
|
|
@ -580,11 +563,30 @@ impl ff::Field for Fq {
|
||||||
impl ff::PrimeField for Fq {
|
impl ff::PrimeField for Fq {
|
||||||
type Repr = [u8; 32];
|
type Repr = [u8; 32];
|
||||||
|
|
||||||
|
const MODULUS: &'static str =
|
||||||
|
"0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001";
|
||||||
const NUM_BITS: u32 = 255;
|
const NUM_BITS: u32 = 255;
|
||||||
const CAPACITY: u32 = 254;
|
const CAPACITY: u32 = 254;
|
||||||
|
const TWO_INV: Self = Fq::from_raw([
|
||||||
|
0xc623759080000001,
|
||||||
|
0x11234c7e04ca546e,
|
||||||
|
0x0000000000000000,
|
||||||
|
0x2000000000000000,
|
||||||
|
]);
|
||||||
const MULTIPLICATIVE_GENERATOR: Self = GENERATOR;
|
const MULTIPLICATIVE_GENERATOR: Self = GENERATOR;
|
||||||
const S: u32 = S;
|
const S: u32 = S;
|
||||||
const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
|
const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
|
||||||
|
const ROOT_OF_UNITY_INV: Self = Fq::from_raw([
|
||||||
|
0x57eecda0a84b6836,
|
||||||
|
0x4ad38b9084b8a80c,
|
||||||
|
0xf4c8f353124086c1,
|
||||||
|
0x2235e1a7415bf936,
|
||||||
|
]);
|
||||||
|
const DELTA: Self = DELTA;
|
||||||
|
|
||||||
|
fn from_u128(v: u128) -> Self {
|
||||||
|
Fq::from_raw([v as u64, (v >> 64) as u64, 0, 0])
|
||||||
|
}
|
||||||
|
|
||||||
fn from_repr(repr: Self::Repr) -> CtOption<Self> {
|
fn from_repr(repr: Self::Repr) -> CtOption<Self> {
|
||||||
let mut tmp = Fq([0, 0, 0, 0]);
|
let mut tmp = Fq([0, 0, 0, 0]);
|
||||||
|
|
@ -725,36 +727,19 @@ impl SqrtTableHelpers for Fq {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FieldExt for Fq {
|
impl WithSmallOrderMulGroup<3> for Fq {
|
||||||
const MODULUS: &'static str =
|
|
||||||
"0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001";
|
|
||||||
const ROOT_OF_UNITY_INV: Self = Fq::from_raw([
|
|
||||||
0x57eecda0a84b6836,
|
|
||||||
0x4ad38b9084b8a80c,
|
|
||||||
0xf4c8f353124086c1,
|
|
||||||
0x2235e1a7415bf936,
|
|
||||||
]);
|
|
||||||
const DELTA: Self = DELTA;
|
|
||||||
const TWO_INV: Self = Fq::from_raw([
|
|
||||||
0xc623759080000001,
|
|
||||||
0x11234c7e04ca546e,
|
|
||||||
0x0000000000000000,
|
|
||||||
0x2000000000000000,
|
|
||||||
]);
|
|
||||||
const ZETA: Self = Fq::from_raw([
|
const ZETA: Self = Fq::from_raw([
|
||||||
0x2aa9d2e050aa0e4f,
|
0x2aa9d2e050aa0e4f,
|
||||||
0x0fed467d47c033af,
|
0x0fed467d47c033af,
|
||||||
0x511db4d81cf70f5a,
|
0x511db4d81cf70f5a,
|
||||||
0x06819a58283e528e,
|
0x06819a58283e528e,
|
||||||
]);
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
fn from_u128(v: u128) -> Self {
|
impl FromUniformBytes<64> for Fq {
|
||||||
Fq::from_raw([v as u64, (v >> 64) as u64, 0, 0])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a 512-bit little endian integer into
|
/// Converts a 512-bit little endian integer into
|
||||||
/// a `Fq` by reducing by the modulus.
|
/// a `Fq` by reducing by the modulus.
|
||||||
fn from_bytes_wide(bytes: &[u8; 64]) -> Fq {
|
fn from_uniform_bytes(bytes: &[u8; 64]) -> Fq {
|
||||||
Fq::from_u512([
|
Fq::from_u512([
|
||||||
u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
|
u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
|
||||||
u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
|
u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
|
||||||
|
|
@ -766,12 +751,6 @@ impl FieldExt for Fq {
|
||||||
u64::from_le_bytes(bytes[56..64].try_into().unwrap()),
|
u64::from_le_bytes(bytes[56..64].try_into().unwrap()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_lower_128(&self) -> u128 {
|
|
||||||
let tmp = Fq::montgomery_reduce(self.0[0], self.0[1], self.0[2], self.0[3], 0, 0, 0, 0);
|
|
||||||
|
|
||||||
u128::from(tmp.0[0]) | (u128::from(tmp.0[1]) << 64)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gpu")]
|
#[cfg(feature = "gpu")]
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
//! This module implements "simplified SWU" hashing to short Weierstrass curves
|
//! This module implements "simplified SWU" hashing to short Weierstrass curves
|
||||||
//! with a = 0.
|
//! with a = 0.
|
||||||
|
|
||||||
|
use ff::{Field, FromUniformBytes, PrimeField};
|
||||||
use static_assertions::const_assert;
|
use static_assertions::const_assert;
|
||||||
use subtle::ConstantTimeEq;
|
use subtle::ConstantTimeEq;
|
||||||
|
|
||||||
use crate::arithmetic::{CurveExt, FieldExt};
|
use crate::arithmetic::CurveExt;
|
||||||
|
|
||||||
/// Hashes over a message and writes the output to all of `buf`.
|
/// Hashes over a message and writes the output to all of `buf`.
|
||||||
pub fn hash_to_field<F: FieldExt>(
|
pub fn hash_to_field<F: FromUniformBytes<64>>(
|
||||||
curve_id: &str,
|
curve_id: &str,
|
||||||
domain_prefix: &str,
|
domain_prefix: &str,
|
||||||
message: &[u8],
|
message: &[u8],
|
||||||
|
|
@ -72,12 +73,12 @@ pub fn hash_to_field<F: FieldExt>(
|
||||||
let mut little = [0u8; CHUNKLEN];
|
let mut little = [0u8; CHUNKLEN];
|
||||||
little.copy_from_slice(big.as_array());
|
little.copy_from_slice(big.as_array());
|
||||||
little.reverse();
|
little.reverse();
|
||||||
*buf = F::from_bytes_wide(&little);
|
*buf = F::from_uniform_bytes(&little);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implements a degree 3 isogeny map.
|
/// Implements a degree 3 isogeny map.
|
||||||
pub fn iso_map<F: FieldExt, C: CurveExt<Base = F>, I: CurveExt<Base = F>>(
|
pub fn iso_map<F: Field, C: CurveExt<Base = F>, I: CurveExt<Base = F>>(
|
||||||
p: &I,
|
p: &I,
|
||||||
iso: &[C::Base; 13],
|
iso: &[C::Base; 13],
|
||||||
) -> C {
|
) -> C {
|
||||||
|
|
@ -105,7 +106,7 @@ pub fn iso_map<F: FieldExt, C: CurveExt<Base = F>, I: CurveExt<Base = F>>(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::many_single_char_names)]
|
#[allow(clippy::many_single_char_names)]
|
||||||
pub fn map_to_curve_simple_swu<F: FieldExt, C: CurveExt<Base = F>, I: CurveExt<Base = F>>(
|
pub fn map_to_curve_simple_swu<F: PrimeField, C: CurveExt<Base = F>, I: CurveExt<Base = F>>(
|
||||||
u: &F,
|
u: &F,
|
||||||
theta: F,
|
theta: F,
|
||||||
z: F,
|
z: F,
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@ pub extern crate group;
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_endo_consistency() {
|
fn test_endo_consistency() {
|
||||||
use crate::arithmetic::{CurveExt, FieldExt};
|
use crate::arithmetic::CurveExt;
|
||||||
use group::Group;
|
use group::{ff::WithSmallOrderMulGroup, Group};
|
||||||
|
|
||||||
let a = pallas::Point::generator();
|
let a = pallas::Point::generator();
|
||||||
assert_eq!(a * pallas::Scalar::ZETA, a.endo());
|
assert_eq!(a * pallas::Scalar::ZETA, a.endo());
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue