openvm_keccak256_transpiler/
lib.rs

1use core::panic;
2
3use openvm_instructions::{riscv::RV32_MEMORY_AS, LocalOpcode};
4use openvm_instructions_derive::LocalOpcode;
5use openvm_keccak256_guest::{KECCAKF_FUNCT7, OPCODE, XORIN_FUNCT3, XORIN_FUNCT7};
6use openvm_stark_backend::p3_field::PrimeField32;
7use openvm_transpiler::{util::from_r_type, TranspilerExtension, TranspilerOutput};
8use rrs_lib::instruction_formats::RType;
9use strum::{EnumCount, EnumIter, FromRepr};
10
11#[derive(
12    Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EnumCount, EnumIter, FromRepr, LocalOpcode,
13)]
14#[opcode_offset = 0x310]
15#[repr(usize)]
16pub enum KeccakfOpcode {
17    KECCAKF,
18}
19
20#[derive(
21    Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EnumCount, EnumIter, FromRepr, LocalOpcode,
22)]
23#[opcode_offset = 0x311]
24#[repr(usize)]
25pub enum XorinOpcode {
26    XORIN,
27}
28
29#[derive(Default)]
30pub struct Keccak256TranspilerExtension;
31
32impl<F: PrimeField32> TranspilerExtension<F> for Keccak256TranspilerExtension {
33    fn process_custom(&self, instruction_stream: &[u32]) -> Option<TranspilerOutput<F>> {
34        if instruction_stream.is_empty() {
35            return None;
36        }
37        let instruction_u32 = instruction_stream[0];
38        let opcode = (instruction_u32 & 0x7f) as u8;
39        let funct3 = ((instruction_u32 >> 12) & 0b111) as u8;
40
41        // Safety note: KECCAKF_FUNCT3 == XORIN_FUNCT3 so it suffices to check once
42        if (opcode, funct3) != (OPCODE, XORIN_FUNCT3) {
43            return None;
44        }
45
46        let dec_insn = RType::new(instruction_u32);
47
48        if dec_insn.funct7 != XORIN_FUNCT7 as u32 && dec_insn.funct7 != KECCAKF_FUNCT7 as u32 {
49            return None;
50        }
51
52        let instruction = if dec_insn.funct7 == XORIN_FUNCT7 as u32 {
53            from_r_type(
54                XorinOpcode::XORIN.global_opcode().as_usize(),
55                RV32_MEMORY_AS as usize,
56                &dec_insn,
57                true,
58            )
59        } else {
60            from_r_type(
61                KeccakfOpcode::KECCAKF.global_opcode().as_usize(),
62                RV32_MEMORY_AS as usize,
63                &dec_insn,
64                true,
65            )
66        };
67
68        Some(TranspilerOutput::one_to_one(instruction))
69    }
70}