Skip to content

Commit 6512e48

Browse files
mmagicianweikengchenonewayfunc
authored
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 <[email protected]> Co-authored-by: onewayfunc <[email protected]>
1 parent db6a3d6 commit 6512e48

File tree

13 files changed

+144
-112
lines changed

13 files changed

+144
-112
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ jobs:
187187
echo "ark-ff = { git = 'https://github.com/arkworks-rs/algebra' }"
188188
echo "ark-poly = { git = 'https://github.com/arkworks-rs/algebra' }"
189189
echo "ark-serialize = { git = 'https://github.com/arkworks-rs/algebra' }"
190+
echo "ark-algebra-bench-templates = { git = 'https://github.com/arkworks-rs/algebra' }"
190191
echo "ark-algebra-test-templates = { git = 'https://github.com/arkworks-rs/algebra' }"
191192
echo "ark-r1cs-std = { path = 'r1cs-std' }"
192193
} >> Cargo.toml

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ ark-std = { git = "https://github.com/arkworks-rs/std" }
7777
ark-ec = { git = "https://github.com/arkworks-rs/algebra" }
7878
ark-ff = { git = "https://github.com/arkworks-rs/algebra" }
7979
ark-poly = { git = "https://github.com/arkworks-rs/algebra" }
80+
ark-algebra-bench-templates = { git = "https://github.com/arkworks-rs/algebra" }
8081
ark-test-curves = { git = "https://github.com/arkworks-rs/algebra" }
8182
ark-bls12-381 = { git = "https://github.com/arkworks-rs/curves" }
8283
ark-bls12-377 = { git = "https://github.com/arkworks-rs/curves" }

