openvm_sha2_transpiler/
lib.rs

1use openvm_instructions::{riscv::RV32_MEMORY_AS, LocalOpcode};
2use openvm_instructions_derive::LocalOpcode;
3use openvm_sha2_guest::{Sha2BaseFunct7, OPCODE, SHA2_FUNCT3};
4use openvm_stark_backend::p3_field::PrimeField32;
5use openvm_transpiler::{util::from_r_type, TranspilerExtension, TranspilerOutput};
6use rrs_lib::instruction_formats::RType;
7use strum::{EnumCount, EnumIter, FromRepr};
8
9// There is no SHA384 opcode because the SHA-384 compression function is
10// the same as the SHA-512 compression function.
11#[derive(
12    Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EnumCount, EnumIter, FromRepr, LocalOpcode,
13)]
14#[opcode_offset = 0x320]
15#[repr(usize)]
16pub enum Rv32Sha2Opcode {
17    SHA256,
18    SHA512,
19}
20
21#[derive(Default)]
22pub struct Sha2TranspilerExtension;
23
24impl<F: PrimeField32> TranspilerExtension<F> for Sha2TranspilerExtension {
25    fn process_custom(&self, instruction_stream: &[u32]) -> Option<TranspilerOutput<F>> {
26        if instruction_stream.is_empty() {
27            return None;
28        }
29        let instruction_u32 = instruction_stream[0];
30        let opcode = (instruction_u32 & 0x7f) as u8;
31        let funct3 = ((instruction_u32 >> 12) & 0b111) as u8;
32
33        if (opcode, funct3) != (OPCODE, SHA2_FUNCT3) {
34            return None;
35        }
36        let dec_insn = RType::new(instruction_u32);
37
38        if dec_insn.funct7 == Sha2BaseFunct7::Sha256 as u32 {
39            let instruction = from_r_type(
40                Rv32Sha2Opcode::SHA256.global_opcode().as_usize(),
41                RV32_MEMORY_AS as usize,
42                &dec_insn,
43                true,
44            );
45            Some(TranspilerOutput::one_to_one(instruction))
46        } else if dec_insn.funct7 == Sha2BaseFunct7::Sha512 as u32 {
47            let instruction = from_r_type(
48                Rv32Sha2Opcode::SHA512.global_opcode().as_usize(),
49                RV32_MEMORY_AS as usize,
50                &dec_insn,
51                true,
52            );
53            Some(TranspilerOutput::one_to_one(instruction))
54        } else {
55            None
56        }
57    }
58}