openvm_pairing_guest/pairing/
mod.rs1mod final_exp;
2mod line;
3mod miller_loop;
4mod miller_step;
5
6pub use final_exp::*;
7pub use line::*;
8pub use miller_loop::*;
9pub use miller_step::*;
10use openvm_algebra_guest::{
11 field::{ComplexConjugate, FieldExtension},
12 ExpBytes, Field, IntMod,
13};
14use openvm_ecc_guest::AffinePoint;
15
16use crate::PairingBaseFunct7;
17
18pub trait PairingIntrinsics {
19 type Fp: Field + IntMod;
20 type Fp2: Field + FieldExtension<Self::Fp> + ComplexConjugate;
21 type Fp12: FieldExtension<Self::Fp2> + ComplexConjugate;
22
23 const PAIRING_IDX: usize;
25 const XI: Self::Fp2;
27 const FROBENIUS_COEFFS: [[Self::Fp2; 5]; 12];
30
31 const FP2_TWO: Self::Fp2;
32 const FP2_THREE: Self::Fp2;
33}
34
35#[allow(non_snake_case)]
36pub trait PairingCheck {
37 type Fp: Field;
38 type Fp2: Field + FieldExtension<Self::Fp> + ComplexConjugate;
39 type Fp12: FieldExtension<Self::Fp2> + ComplexConjugate;
40
41 fn pairing_check_hint(
46 P: &[AffinePoint<Self::Fp>],
47 Q: &[AffinePoint<Self::Fp2>],
48 ) -> (Self::Fp12, Self::Fp12);
49
50 fn pairing_check(
51 P: &[AffinePoint<Self::Fp>],
52 Q: &[AffinePoint<Self::Fp2>],
53 ) -> Result<(), PairingCheckError>;
54}
55
56pub fn exp_check_fallback<F: Field + ExpBytes>(f: &F, exp: &[u8]) -> Result<(), PairingCheckError>
60where
61 for<'a> &'a F: core::ops::Mul<&'a F, Output = F>,
62{
63 if f.exp_bytes(true, exp) == F::ONE {
64 Ok(())
65 } else {
66 Err(PairingCheckError)
67 }
68}
69
70pub const fn shifted_funct7<P: PairingIntrinsics>(funct7: PairingBaseFunct7) -> usize {
71 P::PAIRING_IDX * (PairingBaseFunct7::PAIRING_MAX_KINDS as usize) + funct7 as usize
72}
73
74#[derive(Debug, Clone, PartialEq)]
75pub struct PairingCheckError;
76
77impl core::error::Error for PairingCheckError {}
78impl core::fmt::Display for PairingCheckError {
79 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80 write!(f, "Pairing check failed")
81 }
82}
83
84#[cfg(all(test, not(target_os = "zkvm")))]
85mod tests {
86 use num_bigint::BigUint;
87 use openvm_algebra_moduli_macros::{moduli_declare, moduli_init};
88
89 use super::*;
90
91 moduli_declare! {
92 F13 { modulus = "13" },
93 }
94
95 moduli_init! {
96 "13",
97 }
98
99 #[test]
100 fn test_pairing_check_fallback() {
101 let a = F13::from_u8(2);
102 let b = BigUint::from(12u32);
103 let result = exp_check_fallback(&a, &b.to_bytes_be());
104 assert_eq!(result, Ok(()));
105
106 let b = BigUint::from(11u32);
107 let result = exp_check_fallback(&a, &b.to_bytes_be());
108 assert_eq!(result, Err(PairingCheckError));
109 }
110}