Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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