Skip to content

Commit

Permalink
Unify model configs (#580)
Browse files Browse the repository at this point in the history
* move final exp and miller loop to BnConfig trait

* move final exp and miller loop to MNT4 Config trait

* move final exp and miller loop to MNT6 Config trait

* cargo fmt
  • Loading branch information
mmagician authored Jan 16, 2023
1 parent c5a4d73 commit 24496c9
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 110 deletions.
155 changes: 83 additions & 72 deletions ec/src/models/bn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub enum TwistType {
D,
}

pub trait BnConfig: 'static {
pub trait BnConfig: 'static + Sized {
/// The absolute value of the BN curve parameter `X`
/// (as in `q = 36 X^4 + 36 X^3 + 24 X^2 + 6 X + 1`).
const X: &'static [u64];
Expand All @@ -46,65 +46,11 @@ pub trait BnConfig: 'static {
BaseField = Fp2<Self::Fp2Config>,
ScalarField = <Self::G1Config as CurveConfig>::ScalarField,
>;
}

pub mod g1;
pub mod g2;

pub use self::{
g1::{G1Affine, G1Prepared, G1Projective},
g2::{G2Affine, G2Prepared, G2Projective},
};

#[derive(Derivative)]
#[derivative(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct Bn<P: BnConfig>(PhantomData<fn() -> P>);

impl<P: BnConfig> Bn<P> {
/// Evaluates the line function at point p.
fn ell(f: &mut Fp12<P::Fp12Config>, coeffs: &g2::EllCoeff<P>, p: &G1Affine<P>) {
let mut c0 = coeffs.0;
let mut c1 = coeffs.1;
let mut c2 = coeffs.2;

match P::TWIST_TYPE {
TwistType::M => {
c2.mul_assign_by_fp(&p.y);
c1.mul_assign_by_fp(&p.x);
f.mul_by_014(&c0, &c1, &c2);
},
TwistType::D => {
c0.mul_assign_by_fp(&p.y);
c1.mul_assign_by_fp(&p.x);
f.mul_by_034(&c0, &c1, &c2);
},
}
}

fn exp_by_neg_x(mut f: Fp12<P::Fp12Config>) -> Fp12<P::Fp12Config> {
f = f.cyclotomic_exp(P::X);
if !P::X_IS_NEGATIVE {
f.cyclotomic_inverse_in_place();
}
f
}
}

