openvm_pairing_transpiler/
lib.rs

1use openvm_instructions::{
2    instruction::Instruction, riscv::RV32_REGISTER_NUM_LIMBS, PhantomDiscriminant,
3};
4use openvm_pairing_guest::{PairingBaseFunct7, OPCODE, PAIRING_FUNCT3};
5use openvm_stark_backend::p3_field::PrimeField32;
6use openvm_transpiler::{TranspilerExtension, TranspilerOutput};
7use rrs_lib::instruction_formats::RType;
8use strum::FromRepr;
9
10#[derive(Copy, Clone, Debug, PartialEq, Eq, FromRepr)]
11#[repr(u16)]
12pub enum PairingPhantom {
13    /// Uses `b` to determine the curve: `b` is the discriminant of `PairingCurve` kind.
14    /// Peeks at `[r32{0}(a)..r32{0}(a) + Fp::NUM_LIMBS * 12]_2` to get `f: Fp12` and then resets
15    /// the hint stream to equal `final_exp_hint(f) = (residue_witness, scaling_factor): (Fp12,
16    /// Fp12)` as `Fp::NUM_LIMBS * 12 * 2` bytes.
17    HintFinalExp = 0x30,
18}
19
20#[derive(Default)]
21pub struct PairingTranspilerExtension;
22
23impl<F: PrimeField32> TranspilerExtension<F> for PairingTranspilerExtension {
24    fn process_custom(&self, instruction_stream: &[u32]) -> Option<TranspilerOutput<F>> {
25        if instruction_stream.is_empty() {
26            return None;
27        }
28        let instruction_u32 = instruction_stream[0];
29        let opcode = (instruction_u32 & 0x7f) as u8;
30        let funct3 = ((instruction_u32 >> 12) & 0b111) as u8;
31
32        if opcode != OPCODE {
33            return None;
34        }
35        if funct3 != PAIRING_FUNCT3 {
36            return None;
37        }
38
39        let dec_insn = RType::new(instruction_u32);
40        let base_funct7 = (dec_insn.funct7 as u8) % PairingBaseFunct7::PAIRING_MAX_KINDS;
41        let pairing_idx = ((dec_insn.funct7 as u8) / PairingBaseFunct7::PAIRING_MAX_KINDS) as usize;
42        if let Some(PairingBaseFunct7::HintFinalExp) = PairingBaseFunct7::from_repr(base_funct7) {
43            assert_eq!(dec_insn.rd, 0);
44            // Return exits the outermost function
45            return Some(TranspilerOutput::one_to_one(Instruction::phantom(
46                PhantomDiscriminant(PairingPhantom::HintFinalExp as u16),
47                F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs1),
48                F::from_canonical_usize(RV32_REGISTER_NUM_LIMBS * dec_insn.rs2),
49                pairing_idx as u16,
50            )));
51        }
52        None
53    }
54}