mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-11 08:21:30 +01:00
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:
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user