Use 2-NAF for representing ATE_LOOP_COUNT in MNT Miller loop (#96)

* 2-NAF for MNT pairings

* Apply suggestions from code review

* Apply suggestions from code review

* fix

* no std

* patch

* ci

Co-authored-by: Weikeng Chen <w.k@berkeley.edu>
Co-authored-by: onewayfunc <onewayfunc@gmail.com>
This commit is contained in:
mmagician
2022-09-03 09:15:45 +02:00
committed by GitHub
parent db6a3d6687
commit 6512e48540
13 changed files with 144 additions and 112 deletions

View File

@@ -10,7 +10,6 @@ use crate::{
},
};
use ark_ec::mnt4::{MNT4Parameters, MNT4};
use ark_ff::BitIteratorBE;
use core::marker::PhantomData;
@@ -105,10 +104,8 @@ impl<P: MNT4Parameters> PairingVar<P> {
// code below gets executed for all bits (EXCEPT the MSB itself) of
// mnt6_param_p (skipping leading zeros) in MSB to LSB order
for (dbl_idx, bit) in BitIteratorBE::without_leading_zeros(P::ATE_LOOP_COUNT)
.skip(1)
.enumerate()
{
let y_over_twist_neg = &q.y_over_twist.negate()?;
for (dbl_idx, bit) in P::ATE_LOOP_COUNT.iter().skip(1).enumerate() {
let dc = &q.double_coefficients[dbl_idx];
let g_rr_at_p = Fp4G::<P>::new(
@@ -118,16 +115,29 @@ impl<P: MNT4Parameters> PairingVar<P> {
f = f.square()? * &g_rr_at_p;
if bit {
let g_rq_at_p;
// Compute l_{R,Q}(P) if bit == 1, and l_{R,-Q}(P) if bit == -1
if *bit == 1 {
let ac = &q.addition_coefficients[add_idx];
add_idx += 1;
let g_rq_at_p = Fp4G::<P>::new(
g_rq_at_p = Fp4G::<P>::new(
&ac.c_rz * &p.y_twist,
(&q.y_over_twist * &ac.c_rz + &l1_coeff * &ac.c_l1).negate()?,
);
f *= &g_rq_at_p;
} else if *bit == -1 {
let ac = &q.addition_coefficients[add_idx];
add_idx += 1;
g_rq_at_p = Fp4G::<P>::new(
&ac.c_rz * &p.y_twist,
(y_over_twist_neg * &ac.c_rz + &l1_coeff * &ac.c_l1).negate()?,
);
} else {
continue;
}
f *= &g_rq_at_p;
}
if P::ATE_IS_LOOP_COUNT_NEG {

View File

@@ -10,7 +10,6 @@ use crate::{
},
};
use ark_ec::mnt6::{MNT6Parameters, MNT6};
use ark_ff::fields::BitIteratorBE;
use core::marker::PhantomData;
/// Specifies the constraints for computing a pairing in a MNT6 bilinear group.
@@ -100,29 +99,40 @@ impl<P: MNT6Parameters> PairingVar<P> {
// code below gets executed for all bits (EXCEPT the MSB itself) of
// mnt6_param_p (skipping leading zeros) in MSB to LSB order
for (dbl_idx, bit) in BitIteratorBE::without_leading_zeros(P::ATE_LOOP_COUNT)
.skip(1)
.enumerate()
{
let y_over_twist_neg = &q.y_over_twist.negate()?;
for (dbl_idx, bit) in P::ATE_LOOP_COUNT.iter().skip(1).enumerate() {
let dc = &q.double_coefficients[dbl_idx];
let g_rr_at_p = Fp6Var::new(
let g_rr_at_p = Fp6G::<P>::new(
&dc.c_l - &dc.c_4c - &dc.c_j * &p.x_twist,
&dc.c_h * &p.y_twist,
);
f = f.square()? * &g_rr_at_p;
if bit {
let g_rq_at_p;
// Compute l_{R,Q}(P) if bit == 1, and l_{R,-Q}(P) if bit == -1
if *bit == 1 {
let ac = &q.addition_coefficients[add_idx];
add_idx += 1;
let g_rq_at_p = Fp6Var::new(
g_rq_at_p = Fp6G::<P>::new(
&ac.c_rz * &p.y_twist,
(&q.y_over_twist * &ac.c_rz + &(&l1_coeff * &ac.c_l1)).negate()?,
(&q.y_over_twist * &ac.c_rz + &l1_coeff * &ac.c_l1).negate()?,
);
f *= &g_rq_at_p;
} else if *bit == -1 {
let ac = &q.addition_coefficients[add_idx];
add_idx += 1;
g_rq_at_p = Fp6G::<P>::new(
&ac.c_rz * &p.y_twist,
(y_over_twist_neg * &ac.c_rz + &l1_coeff * &ac.c_l1).negate()?,
);
} else {
continue;
}
f *= &g_rq_at_p;
}
if P::ATE_IS_LOOP_COUNT_NEG {

View File

@@ -1,5 +1,6 @@
use crate::prelude::*;
use ark_ec::PairingEngine;
use ark_ec::pairing::Pairing;
use ark_ec::CurveGroup;
use ark_ff::Field;
use ark_relations::r1cs::SynthesisError;
use core::fmt::Debug;
@@ -13,22 +14,23 @@ pub mod mnt6;
/// Specifies the constraints for computing a pairing in the yybilinear group
/// `E`.
pub trait PairingVar<E: PairingEngine, ConstraintF: Field = <E as PairingEngine>::Fq> {
pub trait PairingVar<E: Pairing, ConstraintF: Field = <<E as Pairing>::G1 as CurveGroup>::BaseField>
{
/// An variable representing an element of `G1`.
/// This is the R1CS equivalent of `E::G1Projective`.
type G1Var: CurveVar<E::G1Projective, ConstraintF>
+ AllocVar<E::G1Projective, ConstraintF>
type G1Var: CurveVar<E::G1, ConstraintF>
+ AllocVar<E::G1, ConstraintF>
+ AllocVar<E::G1Affine, ConstraintF>;
/// An variable representing an element of `G2`.
/// This is the R1CS equivalent of `E::G2Projective`.
type G2Var: CurveVar<E::G2Projective, ConstraintF>
+ AllocVar<E::G2Projective, ConstraintF>
type G2Var: CurveVar<E::G2, ConstraintF>
+ AllocVar<E::G2, ConstraintF>
+ AllocVar<E::G2Affine, ConstraintF>;
/// An variable representing an element of `GT`.
/// This is the R1CS equivalent of `E::GT`.
type GTVar: FieldVar<E::Fqk, ConstraintF>;
type GTVar: FieldVar<E::TargetField, ConstraintF>;
/// An variable representing cached precomputation that can speed up
/// pairings computations. This is the R1CS equivalent of