impl<P: BnConfig> Pairing for Bn<P> {
type BaseField = <P::G1Config as CurveConfig>::BaseField;
type ScalarField = <P::G1Config as CurveConfig>::ScalarField;
type G1 = G1Projective<P>;
type G1Affine = G1Affine<P>;
type G1Prepared = G1Prepared<P>;
type G2 = G2Projective<P>;
type G2Affine = G2Affine<P>;
type G2Prepared = G2Prepared<P>;
type TargetField = Fp12<P::Fp12Config>;

fn multi_miller_loop(
a: impl IntoIterator<Item = impl Into<Self::G1Prepared>>,
b: impl IntoIterator<Item = impl Into<Self::G2Prepared>>,
) -> MillerLoopOutput<Self> {
a: impl IntoIterator<Item = impl Into<G1Prepared<Self>>>,
b: impl IntoIterator<Item = impl Into<G2Prepared<Self>>>,
) -> MillerLoopOutput<Bn<Self>> {
let mut pairs = a
.into_iter()
.zip_eq(b)
Expand All @@ -119,44 +65,44 @@ impl<P: BnConfig> Pairing for Bn<P> {

let mut f = cfg_chunks_mut!(pairs, 4)
.map(|pairs| {
let mut f = Self::TargetField::one();
for i in (1..P::ATE_LOOP_COUNT.len()).rev() {
if i != P::ATE_LOOP_COUNT.len() - 1 {
let mut f = <Bn<Self> as Pairing>::TargetField::one();
for i in (1..Self::ATE_LOOP_COUNT.len()).rev() {
if i != Self::ATE_LOOP_COUNT.len() - 1 {
f.square_in_place();
}

for (p, coeffs) in pairs.iter_mut() {
Self::ell(&mut f, &coeffs.next().unwrap(), &p.0);
Bn::<Self>::ell(&mut f, &coeffs.next().unwrap(), &p.0);
}

let bit = P::ATE_LOOP_COUNT[i - 1];
let bit = Self::ATE_LOOP_COUNT[i - 1];
if bit == 1 || bit == -1 {
for (p, coeffs) in pairs.iter_mut() {
Self::ell(&mut f, &coeffs.next().unwrap(), &p.0);
Bn::<Self>::ell(&mut f, &coeffs.next().unwrap(), &p.0);
}
}
}
f
})
.product::<Self::TargetField>();
.product::<<Bn<Self> as Pairing>::TargetField>();

if P::X_IS_NEGATIVE {
if Self::X_IS_NEGATIVE {
f.cyclotomic_inverse_in_place();
}

for (p, coeffs) in &mut pairs {
Self::ell(&mut f, &coeffs.next().unwrap(), &p.0);
Bn::<Self>::ell(&mut f, &coeffs.next().unwrap(), &p.0);
}

for (p, coeffs) in &mut pairs {
Self::ell(&mut f, &coeffs.next().unwrap(), &p.0);
Bn::<Self>::ell(&mut f, &coeffs.next().unwrap(), &p.0);
}

MillerLoopOutput(f)
}

#[allow(clippy::let_and_return)]
fn final_exponentiation(f: MillerLoopOutput<Self>) -> Option<PairingOutput<Self>> {
fn final_exponentiation(f: MillerLoopOutput<Bn<Self>>) -> Option<PairingOutput<Bn<Self>>> {
// Easy part: result = elt^((q^6-1)*(q^2+1)).
// Follows, e.g., Beuchat et al page 9, by computing result as follows:
// elt^((q^6-1)*(q^2+1)) = (conj(elt) * elt^(-1))^(q^2+1)
Expand Down Expand Up @@ -191,13 +137,13 @@ impl<P: BnConfig> Pairing for Bn<P> {
//
// result = elt^( 2z * ( 6z^2 + 3z + 1 ) * (q^4 - q^2 + 1)/r ).

let y0 = Self::exp_by_neg_x(r);
let y0 = Bn::<Self>::exp_by_neg_x(r);
let y1 = y0.cyclotomic_square();
let y2 = y1.cyclotomic_square();
let mut y3 = y2 * &y1;
let y4 = Self::exp_by_neg_x(y3);
let y4 = Bn::<Self>::exp_by_neg_x(y3);
let y5 = y4.cyclotomic_square();
let mut y6 = Self::exp_by_neg_x(y5);
let mut y6 = Bn::<Self>::exp_by_neg_x(y5);
y3.cyclotomic_inverse_in_place();
y6.cyclotomic_inverse_in_place();
let y7 = y6 * &y4;
Expand All @@ -219,3 +165,68 @@ impl<P: BnConfig> Pairing for Bn<P> {
})
}
}

pub mod g1;
pub mod g2;

pub use self::{
g1::{G1Affine, G1Prepared, G1Projective},
g2::{G2Affine, G2Prepared, G2Projective},
};

#[derive(Derivative)]
#[derivative(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct Bn<P: BnConfig>(PhantomData<fn() -> P>);

impl<P: BnConfig> Bn<P> {
/// Evaluates the line function at point p.
fn ell(f: &mut Fp12<P::Fp12Config>, coeffs: &g2::EllCoeff<P>, p: &G1Affine<P>) {
let mut c0 = coeffs.0;
let mut c1 = coeffs.1;
let mut c2 = coeffs.2;

match P::TWIST_TYPE {
TwistType::M => {
c2.mul_assign_by_fp(&p.y);
c1.mul_assign_by_fp(&p.x);
f.mul_by_014(&c0, &c1, &c2);
},
TwistType::D => {
c0.mul_assign_by_fp(&p.y);
c1.mul_assign_by_fp(&p.x);
f.mul_by_034(&c0, &c1, &c2);
},
}
}

fn exp_by_neg_x(mut f: Fp12<P::Fp12Config>) -> Fp12<P::Fp12Config> {
f = f.cyclotomic_exp(P::X);
if !P::X_IS_NEGATIVE {
f.cyclotomic_inverse_in_place();
}
f
}
}

impl<P: BnConfig> Pairing for Bn<P> {
type BaseField = <P::G1Config as CurveConfig>::BaseField;
type ScalarField = <P::G1Config as CurveConfig>::ScalarField;
type G1 = G1Projective<P>;
type G1Affine = G1Affine<P>;
type G1Prepared = G1Prepared<P>;
type G2 = G2Projective<P>;
type G2Affine = G2Affine<P>;
type G2Prepared = G2Prepared<P>;
type TargetField = Fp12<P::Fp12Config>;

fn multi_miller_loop(
a: impl IntoIterator<Item = impl Into<Self::G1Prepared>>,
b: impl IntoIterator<Item = impl Into<Self::G2Prepared>>,
) -> MillerLoopOutput<Self> {
P::multi_miller_loop(a, b)
}

fn final_exponentiation(f: MillerLoopOutput<Self>) -> Option<PairingOutput<Self>> {
P::final_exponentiation(f)
}
}
48 changes: 31 additions & 17 deletions ec/src/models/mnt4/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub use self::{

pub type GT<P> = Fp4<P>;

pub trait MNT4Config: 'static {
pub trait MNT4Config: 'static + Sized {
const TWIST: Fp2<Self::Fp2Config>;
const TWIST_COEFF_A: Fp2<Self::Fp2Config>;
const ATE_LOOP_COUNT: &'static [i8];
Expand All @@ -43,6 +43,34 @@ pub trait MNT4Config: 'static {
BaseField = Fp2<Self::Fp2Config>,
ScalarField = <Self::G1Config as CurveConfig>::ScalarField,
>;
fn multi_miller_loop(
a: impl IntoIterator<Item = impl Into<G1Prepared<Self>>>,
b: impl IntoIterator<Item = impl Into<G2Prepared<Self>>>,
) -> MillerLoopOutput<MNT4<Self>> {
let pairs = a
.into_iter()
.zip_eq(b)
.map(|(a, b)| (a.into(), b.into()))
.collect::<Vec<_>>();
let result = cfg_into_iter!(pairs)
.map(|(a, b)| MNT4::<Self>::ate_miller_loop(&a, &b))
.product();
MillerLoopOutput(result)
}

fn final_exponentiation(f: MillerLoopOutput<MNT4<Self>>) -> Option<PairingOutput<MNT4<Self>>> {
let value = f.0;
let value_inv = value.inverse().unwrap();
let value_to_first_chunk =
MNT4::<Self>::final_exponentiation_first_chunk(&value, &value_inv);
let value_inv_to_first_chunk =
MNT4::<Self>::final_exponentiation_first_chunk(&value_inv, &value);
let result = MNT4::<Self>::final_exponentiation_last_chunk(
&value_to_first_chunk,
&value_inv_to_first_chunk,
);
Some(PairingOutput(result))
}
}

#[derive(Derivative)]
Expand Down Expand Up @@ -211,24 +239,10 @@ impl<P: MNT4Config> Pairing for MNT4<P> {
a: impl IntoIterator<Item = impl Into<Self::G1Prepared>>,
b: impl IntoIterator<Item = impl Into<Self::G2Prepared>>,
) -> MillerLoopOutput<Self> {
let pairs = a
.into_iter()
.zip_eq(b)
.map(|(a, b)| (a.into(), b.into()))
.collect::<Vec<_>>();
let result = cfg_into_iter!(pairs)
.map(|(a, b)| Self::ate_miller_loop(&a, &b))
.product();
MillerLoopOutput(result)
P::multi_miller_loop(a, b)
}

fn final_exponentiation(f: MillerLoopOutput<Self>) -> Option<PairingOutput<Self>> {
let value = f.0;
let value_inv = value.inverse().unwrap();
let value_to_first_chunk = Self::final_exponentiation_first_chunk(&value, &value_inv);
let value_inv_to_first_chunk = Self::final_exponentiation_first_chunk(&value_inv, &value);
let result =
Self::final_exponentiation_last_chunk(&value_to_first_chunk, &value_inv_to_first_chunk);
Some(PairingOutput(result))
P::final_exponentiation(f)
}
}
49 changes: 32 additions & 17 deletions ec/src/models/mnt6/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub use self::{

pub type GT<P> = Fp6<P>;

pub trait MNT6Config: 'static {
pub trait MNT6Config: 'static + Sized {
const TWIST: Fp3<Self::Fp3Config>;
const TWIST_COEFF_A: Fp3<Self::Fp3Config>;
const ATE_LOOP_COUNT: &'static [i8];
Expand All @@ -43,6 +43,35 @@ pub trait MNT6Config: 'static {
BaseField = Fp3<Self::Fp3Config>,
ScalarField = <Self::G1Config as CurveConfig>::ScalarField,
>;

fn multi_miller_loop(
a: impl IntoIterator<Item = impl Into<G1Prepared<Self>>>,
b: impl IntoIterator<Item = impl Into<G2Prepared<Self>>>,
) -> MillerLoopOutput<MNT6<Self>> {
let pairs = a
.into_iter()
.zip_eq(b)
.map(|(a, b)| (a.into(), b.into()))
.collect::<Vec<_>>();
let result = cfg_into_iter!(pairs)
.map(|(a, b)| MNT6::<Self>::ate_miller_loop(&a, &b))
.product();
MillerLoopOutput(result)
}

fn final_exponentiation(f: MillerLoopOutput<MNT6<Self>>) -> Option<PairingOutput<MNT6<Self>>> {
let value = f.0;
let value_inv = value.inverse().unwrap();
let value_to_first_chunk =
MNT6::<Self>::final_exponentiation_first_chunk(&value, &value_inv);
let value_inv_to_first_chunk =
MNT6::<Self>::final_exponentiation_first_chunk(&value_inv, &value);
let result = MNT6::<Self>::final_exponentiation_last_chunk(
&value_to_first_chunk,
&value_inv_to_first_chunk,
);
Some(PairingOutput(result))
}
}

#[derive(Derivative)]
Expand Down Expand Up @@ -217,24 +246,10 @@ impl<P: MNT6Config> Pairing for MNT6<P> {
a: impl IntoIterator<Item = impl Into<Self::G1Prepared>>,
b: impl IntoIterator<Item = impl Into<Self::G2Prepared>>,
) -> MillerLoopOutput<Self> {
let pairs = a
.into_iter()
.zip_eq(b)
.map(|(a, b)| (a.into(), b.into()))
.collect::<Vec<_>>();
let result = cfg_into_iter!(pairs)
.map(|(a, b)| Self::ate_miller_loop(&a, &b))
.product();
MillerLoopOutput(result)
P::multi_miller_loop(a, b)
}

fn final_exponentiation(f: MillerLoopOutput<Self>) -> Option<PairingOutput<Self>> {
let value = f.0;
let value_inv = value.inverse().unwrap();
let value_to_first_chunk = Self::final_exponentiation_first_chunk(&value, &value_inv);
let value_inv_to_first_chunk = Self::final_exponentiation_first_chunk(&value_inv, &value);
let result =
Self::final_exponentiation_last_chunk(&value_to_first_chunk, &value_inv_to_first_chunk);
Some(PairingOutput(result))
P::final_exponentiation(f)
}
}
3 changes: 1 addition & 2 deletions ff/src/fields/models/fp/montgomery_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,8 +821,7 @@ impl<T: MontConfig<N>, const N: usize> Fp<MontBackend<T, N>, N> {

#[cfg(test)]
mod test {
use ark_std::str::FromStr;
use ark_std::vec::Vec;
use ark_std::{str::FromStr, vec::Vec};
use ark_test_curves::secp256k1::Fr;
use num_bigint::{BigInt, BigUint, Sign};

Expand Down
3 changes: 1 addition & 2 deletions test-templates/src/h2c/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ macro_rules! test_h2c {
fs::{read_dir, File},
io::BufReader,
};
use $crate::decode;
use $crate::Sha256;
use $crate::{decode, Sha256};

use $crate::json::SuiteVector;
#[test]
Expand Down

0 comments on commit 24496c9

Please sign in to comment.