src/groups/curves/short_weierstrass/bls12/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl<P: Bls12Parameters> G1PreparedVar<P> {
4343
let y = self.0.y.value()?;
4444
let infinity = self.0.infinity.value()?;
4545
let g = infinity
46-
.then_some(GroupAffine::zero())
46+
.then_some(GroupAffine::identity())
4747
.unwrap_or(GroupAffine::new(x, y))
4848
.into();
4949
Ok(g)

src/groups/curves/short_weierstrass/mnt4/mod.rs

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -291,33 +291,32 @@ impl<P: MNT4Parameters> G2PreparedVar<P> {
291291
t: Fp2G::<P>::one(),
292292
};
293293

294-
for (idx, value) in P::ATE_LOOP_COUNT.iter().rev().enumerate() {
295-
let mut tmp = *value;
296-
let skip_extraneous_bits = 64 - value.leading_zeros();
297-
let mut v = Vec::with_capacity(16);
298-
for i in 0..64 {
299-
if idx == 0 && (i == 0 || i >= skip_extraneous_bits) {
300-
continue;
301-
}
302-
v.push(tmp & 1 == 1);
303-
tmp >>= 1;
304-
}
305-
306-
for bit in v.iter().rev() {
307-
let (r2, coeff) = PairingVar::<P>::doubling_step_for_flipped_miller_loop(&r)?;
308-
g2p.double_coefficients.push(coeff);
309-
r = r2;
310-
311-
if *bit {
312-
let (r2, coeff) = PairingVar::<P>::mixed_addition_step_for_flipped_miller_loop(
313-
&q.x, &q.y, &r,
314-
)?;
315-
g2p.addition_coefficients.push(coeff);
316-
r = r2;
317-
}
318-
319-
tmp >>= 1;
294+
for bit in P::ATE_LOOP_COUNT.iter().skip(1) {
295+
let (r2, coeff) = PairingVar::<P>::doubling_step_for_flipped_miller_loop(&r)?;
296+
g2p.double_coefficients.push(coeff);
297+
r = r2;
298+
299+
let add_coeff;
300+
let r_temp;
301+
match bit {
302+
1 => {
303+
(r_temp, add_coeff) =
304+
PairingVar::<P>::mixed_addition_step_for_flipped_miller_loop(
305+
&q.x, &q.y, &r,
306+
)?;
307+
},
308+
-1 => {
309+
(r_temp, add_coeff) =
310+
PairingVar::<P>::mixed_addition_step_for_flipped_miller_loop(
311+
&q.x,
312+
&q.y.negate()?,
313+
&r,
314+
)?;
315+
},
316+
_ => continue,
320317
}
318+
g2p.addition_coefficients.push(add_coeff);
319+
r = r_temp;
321320
}
322321

323322
if P::ATE_IS_LOOP_COUNT_NEG {

src/groups/curves/short_weierstrass/mnt6/mod.rs

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -291,33 +291,32 @@ impl<P: MNT6Parameters> G2PreparedVar<P> {
291291
t: Fp3G::<P>::one(),
292292
};
293293

294-
for (idx, value) in P::ATE_LOOP_COUNT.iter().rev().enumerate() {
295-
let mut tmp = *value;
296-
let skip_extraneous_bits = 64 - value.leading_zeros();
297-
let mut v = Vec::with_capacity(16);
298-
for i in 0..64 {
299-
if idx == 0 && (i == 0 || i >= skip_extraneous_bits) {
300-
continue;
301-
}
302-
v.push(tmp & 1 == 1);
303-
tmp >>= 1;
304-
}
305-
306-
for bit in v.iter().rev() {
307-
let (r2, coeff) = PairingVar::<P>::doubling_step_for_flipped_miller_loop(&r)?;
308-
g2p.double_coefficients.push(coeff);
309-
r = r2;
310-
311-
if *bit {
312-
let (r2, coeff) = PairingVar::<P>::mixed_addition_step_for_flipped_miller_loop(
313-
&q.x, &q.y, &r,
314-
)?;
315-
g2p.addition_coefficients.push(coeff);
316-
r = r2;
317-
}
318-
319-
tmp >>= 1;
294+
for bit in P::ATE_LOOP_COUNT.iter().skip(1) {
295+
let (r2, coeff) = PairingVar::<P>::doubling_step_for_flipped_miller_loop(&r)?;
296+
g2p.double_coefficients.push(coeff);
297+
r = r2;
298+
299+
let add_coeff;
300+
let r_temp;
301+
match bit {
302+
1 => {
303+
(r_temp, add_coeff) =
304+
PairingVar::<P>::mixed_addition_step_for_flipped_miller_loop(
305+
&q.x, &q.y, &r,
306+
)?;
307+
},
308+
-1 => {
309+
(r_temp, add_coeff) =
310+
PairingVar::<P>::mixed_addition_step_for_flipped_miller_loop(
311+
&q.x,
312+
&q.y.negate()?,
313+
&r,
314+
)?;
315+
},
316+
_ => continue,
320317
}
318+
g2p.addition_coefficients.push(add_coeff);
319+
r = r_temp;
321320
}
322321

323322
if P::ATE_IS_LOOP_COUNT_NEG {

src/groups/curves/short_weierstrass/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use ark_ec::{
22
short_weierstrass::{
33
Affine as SWAffine, Projective as SWProjective, SWCurveConfig as SWModelParameters,
44
},
5-
AffineCurve, ProjectiveCurve,
5+
AffineRepr, CurveGroup,
66
};
77
use ark_ff::{BigInteger, BitIteratorBE, Field, One, PrimeField, Zero};
88
use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError};
@@ -94,7 +94,7 @@ where
9494
/// constraint system.
9595
pub fn value(&self) -> Result<SWAffine<P>, SynthesisError> {
9696
Ok(match self.infinity.value()? {
97-
true => SWAffine::zero(),
97+
true => SWAffine::identity(),
9898
false => SWAffine::new(self.x.value()?, self.y.value()?),
9999
})
100100
}
@@ -137,7 +137,7 @@ where
137137
let result = if let Some(z_inv) = z.inverse() {
138138
SWAffine::new(x * &z_inv, y * &z_inv)
139139
} else {
140-
SWAffine::zero()
140+
SWAffine::identity()
141141
};
142142
Ok(result.into())
143143
}
@@ -209,7 +209,7 @@ where
209209
let (x, y, z) = match f() {
210210
Ok(ge) => {
211211
let ge = ge.into_affine();
212-
if ge.is_zero() {
212+
if ge.is_identity() {
213213
(
214214
Ok(P::BaseField::zero()),
215215
Ok(P::BaseField::one()),
@@ -782,7 +782,11 @@ where
782782
f: impl FnOnce() -> Result<T, SynthesisError>,
783783
mode: AllocationMode,
784784
) -> Result<Self, SynthesisError> {
785-
Self::new_variable(cs, || f().map(|b| b.borrow().into_projective()), mode)
785+
Self::new_variable(
786+
cs,
787+
|| f().map(|b| SWProjective::from((*b.borrow()).clone())),
788+
mode,
789+
)
786790
}
787791
}
788792

src/groups/curves/short_weierstrass/non_zero_affine.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use super::*;
2+
use ark_ec::Group;
3+
use ark_std::ops::Add;
24

35
/// An affine representation of a prime order curve point that is guaranteed
46
/// to *not* be the point at infinity.
@@ -43,8 +45,7 @@ where
4345
#[tracing::instrument(target = "r1cs", skip(self, other))]
4446
pub fn add_unchecked(&self, other: &Self) -> Result<Self, SynthesisError> {
4547
if [self, other].is_constant() {
46-
let result =
47-
(self.value()?.into_projective() + other.value()?.into_projective()).into_affine();
48+
let result = self.value()?.add(other.value()?).into_affine();
4849
Ok(Self::new(F::constant(result.x), F::constant(result.y)))
4950
} else {
5051
let (x1, y1) = (&self.x, &self.y);
@@ -70,9 +71,11 @@ where
7071
#[tracing::instrument(target = "r1cs", skip(self))]
7172
pub fn double(&self) -> Result<Self, SynthesisError> {
7273
if [self].is_constant() {
73-
let result = self.value()?.into_projective().double().into_affine();
74+
let result = SWProjective::<P>::from(self.value()?)
75+
.double()
76+
.into_affine();
7477
// Panic if the result is zero.
75-
assert!(!result.is_zero());
78+
assert!(!result.is_identity());
7679
Ok(Self::new(F::constant(result.x), F::constant(result.y)))
7780
} else {
7881
let (x1, y1) = (&self.x, &self.y);
@@ -236,7 +239,7 @@ mod test_non_zero_affine {
236239
},
237240
R1CSVar,
238241
};
239-
use ark_ec::{models::short_weierstrass::SWCurveConfig, ProjectiveCurve};
242+
use ark_ec::{models::short_weierstrass::SWCurveConfig, CurveGroup};
240243
use ark_relations::r1cs::ConstraintSystem;
241244
use ark_std::{vec::Vec, One};
242245
use ark_test_curves::bls12_381::{g1::Parameters as G1Parameters, Fq};

src/groups/curves/twisted_edwards/mod.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ use ark_ec::{
33
Affine as TEAffine, MontCurveConfig as MontgomeryModelParameter,
44
Projective as TEProjective, TECurveConfig as TEModelParameters,
55
},
6-
AffineCurve, ProjectiveCurve,
6+
AffineRepr, CurveGroup, Group,
77
};
88
use ark_ff::{BigInteger, BitIteratorBE, Field, One, PrimeField, Zero};
9-
109
use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError};
1110

1211
use crate::{prelude::*, ToConstraintFieldGadget, Vec};
@@ -85,7 +84,7 @@ mod montgomery_affine_impl {
8584
p: &TEAffine<P>,
8685
) -> Result<(P::BaseField, P::BaseField), SynthesisError> {
8786
let montgomery_point: GroupAffine<P> = if p.y == P::BaseField::one() {
88-
GroupAffine::zero()
87+
GroupAffine::identity()
8988
} else if p.x == P::BaseField::zero() {
9089
GroupAffine::new(P::BaseField::zero(), P::BaseField::zero())
9190
} else {
@@ -543,7 +542,7 @@ where
543542
if bits.len() == 2 {
544543
let mut table = [multiples[0], multiples[1], multiples[0] + multiples[1]];
545544

546-
TEProjective::batch_normalization(&mut table);
545+
TEProjective::normalize_batch(&mut table);
547546
let x_s = [zero.x, table[0].x, table[1].x, table[2].x];
548547
let y_s = [zero.y, table[0].y, table[1].y, table[2].y];
549548

@@ -675,7 +674,11 @@ where
675674
f: impl FnOnce() -> Result<Point, SynthesisError>,
676675
mode: AllocationMode,
677676
) -> Result<Self, SynthesisError> {
678-
Self::new_variable(cs, || f().map(|b| b.borrow().into_projective()), mode)
677+
Self::new_variable(
678+
cs,
679+
|| f().map(|b| TEProjective::<P>::from((*b.borrow()).clone())),
680+
mode,
681+
)
679682
}
680683
}
681684

src/groups/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::prelude::*;
2-
use ark_ec::ProjectiveCurve;
32
use ark_ff::Field;
43
use ark_relations::r1cs::{Namespace, SynthesisError};
54
use core::ops::{Add, AddAssign, Sub, SubAssign};
65

6+
use ark_ec::CurveGroup;
77
use core::{borrow::Borrow, fmt::Debug};
88

99
/// This module contains implementations of arithmetic for various curve models.
@@ -25,7 +25,7 @@ pub trait GroupOpsBounds<'a, F, T: 'a>:
2525

2626
/// A variable that represents a curve point for
2727
/// the curve `C`.
28-
pub trait CurveVar<C: ProjectiveCurve, ConstraintF: Field>:
28+
pub trait CurveVar<C: CurveGroup, ConstraintF: Field>:
2929
'static
3030
+ Sized
3131
+ Clone

src/pairing/mnt4/mod.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use crate::{
1010
},
1111
};
1212
use ark_ec::mnt4::{MNT4Parameters, MNT4};
13-
use ark_ff::BitIteratorBE;
1413

1514
use core::marker::PhantomData;
1615

@@ -105,10 +104,8 @@ impl<P: MNT4Parameters> PairingVar<P> {
105104

106105
// code below gets executed for all bits (EXCEPT the MSB itself) of
107106
// mnt6_param_p (skipping leading zeros) in MSB to LSB order
108-
for (dbl_idx, bit) in BitIteratorBE::without_leading_zeros(P::ATE_LOOP_COUNT)
109-
.skip(1)
110-
.enumerate()
111-
{
107+
let y_over_twist_neg = &q.y_over_twist.negate()?;
108+
for (dbl_idx, bit) in P::ATE_LOOP_COUNT.iter().skip(1).enumerate() {
112109
let dc = &q.double_coefficients[dbl_idx];
113110

114111
let g_rr_at_p = Fp4G::<P>::new(
@@ -118,16 +115,29 @@ impl<P: MNT4Parameters> PairingVar<P> {
118115

119116
f = f.square()? * &g_rr_at_p;
120117

121-
if bit {
118+
let g_rq_at_p;
119+
// Compute l_{R,Q}(P) if bit == 1, and l_{R,-Q}(P) if bit == -1
120+
if *bit == 1 {
122121
let ac = &q.addition_coefficients[add_idx];
123122
add_idx += 1;
124123

125-
let g_rq_at_p = Fp4G::<P>::new(
124+
g_rq_at_p = Fp4G::<P>::new(
126125
&ac.c_rz * &p.y_twist,
127126
(&q.y_over_twist * &ac.c_rz + &l1_coeff * &ac.c_l1).negate()?,
128127
);
129-
f *= &g_rq_at_p;
128+
} else if *bit == -1 {
129+
let ac = &q.addition_coefficients[add_idx];
130+
add_idx += 1;
131+
132+
g_rq_at_p = Fp4G::<P>::new(
133+
&ac.c_rz * &p.y_twist,
134+
(y_over_twist_neg * &ac.c_rz + &l1_coeff * &ac.c_l1).negate()?,
135+
);
136+
} else {
137+
continue;
130138
}
139+
140+
f *= &g_rq_at_p;
131141
}
132142

133143
if P::ATE_IS_LOOP_COUNT_NEG {

0 commit comments

Comments
 (0)