Skip to content

Commit

Permalink
[wip] cleanup dead code
Browse files Browse the repository at this point in the history
  • Loading branch information
trbritt committed Aug 16, 2024
1 parent 083164c commit 86c800b
Show file tree
Hide file tree
Showing 15 changed files with 123 additions and 167 deletions.
5 changes: 2 additions & 3 deletions src/fields/extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,11 @@ impl<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>> From<u64>
Self::new(&retval)
}
}
#[allow(dead_code)]
impl<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>> FieldExtension<D, N, F> {
pub(crate) const fn new(c: &[F; N]) -> Self {
pub const fn new(c: &[F; N]) -> Self {
Self(*c)
}
pub(crate) fn scale(&self, factor: F) -> Self {
pub fn scale(&self, factor: F) -> Self {
let mut i = 0;
let mut retval = [F::zero(); N];
while i < N {
Expand Down
53 changes: 18 additions & 35 deletions src/fields/fp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ use num_traits::{Euclid, Inv, One, Pow, Zero};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
use subtle::CtOption;

pub(crate) const BN254_FP_MODULUS: Fp = Fp::new(U256::from_words([
0x3C208C16D87CFD47,
0x97816A916871CA8D,
0xB85045B68181585D,
0x30644E72E131A029,
]));
/// This defines the key properties of a field extension. Now, mathematically,
/// a finite field satisfies many rigorous mathematical properties. The
/// (non-exhaustive) list below simply suffices to illustrate those properties
Expand Down Expand Up @@ -74,15 +80,12 @@ pub(crate) trait FieldExtensionTrait<const D: usize, const N: usize>:
// heavily such a value below
fn quadratic_non_residue() -> Self;
// this endomorphism is key for twist operations
#[allow(dead_code)]
fn frobenius(&self, exponent: usize) -> Self;
// specialized algorithms exist in each extension
// for sqrt and square, simply helper functions really
#[allow(dead_code)]
fn sqrt(&self) -> CtOption<Self>;
fn square(&self) -> Self;

#[allow(dead_code)]
fn rand<R: CryptoRngCore>(rng: &mut R) -> Self;

fn is_square(&self) -> Choice;
Expand All @@ -91,7 +94,7 @@ pub(crate) trait FieldExtensionTrait<const D: usize, const N: usize>:

fn curve_constant() -> Self;
}
pub(crate) trait FinitePrimeField<const DLIMBS: usize, UintType, const D: usize, const N: usize>:
pub trait FinitePrimeField<const DLIMBS: usize, UintType, const D: usize, const N: usize>:
FieldExtensionTrait<D, N> + Rem<Output = Self> + Euclid + Pow<U256> + From<u64>
where
UintType: ConcatMixed<MixedOutput = Uint<DLIMBS>>,
Expand All @@ -115,18 +118,18 @@ macro_rules! define_finite_prime_field {
//special struct for const-time arithmetic on montgomery form integers mod p
type $output = crypto_bigint::modular::ConstMontyForm<$mod_struct, { $mod_struct::LIMBS }>;
#[derive(Clone, Debug, Copy)] //to be used in const contexts
pub(crate) struct $wrapper_name($mod_struct, $output);
#[allow(dead_code)]
pub struct $wrapper_name($mod_struct, $output);

impl FinitePrimeField<$limbs, $uint_type, $degree, $nreps> for $wrapper_name {}
#[allow(dead_code)]

impl $wrapper_name {
// builder structure to create elements in the base field of a given value
pub(crate) const fn new(value: $uint_type) -> Self {
pub const fn new(value: $uint_type) -> Self {
Self($mod_struct, $output::new(&value))
}
#[allow(dead_code)] // this is indeed used in the test cases, which are ignored by
// this is indeed used in the test cases, which are ignored by
// the linter
pub(crate) fn new_from_str(value: &str) -> Option<Self> {
pub fn new_from_str(value: &str) -> Option<Self> {
let ints: Vec<_> = {
let mut acc = Self::zero();
(0..11)
Expand All @@ -150,10 +153,10 @@ macro_rules! define_finite_prime_field {
Some(res)
}
// take the element and convert it to "normal" form from montgomery form
pub(crate) const fn value(&self) -> $uint_type {
pub const fn value(&self) -> $uint_type {
self.1.retrieve()
}
pub(crate) fn characteristic() -> $uint_type {
pub fn characteristic() -> $uint_type {
<$uint_type>::from($mod_struct::MODULUS.as_nz_ref().get())
}
pub const ZERO: Self = Self::new(<$uint_type>::from_words([0x0; 4]));
Expand All @@ -170,12 +173,7 @@ macro_rules! define_finite_prime_field {
fn quadratic_non_residue() -> Self {
//this is p - 1 mod p = -1 mod p = 0 - 1 mod p
// = -1
Self::new(U256::from_words([
4332616871279656262,
10917124144477883021,
13281191951274694749,
3486998266802970665,
]))
Self::new((-Self::ONE).1.retrieve())
}
fn frobenius(&self, _exponent: usize) -> Self {
Self::zero()
Expand Down Expand Up @@ -483,25 +481,10 @@ impl FieldExtensionTrait<2, 2> for Fp {
#[cfg(test)]
mod tests {
use super::*;
const MODULUS: [u64; 4] = [
0x3C208C16D87CFD47,
0x97816A916871CA8D,
0xB85045B68181585D,
0x30644E72E131A029,
];

fn create_field(value: [u64; 4]) -> Fp {
Fp::new(U256::from_words(value))
}
mod test_modulus_conversion {
use super::*;
#[test]
fn test_modulus() {
for i in U256::from_be_hex(BN254_MOD_STRING).as_limbs() {
println!("{:X}", i.0);
}
}
}
mod addition_tests {
use super::*;

Expand Down Expand Up @@ -545,7 +528,7 @@ mod tests {
);

// Addition that wraps around the modulus
let e = create_field(MODULUS);
let e = BN254_FP_MODULUS;
let f = create_field([1, 0, 0, 0]);
assert_eq!(
(e + f).value(),
Expand Down Expand Up @@ -633,7 +616,7 @@ mod tests {
);

// Subtraction resulting in zero
let g = create_field(MODULUS);
let g = BN254_FP_MODULUS;
assert_eq!(
(g - g).value(),
U256::from_words([0, 0, 0, 0]),
Expand Down
32 changes: 16 additions & 16 deletions src/fields/fp12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ use crate::fields::extensions::FieldExtension;
use crate::fields::fp::{FieldExtensionTrait, Fp};
use crate::fields::fp2::Fp2;
use crate::fields::fp6::Fp6;
use crate::fields::utils::u256_to_u4096;
use crypto_bigint::{rand_core::CryptoRngCore, subtle::ConditionallySelectable, U256, U4096};
use crypto_bigint::{rand_core::CryptoRngCore, subtle::ConditionallySelectable, U256};
use num_traits::{Inv, One, Zero};
use std::ops::{Div, DivAssign, Mul, MulAssign};
use subtle::{Choice, CtOption};
Expand Down Expand Up @@ -163,26 +162,27 @@ const FROBENIUS_COEFF_FP12_C1: &[Fp2; 12] = &[
])),
]),
];
pub(crate) type Fp12 = FieldExtension<12, 2, Fp6>;
const FP12_QUADRATIC_NON_RESIDUE: Fp12 = Fp12::new(&[
Fp6::new(&[
Fp2::new(&[Fp::ZERO, Fp::ZERO]),
Fp2::new(&[Fp::ZERO, Fp::ZERO]),
Fp2::new(&[Fp::ZERO, Fp::ZERO]),
]),
Fp6::new(&[
Fp2::new(&[Fp::ONE, Fp::ZERO]),
Fp2::new(&[Fp::ZERO, Fp::ZERO]),
Fp2::new(&[Fp::ZERO, Fp::ZERO]),
]),
]);

impl Fp12 {
// we have no need to define a residue multiplication since this
// is the top of our tower extension
#[allow(dead_code)]
fn characteristic() -> U4096 {
let wide_p = u256_to_u4096(&Fp::characteristic());
let wide_p2 = wide_p * wide_p;
let wide_p6 = wide_p2 * wide_p2 * wide_p2;
wide_p6 * wide_p6
}
}
pub(crate) type Fp12 = FieldExtension<12, 2, Fp6>;

impl FieldExtensionTrait<12, 2> for Fp12 {
fn quadratic_non_residue() -> Self {
Self::new(&[Fp6::zero(), Fp6::one()])
// Self::new(&[Fp6::zero(), Fp6::one()])
FP12_QUADRATIC_NON_RESIDUE
}
fn frobenius(&self, exponent: usize) -> Self {
// TODO: integrate generic D into struct to not hardcode degrees
Self::new(&[
<Fp6 as FieldExtensionTrait<6, 3>>::frobenius(&self.0[0], exponent),
<Fp6 as FieldExtensionTrait<6, 3>>::frobenius(&self.0[1], exponent)
Expand Down
71 changes: 41 additions & 30 deletions src/fields/fp2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
//! that elements of this field are represented as a_0 + a_1*X. This implements
//! the specific behaviour for this extension, such as multiplication.
use crate::fields::extensions::FieldExtension;
use crate::fields::fp::{FieldExtensionTrait, Fp};
use crate::fields::utils::u256_to_u512;
use crate::fields::fp::{FieldExtensionTrait, Fp, BN254_FP_MODULUS};
use crypto_bigint::{rand_core::CryptoRngCore, subtle::ConditionallySelectable, U256, U512};
use num_traits::{Inv, One, Pow, Zero};
use std::ops::{Div, DivAssign, Mul, MulAssign};
Expand All @@ -17,23 +16,45 @@ pub(crate) const TWO_INV: Fp = Fp::new(U256::from_words([
15863968012492123182,
1743499133401485332,
]));

// (BN254_FP_MODULUS - Fp::THREE)/Fp::FOUR
const P_MINUS_3_OVER_4: Fp = Fp::new(U256::from_words([
5694840236247301969,
7340967054546858659,
7931984006246061591,
871749566700742666,
]));
// (BN254_FP_MODULUS - Fp::ONE)/Fp::TWO
const P_MINUS_1_OVER_2: Fp = Fp::new(U256::from_words([
11389680472494603939,
14681934109093717318,
15863968012492123182,
1743499133401485332,
]));
const FP2_TWIST_CURVE_CONSTANT: Fp2 = Fp2::new(&[
Fp::new(U256::from_words([
3632125457679333605,
13093307605518643107,
9348936922344483523,
3104278944836790958,
])),
Fp::new(U256::from_words([
16474938222586303954,
12056031220135172178,
14784384838321896948,
42524369107353300,
])),
]);
pub(crate) type Fp2 = FieldExtension<2, 2, Fp>;

// there are some specific things that must be defined as
// helper functions for us on this specific extension, but
// don't generalize to any extension.
impl Fp2 {
// variable runtime with respect to the input argument,
// aka the size of the argument to the exponentiation.
// the naming convention makes it explicit to us that
// this should be used only in scenarios where we know
// precisely what we're doing to not expose vectors
// for side channel attacks in our api.
// the below is not exposed publicly
#[allow(dead_code)]
pub(crate) fn pow_vartime(&self, by: &[u64]) -> Self {
pub(crate) fn pow(&self, by: &Fp) -> Self {
let bits = by.value().to_words();
let mut res = Self::one();
for e in by.iter().rev() {
for e in bits.iter().rev() {
for i in (0..64).rev() {
res = res * res;
if ((*e >> i) & 1) == 1 {
Expand All @@ -43,13 +64,7 @@ impl Fp2 {
}
res
}
// type casting must be done on case-by-case basis
#[allow(dead_code)]
fn characteristic() -> U512 {
let wide_p = u256_to_u512(&Fp::characteristic());
wide_p * wide_p
}


pub(crate) fn residue_mul(&self) -> Self {
*self * FP2_QUADRATIC_NON_RESIDUE
}
Expand All @@ -74,13 +89,10 @@ impl FieldExtensionTrait<2, 2> for Fp2 {
}
}
fn sqrt(&self) -> CtOption<Self> {
let p_minus_3_over_4 = ((Fp::new(Fp::characteristic()) - Fp::THREE) / Fp::FOUR).value();
let p_minus_1_over_2 = ((Fp::new(Fp::characteristic()) - Fp::ONE) / Fp::TWO).value();
let p = Fp::characteristic();
let a1 = self.pow_vartime(&p_minus_3_over_4.to_words());
let a1 = self.pow(&P_MINUS_3_OVER_4);

let alpha = a1 * a1 * (*self);
let a0 = alpha.pow_vartime(&p.to_words());
let a0 = alpha.pow(&BN254_FP_MODULUS);
if a0 == -Fp2::one() {
return CtOption::new(Fp2::zero(), Choice::from(0u8));
}
Expand All @@ -93,7 +105,7 @@ impl FieldExtensionTrait<2, 2> for Fp2 {
<Fp2 as FieldExtensionTrait<2, 2>>::square(&sqrt).ct_eq(self),
)
} else {
let b = (alpha + Fp2::one()).pow_vartime(&p_minus_1_over_2.to_words());
let b = (alpha + Fp2::one()).pow(&P_MINUS_1_OVER_2);
let sqrt = b * a1 * (*self);
CtOption::new(
sqrt,
Expand All @@ -119,8 +131,7 @@ impl FieldExtensionTrait<2, 2> for Fp2 {
}
fn is_square(&self) -> Choice {
let legendre = |x: &Fp| -> i32 {
let exp = ((Fp::new(Fp::characteristic()) - Fp::ONE) / Fp::from(2)).value();
let res = x.pow(exp);
let res = x.pow(P_MINUS_1_OVER_2.value());

if res.is_one() {
1
Expand All @@ -144,7 +155,8 @@ impl FieldExtensionTrait<2, 2> for Fp2 {
fn curve_constant() -> Self {
// this is the curve constant for the twist curve in Fp2. In short Weierstrass form the
// curve over the twist is $y'^2 = x'^3 + b$, where $b=3/(9+u)$, which is the below.
Self::from(3) / FP2_QUADRATIC_NON_RESIDUE
// Self::THREE / FP2_QUADRATIC_NON_RESIDUE
FP2_TWIST_CURVE_CONSTANT
}
}

Expand All @@ -156,7 +168,6 @@ impl Mul for Fp2 {
// multiplication.
// See https://eprint.iacr.org/2006/471.pdf, Sec 3
// We create the addition chain from Algo 1 of https://eprint.iacr.org/2022/367.pdf
// TODO: Implement optimized squaring algorithm in base field?
let t0 = self.0[0] * other.0[0];
let t1 = self.0[1] * other.0[1];

Expand Down Expand Up @@ -424,7 +435,7 @@ mod tests {
let q = FP2_QUADRATIC_NON_RESIDUE;
let a1 = (Fp::new(Fp::characteristic()) - Fp::from(1)) / Fp::from(3);

let c1_1 = q.pow_vartime(&a1.value().to_words());
let c1_1 = q.pow(&a1);
let c1_1_real = create_field_extension(
[
0x99e39557176f553d,
Expand Down
Loading

0 comments on commit 86c800b

Please sign in to comment.