Migrate remaining FieldExt constants and methods into ff

This commit is contained in:
Jack Grigg 2022-11-24 05:11:46 +00:00
parent bedaa0055c
commit 9862b247d2
7 changed files with 64 additions and 75 deletions

View file

@ -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" }

View file

@ -30,29 +30,7 @@ pub(crate) trait SqrtTableHelpers: 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.
pub trait FieldExt: ff::PrimeField + Ord { pub trait FieldExt: ff::WithSmallOrderMulGroup<3> + Ord {}
/// 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;
}
/// 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")]

View file

@ -18,10 +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};
#[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,

View file

@ -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};
@ -563,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]);
@ -709,36 +728,21 @@ impl SqrtTableHelpers for Fp {
} }
} }
impl FieldExt for Fp { impl FieldExt for Fp {}
const MODULUS: &'static str =
"0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001"; impl WithSmallOrderMulGroup<3> for Fp {
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()),

View file

@ -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};
@ -563,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]);
@ -708,36 +727,21 @@ impl SqrtTableHelpers for Fq {
} }
} }
impl FieldExt for Fq { impl FieldExt for Fq {}
const MODULUS: &'static str =
"0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001"; impl WithSmallOrderMulGroup<3> for Fq {
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()),

View file

@ -1,14 +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, PrimeField}; 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],
@ -73,7 +73,7 @@ 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);
} }
} }

View file

@ -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());