Skip to content

Commit 9242cd9

Browse files
Avaneesh-axiomjonathanpwang
authored andcommitted
[fix] Added square-and-multiply fallback for final exponentiation for Bn254 and Bls12_381 curves (#23)
Added a fallback for final exponentiation in the pairing extension for the case that the hint fails to prove that the final exponentiation is equal to 1. This is a temporary fix. We will scope out a better approach after the security reviews. Closes INT-3381
1 parent 17626b9 commit 9242cd9

File tree

9 files changed

+422
-9
lines changed

9 files changed

+422
-9
lines changed

extensions/pairing/guest/src/bls12_381/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,3 +657,11 @@ impl PairingIntrinsics for Bls12_381 {
657657
],
658658
];
659659
}
660+
661+
impl Bls12_381 {
662+
// FINAL_EXPONENT = (p^12 - 1) / r in big-endian
663+
// Validated by a test in test.rs
664+
pub const FINAL_EXPONENT: [u8; 540] = hex!(
665+
"02ee1db5dcc825b7e1bda9c0496a1c0a89ee0193d4977b3f7d4507d07363baa13f8d14a917848517badc3a43d1073776ab353f2c30698e8cc7deada9c0aadff5e9cfee9a074e43b9a660835cc872ee83ff3a0f0f1c0ad0d6106feaf4e347aa68ad49466fa927e7bb9375331807a0dce2630d9aa4b113f414386b0e8819328148978e2b0dd39099b86e1ab656d2670d93e4d7acdd350da5359bc73ab61a0c5bf24c374693c49f570bcd2b01f3077ffb10bf24dde41064837f27611212596bc293c8d4c01f25118790f4684d0b9c40a68eb74bb22a40ee7169cdc1041296532fef459f12438dfc8e2886ef965e61a474c5c85b0129127a1b5ad0463434724538411d1676a53b5a62eb34c05739334f46c02c3f0bd0c55d3109cd15948d0a1fad20044ce6ad4c6bec3ec03ef19592004cedd556952c6d8823b19dadd7c2498345c6e5308f1c511291097db60b1749bf9b71a9f9e0100418a3ef0bc627751bbd81367066bca6a4c1b6dcfc5cceb73fc56947a403577dfa9e13c24ea820b09c1d9f7c31759c3635de3f7a3639991708e88adce88177456c49637fd7961be1a4c7e79fb02faa732e2f3ec2bea83d196283313492caa9d4aff1c910e9622d2a73f62537f2701aaef6539314043f7bbce5b78c7869aeb2181a67e49eeed2161daf3f881bd88592d767f67c4717489119226c2f011d4cab803e9d71650a6f80698e2f8491d12191a04406fbc8fbd5f48925f98630e68bfb24c0bcb9b55df57510"
666+
);
667+
}

