Skip to content

Commit 37f0b55

Browse files
authored
feat: Pairing check hint for target_os != zkvm (#1253)
* pairing check hint for target_os != zkvm * Use current macro * Lints and imports * Fix lints * Fix paths * Update feature gate
1 parent acdb0e2 commit 37f0b55

File tree

8 files changed

+269
-104
lines changed

8 files changed

+269
-104
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use openvm_ecc_guest::{weierstrass::IntrinsicCurve, CyclicGroup, Group};
77
mod fp12;
88
mod fp2;
99
mod pairing;
10+
#[cfg(all(feature = "halo2curves", not(target_os = "zkvm")))]
11+
pub(crate) mod utils;
1012

1113
pub use fp12::*;
1214
pub use fp2::*;

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ use crate::pairing::{
2020
Evaluatable, EvaluatedLine, FromLineMType, LineMulMType, MillerStep, MultiMillerLoop,
2121
PairingCheck, PairingCheckError, PairingIntrinsics, UnevaluatedLine,
2222
};
23+
#[cfg(all(feature = "halo2curves", not(target_os = "zkvm")))]
24+
use crate::{
25+
bls12_381::utils::{
26+
convert_bls12381_fp2_to_halo2_fq2, convert_bls12381_fp_to_halo2_fq,
27+
convert_bls12381_halo2_fq12_to_fp12,
28+
},
29+
halo2curves_shims::bls12_381::Bls12_381 as Halo2CurvesBls12_381,
30+
pairing::FinalExp,
31+
};
2332

2433
// TODO[jpw]: make macro
2534
impl Evaluatable<Fp, Fp2> for UnevaluatedLine<Fp2> {
@@ -275,7 +284,35 @@ impl PairingCheck for Bls12_381 {
275284
) -> (Self::Fp12, Self::Fp12) {
276285
#[cfg(not(target_os = "zkvm"))]
277286
{
278-
todo!()
287+
#[cfg(not(feature = "halo2curves"))]
288+
panic!("`halo2curves` feature must be enabled to use pairing check hint on host");
289+
290+
#[cfg(feature = "halo2curves")]
291+
{
292+
let p_halo2 = P
293+
.iter()
294+
.map(|p| {
295+
AffinePoint::new(
296+
convert_bls12381_fp_to_halo2_fq(p.x.clone()),
297+
convert_bls12381_fp_to_halo2_fq(p.y.clone()),
298+
)
299+
})
300+
.collect::<Vec<_>>();
301+
let q_halo2 = Q
302+
.iter()
303+
.map(|q| {
304+
AffinePoint::new(
305+
convert_bls12381_fp2_to_halo2_fq2(q.x.clone()),
306+
convert_bls12381_fp2_to_halo2_fq2(q.y.clone()),
307+
)
308+
})
309+
.collect::<Vec<_>>();
310+
let fq12 = Halo2CurvesBls12_381::multi_miller_loop(&p_halo2, &q_halo2);
311+
let (c_fq12, s_fq12) = Halo2CurvesBls12_381::final_exp_hint(&fq12);
312+
let c = convert_bls12381_halo2_fq12_to_fp12(c_fq12);
313+
let s = convert_bls12381_halo2_fq12_to_fp12(s_fq12);
314+
(c, s)
315+
}
279316
}
280317
#[cfg(target_os = "zkvm")]
281318
{

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

Lines changed: 46 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use alloc::vec::Vec;
2-
31
use group::ff::Field;
42
use halo2curves_axiom::bls12_381::{
53
Fq, Fq12, Fq2, Fq6, G1Affine, G2Affine, G2Prepared, MillerLoopResult, FROBENIUS_COEFF_FQ12_C1,
@@ -10,59 +8,20 @@ use rand::{rngs::StdRng, SeedableRng};
108

119
use super::{Fp, Fp12, Fp2};
1210
use crate::{
13-
bls12_381::{Bls12_381, G2Affine as OpenVmG2Affine},
11+
bls12_381::{
12+
utils::{
13+
convert_bls12381_fp12_to_halo2_fq12, convert_bls12381_halo2_fq12_to_fp12,
14+
convert_bls12381_halo2_fq2_to_fp2, convert_bls12381_halo2_fq_to_fp,
15+
convert_g2_affine_halo2_to_openvm,
16+
},
17+
Bls12_381, G2Affine as OpenVmG2Affine,
18+
},
1419
pairing::{
15-
fp2_invert_assign, fp6_invert_assign, fp6_square_assign, MultiMillerLoop, PairingIntrinsics,
20+
fp2_invert_assign, fp6_invert_assign, fp6_square_assign, FinalExp, MultiMillerLoop,
21+
PairingCheck, PairingIntrinsics,
1622
},
1723
};
1824

19-
fn convert_bls12381_halo2_fq_to_fp(x: Fq) -> Fp {
20-
let bytes = x.to_bytes();
21-
Fp::from_le_bytes(&bytes)
22-
}
23-
24-
fn convert_bls12381_halo2_fq2_to_fp2(x: Fq2) -> Fp2 {
25-
Fp2::new(
26-
convert_bls12381_halo2_fq_to_fp(x.c0),
27-
convert_bls12381_halo2_fq_to_fp(x.c1),
28-
)
29-
}
30-
31-
fn convert_bls12381_halo2_fq12_to_fp12(x: Fq12) -> Fp12 {
32-
Fp12 {
33-
c: x.to_coeffs().map(convert_bls12381_halo2_fq2_to_fp2),
34-
}
35-
}
36-
37-
fn convert_bls12381_fp_to_halo2_fq(x: Fp) -> Fq {
38-
let bytes =
39-
x.0.chunks(8)
40-
.map(|b| u64::from_le_bytes(b.try_into().unwrap()))
41-
.collect::<Vec<_>>()
42-
.try_into()
43-
.unwrap();
44-
Fq::from_raw_unchecked(bytes)
45-
}
46-
47-
fn convert_bls12381_fp2_to_halo2_fq2(x: Fp2) -> Fq2 {
48-
Fq2 {
49-
c0: convert_bls12381_fp_to_halo2_fq(x.c0.clone()),
50-
c1: convert_bls12381_fp_to_halo2_fq(x.c1.clone()),
51-
}
52-
}
53-
54-
fn convert_bls12381_fp12_to_halo2_fq12(x: Fp12) -> Fq12 {
55-
let c = x.to_coeffs();
56-
Fq12::from_coeffs(c.map(convert_bls12381_fp2_to_halo2_fq2))
57-
}
58-
59-
fn convert_g2_affine_halo2_to_openvm(p: G2Affine) -> OpenVmG2Affine {
60-
OpenVmG2Affine::from_xy_unchecked(
61-
convert_bls12381_halo2_fq2_to_fp2(p.x),
62-
convert_bls12381_halo2_fq2_to_fp2(p.y),
63-
)
64-
}
65-
6625
#[test]
6726
fn test_bls12381_frobenius_coeffs() {
6827
#[allow(clippy::needless_range_loop)]
@@ -300,3 +259,39 @@ fn test_bls12381_g2_affine() {
300259
}
301260
}
302261
}
262+
263+
#[test]
264+
fn test_bls12381_pairing_check_hint_host() {
265+
let mut rng = StdRng::seed_from_u64(83);
266+
let h2c_p = G1Affine::random(&mut rng);
267+
let h2c_q = G2Affine::random(&mut rng);
268+
269+
let p = AffinePoint {
270+
x: convert_bls12381_halo2_fq_to_fp(h2c_p.x),
271+
y: convert_bls12381_halo2_fq_to_fp(h2c_p.y),
272+
};
273+
let q = AffinePoint {
274+
x: convert_bls12381_halo2_fq2_to_fp2(h2c_q.x),
275+
y: convert_bls12381_halo2_fq2_to_fp2(h2c_q.y),
276+
};
277+
278+
let (c, s) = Bls12_381::pairing_check_hint(&[p], &[q]);
279+
280+
let p_cmp = AffinePoint {
281+
x: h2c_p.x,
282+
y: h2c_p.y,
283+
};
284+
let q_cmp = AffinePoint {
285+
x: h2c_q.x,
286+
y: h2c_q.y,
287+
};
288+
289+
let f_cmp =
290+
crate::halo2curves_shims::bls12_381::Bls12_381::multi_miller_loop(&[p_cmp], &[q_cmp]);
291+
let (c_cmp, s_cmp) = crate::halo2curves_shims::bls12_381::Bls12_381::final_exp_hint(&f_cmp);
292+
let c_cmp = convert_bls12381_halo2_fq12_to_fp12(c_cmp);
293+
let s_cmp = convert_bls12381_halo2_fq12_to_fp12(s_cmp);
294+
295+
assert_eq!(c, c_cmp);
296+
assert_eq!(s, s_cmp);
297+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use halo2curves_axiom::bls12_381::{Fq, Fq12, Fq2, G2Affine};
2+
use openvm_algebra_guest::{field::FieldExtension, IntMod};
3+
use openvm_ecc_guest::weierstrass::WeierstrassPoint;
4+
5+
use super::{Fp, Fp12, Fp2};
6+
use crate::bls12_381::G2Affine as OpenVmG2Affine;
7+
8+
pub(crate) fn convert_bls12381_halo2_fq_to_fp(x: Fq) -> Fp {
9+
let bytes = x.to_bytes();
10+
Fp::from_le_bytes(&bytes)
11+
}
12+
13+
pub(crate) fn convert_bls12381_halo2_fq2_to_fp2(x: Fq2) -> Fp2 {
14+
Fp2::new(
15+
convert_bls12381_halo2_fq_to_fp(x.c0),
16+
convert_bls12381_halo2_fq_to_fp(x.c1),
17+
)
18+
}
19+
20+
pub(crate) fn convert_bls12381_halo2_fq12_to_fp12(x: Fq12) -> Fp12 {
21+
Fp12 {
22+
c: x.to_coeffs().map(convert_bls12381_halo2_fq2_to_fp2),
23+
}
24+
}
25+
26+
pub(crate) fn convert_bls12381_fp_to_halo2_fq(x: Fp) -> Fq {
27+
Fq::from_bytes(&x.0).unwrap()
28+
}
29+
30+
pub(crate) fn convert_bls12381_fp2_to_halo2_fq2(x: Fp2) -> Fq2 {
31+
Fq2 {
32+
c0: convert_bls12381_fp_to_halo2_fq(x.c0.clone()),
33+
c1: convert_bls12381_fp_to_halo2_fq(x.c1.clone()),
34+
}
35+
}
36+
37+
#[allow(unused)]
38+
pub(crate) fn convert_bls12381_fp12_to_halo2_fq12(x: Fp12) -> Fq12 {
39+
let c = x.to_coeffs();
40+
Fq12::from_coeffs(c.map(convert_bls12381_fp2_to_halo2_fq2))
41+
}
42+
43+
#[allow(unused)]
44+
pub(crate) fn convert_g2_affine_halo2_to_openvm(p: G2Affine) -> OpenVmG2Affine {
45+
OpenVmG2Affine::from_xy_unchecked(
46+
convert_bls12381_halo2_fq2_to_fp2(p.x),
47+
convert_bls12381_halo2_fq2_to_fp2(p.y),
48+
)
49+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ use crate::pairing::PairingIntrinsics;
1818
mod fp12;
1919
mod fp2;
2020
pub mod pairing;
21+
#[cfg(all(feature = "halo2curves", not(target_os = "zkvm")))]
22+
pub(crate) mod utils;
2123

2224
pub use fp12::*;
2325
pub use fp2::*;

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ use crate::pairing::{
1616
Evaluatable, EvaluatedLine, FromLineDType, LineMulDType, MillerStep, MultiMillerLoop,
1717
PairingCheck, PairingCheckError, PairingIntrinsics, UnevaluatedLine,
1818
};
19+
#[cfg(all(feature = "halo2curves", not(target_os = "zkvm")))]
20+
use crate::{
21+
bn254::utils::{
22+
convert_bn254_fp2_to_halo2_fq2, convert_bn254_fp_to_halo2_fq,
23+
convert_bn254_halo2_fq12_to_fp12,
24+
},
25+
halo2curves_shims::bn254::Bn254 as Halo2CurvesBn254,
26+
pairing::FinalExp,
27+
};
1928

2029
// TODO[jpw]: make macro
2130
impl Evaluatable<Fp, Fp2> for UnevaluatedLine<Fp2> {
@@ -307,7 +316,35 @@ impl PairingCheck for Bn254 {
307316
) -> (Self::Fp12, Self::Fp12) {
308317
#[cfg(not(target_os = "zkvm"))]
309318
{
310-
todo!()
319+
#[cfg(not(feature = "halo2curves"))]
320+
panic!("`halo2curves` feature must be enabled to use pairing check hint on host");
321+
322+
#[cfg(feature = "halo2curves")]
323+
{
324+
let p_halo2 = P
325+
.iter()
326+
.map(|p| {
327+
AffinePoint::new(
328+
convert_bn254_fp_to_halo2_fq(p.x.clone()),
329+
convert_bn254_fp_to_halo2_fq(p.y.clone()),
330+
)
331+
})
332+
.collect::<Vec<_>>();
333+
let q_halo2 = Q
334+
.iter()
335+
.map(|q| {
336+
AffinePoint::new(
337+
convert_bn254_fp2_to_halo2_fq2(q.x.clone()),
338+
convert_bn254_fp2_to_halo2_fq2(q.y.clone()),
339+
)
340+
})
341+
.collect::<Vec<_>>();
342+
let fq12 = Halo2CurvesBn254::multi_miller_loop(&p_halo2, &q_halo2);
343+
let (c_fq12, s_fq12) = Halo2CurvesBn254::final_exp_hint(&fq12);
344+
let c = convert_bn254_halo2_fq12_to_fp12(c_fq12);
345+
let s = convert_bn254_halo2_fq12_to_fp12(s_fq12);
346+
(c, s)
347+
}
311348
}
312349
#[cfg(target_os = "zkvm")]
313350
{

0 commit comments

Comments
 (0)