extensions/pairing/guest/src/bls12_381/pairing.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use {
1818

1919
use super::{Bls12_381, Fp, Fp12, Fp2};
2020
use crate::pairing::{
21-
Evaluatable, EvaluatedLine, FromLineMType, LineMulMType, MillerStep, MultiMillerLoop,
22-
PairingCheck, PairingCheckError, PairingIntrinsics, UnevaluatedLine,
21+
exp_check_fallback, Evaluatable, EvaluatedLine, FromLineMType, LineMulMType, MillerStep,
22+
MultiMillerLoop, PairingCheck, PairingCheckError, PairingIntrinsics, UnevaluatedLine,
2323
};
2424
#[cfg(all(feature = "halo2curves", not(target_os = "zkvm")))]
2525
use crate::{
@@ -362,7 +362,8 @@ impl PairingCheck for Bls12_381 {
362362
if fc * s == c_q {
363363
Ok(())
364364
} else {
365-
Err(PairingCheckError)
365+
let f = Self::multi_miller_loop(P, Q);
366+
exp_check_fallback(&f, &Self::FINAL_EXPONENT)
366367
}
367368
}
368369
}

extensions/pairing/guest/src/bls12_381/tests.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ use group::ff::Field;
22
use halo2curves_axiom::bls12_381::{
33
Fq, Fq12, Fq2, Fq6, G1Affine, G2Affine, G2Prepared, MillerLoopResult, FROBENIUS_COEFF_FQ12_C1,
44
};
5+
use num_bigint::BigUint;
6+
use num_traits::One;
57
use openvm_algebra_guest::{field::FieldExtension, IntMod};
68
use openvm_ecc_guest::{weierstrass::WeierstrassPoint, AffinePoint};
79
use rand::{rngs::StdRng, SeedableRng};
810

9-
use super::{Fp, Fp12, Fp2};
11+
use super::{Fp, Fp12, Fp2, BLS12_381_MODULUS, BLS12_381_ORDER};
1012
use crate::{
1113
bls12_381::{
1214
utils::{
@@ -295,3 +297,9 @@ fn test_bls12381_pairing_check_hint_host() {
295297
assert_eq!(c, c_cmp);
296298
assert_eq!(s, s_cmp);
297299
}
300+
301+
#[test]
302+
fn test_bls12381_final_exponent() {
303+
let final_exp = (BLS12_381_MODULUS.pow(12) - BigUint::one()) / BLS12_381_ORDER.clone();
304+
assert_eq!(Bls12_381::FINAL_EXPONENT.to_vec(), final_exp.to_bytes_be());
305+
}

extensions/pairing/guest/src/bn254/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,12 @@ impl Bn254 {
172172
"e3b02326637fd382d25ba28fc97d80212b6f79eca7b504079a0441acbc3cc007"
173173
)),
174174
};
175+
176+
// FINAL_EXPONENT = (p^12 - 1) / r in big-endian
177+
// Validated by a test in test.rs
178+
pub const FINAL_EXPONENT: [u8; 349] = hex!(
179+
"2f4b6dc97020fddadf107d20bc842d43bf6369b1ff6a1c71015f3f7be2e1e30a73bb94fec0daf15466b2383a5d3ec3d15ad524d8f70c54efee1bd8c3b21377e563a09a1b705887e72eceaddea3790364a61f676baaf977870e88d5c6c8fef0781361e443ae77f5b63a2a2264487f2940a8b1ddb3d15062cd0fb2015dfc6668449aed3cc48a82d0d602d268c7daab6a41294c0cc4ebe5664568dfc50e1648a45a4a1e3a5195846a3ed011a337a02088ec80e0ebae8755cfe107acf3aafb40494e406f804216bb10cf430b0f37856b42db8dc5514724ee93dfb10826f0dd4a0364b9580291d2cd65664814fde37ca80bb4ea44eacc5e641bbadf423f9a2cbf813b8d145da90029baee7ddadda71c7f3811c4105262945bba1668c3be69a3c230974d83561841d766f9c9d570bb7fbe04c7e8a6c3c760c0de81def35692da361102b6b9b2b918837fa97896e84abb40a4efb7e54523a486964b64ca86f120"
180+
);
175181
}
176182

177183
impl IntrinsicCurve for Bn254 {

extensions/pairing/guest/src/bn254/pairing.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use {
1414

1515
use super::{Bn254, Fp, Fp12, Fp2};
1616
use crate::pairing::{
17-
Evaluatable, EvaluatedLine, FromLineDType, LineMulDType, MillerStep, MultiMillerLoop,
18-
PairingCheck, PairingCheckError, PairingIntrinsics, UnevaluatedLine,
17+
exp_check_fallback, Evaluatable, EvaluatedLine, FromLineDType, LineMulDType, MillerStep,
18+
MultiMillerLoop, PairingCheck, PairingCheckError, PairingIntrinsics, UnevaluatedLine,
1919
};
2020
#[cfg(all(feature = "halo2curves", not(target_os = "zkvm")))]
2121
use crate::{
@@ -391,7 +391,8 @@ impl PairingCheck for Bn254 {
391391
if fc * c_mul * u == Fp12::ONE {
392392
Ok(())
393393
} else {
394-
Err(PairingCheckError)
394+
let f = Self::multi_miller_loop(P, Q);
395+
exp_check_fallback(&f, &Self::FINAL_EXPONENT)
395396
}
396397
}
397398
}

extensions/pairing/guest/src/bn254/tests.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use group::{ff::Field, prime::PrimeCurveAffine};
22
use halo2curves_axiom::bn256::{
33
Fq, Fq12, Fq2, Fq6, G1Affine, G2Affine, G2Prepared, Gt, FROBENIUS_COEFF_FQ12_C1,
44
};
5+
use num_bigint::BigUint;
6+
use num_traits::One;
57
use openvm_algebra_guest::{field::FieldExtension, IntMod};
68
use openvm_ecc_guest::{weierstrass::WeierstrassPoint, AffinePoint};
79
use rand::{rngs::StdRng, SeedableRng};
@@ -14,7 +16,7 @@ use crate::{
1416
convert_bn254_halo2_fq2_to_fp2, convert_bn254_halo2_fq_to_fp,
1517
convert_g2_affine_halo2_to_openvm,
1618
},
17-
Bn254, G2Affine as OpenVmG2Affine,
19+
Bn254, G2Affine as OpenVmG2Affine, BN254_MODULUS, BN254_ORDER,
1820
},
1921
pairing::{
2022
fp2_invert_assign, fp6_invert_assign, fp6_square_assign, FinalExp, MultiMillerLoop,
@@ -280,3 +282,9 @@ fn test_bn254_pairing_check_hint_host() {
280282
assert_eq!(c, c_cmp);
281283
assert_eq!(u, u_cmp);
282284
}
285+
286+
#[test]
287+
fn test_bn254_final_exponent() {
288+
let final_exp = (BN254_MODULUS.pow(12) - BigUint::one()) / BN254_ORDER.clone();
289+
assert_eq!(Bn254::FINAL_EXPONENT.to_vec(), final_exp.to_bytes_be());
290+
}

extensions/pairing/guest/src/pairing/mod.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub use miller_loop::*;
1111
pub use miller_step::*;
1212
use openvm_algebra_guest::{
1313
field::{ComplexConjugate, FieldExtension},
14-
Field, IntMod,
14+
ExpBytes, Field, IntMod,
1515
};
1616
use openvm_ecc_guest::AffinePoint;
1717
#[allow(unused_imports)]
@@ -55,6 +55,20 @@ pub trait PairingCheck {
5555
) -> Result<(), PairingCheckError>;
5656
}
5757

58+
// Square and multiply implementation of final exponentiation. Used if the hint fails to prove
59+
// the pairing check.
60+
// `exp` should be big-endian.
61+
pub fn exp_check_fallback<F: Field + ExpBytes>(f: &F, exp: &[u8]) -> Result<(), PairingCheckError>
62+
where
63+
for<'a> &'a F: core::ops::Mul<&'a F, Output = F>,
64+
{
65+
if f.exp_bytes(true, exp) == F::ONE {
66+
Ok(())
67+
} else {
68+
Err(PairingCheckError)
69+
}
70+
}
71+
5872
pub const fn shifted_funct7<P: PairingIntrinsics>(funct7: PairingBaseFunct7) -> usize {
5973
P::PAIRING_IDX * (PairingBaseFunct7::PAIRING_MAX_KINDS as usize) + funct7 as usize
6074
}
@@ -68,3 +82,45 @@ impl core::fmt::Display for PairingCheckError {
6882
write!(f, "Pairing check failed")
6983
}
7084
}
85+
86+
#[cfg(all(test, not(target_os = "zkvm")))]
87+
mod tests {
88+
use num_bigint::BigUint;
89+
use openvm_algebra_moduli_macros::{moduli_declare, moduli_init};
90+
91+
use super::*;
92+
93+
moduli_declare! {
94+
F13 { modulus = "13" },
95+
}
96+
97+
moduli_init! {
98+
"13",
99+
}
100+
101+
impl Field for F13 {
102+
type SelfRef<'a> = &'a Self;
103+
const ZERO: Self = <Self as IntMod>::ZERO;
104+
const ONE: Self = <Self as IntMod>::ONE;
105+
106+
fn double_assign(&mut self) {
107+
IntMod::double_assign(self);
108+
}
109+
110+
fn square_assign(&mut self) {
111+
IntMod::square_assign(self);
112+
}
113+
}
114+
115+
#[test]
116+
fn test_pairing_check_fallback() {
117+
let a = F13::from_u8(2);
118+
let b = BigUint::from(12u32);
119+
let result = exp_check_fallback(&a, &b.to_bytes_be());
120+
assert_eq!(result, Ok(()));
121+
122+
let b = BigUint::from(11u32);
123+
let result = exp_check_fallback(&a, &b.to_bytes_be());
124+
assert_eq!(result, Err(PairingCheckError));
125+
}
126+
}

0 commit comments

Comments
 (0)