openvm_sha256_circuit/extension/
mod.rs1use std::{result::Result, sync::Arc};
2
3use derive_more::derive::From;
4use openvm_circuit::{
5 arch::{
6 AirInventory, AirInventoryError, ChipInventory, ChipInventoryError,
7 ExecutorInventoryBuilder, ExecutorInventoryError, RowMajorMatrixArena, VmCircuitExtension,
8 VmExecutionExtension, VmProverExtension,
9 },
10 system::memory::SharedMemoryHelper,
11};
12use openvm_circuit_derive::{AnyEnum, Executor, MeteredExecutor, PreflightExecutor};
13use openvm_circuit_primitives::bitwise_op_lookup::{
14 BitwiseOperationLookupAir, BitwiseOperationLookupBus, BitwiseOperationLookupChip,
15 SharedBitwiseOperationLookupChip,
16};
17use openvm_instructions::*;
18use openvm_sha256_transpiler::Rv32Sha256Opcode;
19use openvm_stark_backend::{
20 config::{StarkGenericConfig, Val},
21 p3_field::PrimeField32,
22 prover::cpu::{CpuBackend, CpuDevice},
23};
24use openvm_stark_sdk::engine::StarkEngine;
25use serde::{Deserialize, Serialize};
26use strum::IntoEnumIterator;
27
28use crate::*;
29
30cfg_if::cfg_if! {
31 if #[cfg(feature = "cuda")] {
32 mod cuda;
33 pub use self::cuda::*;
34 pub use self::cuda::Sha256GpuProverExt as Sha256ProverExt;
35 } else {
36 pub use self::Sha2CpuProverExt as Sha256ProverExt;
37 }
38}
39
40#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
42pub struct Sha256;
43
44#[derive(Clone, From, AnyEnum, Executor, MeteredExecutor, PreflightExecutor)]
45#[cfg_attr(
46 feature = "aot",
47 derive(
48 openvm_circuit_derive::AotExecutor,
49 openvm_circuit_derive::AotMeteredExecutor
50 )
51)]
52pub enum Sha256Executor {
53 Sha256(Sha256VmExecutor),
54}
55
56impl<F> VmExecutionExtension<F> for Sha256 {
57 type Executor = Sha256Executor;
58
59 fn extend_execution(
60 &self,
61 inventory: &mut ExecutorInventoryBuilder<F, Sha256Executor>,
62 ) -> Result<(), ExecutorInventoryError> {
63 let pointer_max_bits = inventory.pointer_max_bits();
64 let sha256_step = Sha256VmExecutor::new(Rv32Sha256Opcode::CLASS_OFFSET, pointer_max_bits);
65 inventory.add_executor(
66 sha256_step,
67 Rv32Sha256Opcode::iter().map(|x| x.global_opcode()),
68 )?;
69
70 Ok(())
71 }
72}
73
74impl<SC: StarkGenericConfig> VmCircuitExtension<SC> for Sha256 {
75 fn extend_circuit(&self, inventory: &mut AirInventory<SC>) -> Result<(), AirInventoryError> {
76 let pointer_max_bits = inventory.pointer_max_bits();
77
78 let bitwise_lu = {
79 let existing_air = inventory.find_air::<BitwiseOperationLookupAir<8>>().next();
80 if let Some(air) = existing_air {
81 air.bus
82 } else {
83 let bus = BitwiseOperationLookupBus::new(inventory.new_bus_idx());
84 let air = BitwiseOperationLookupAir::<8>::new(bus);
85 inventory.add_air(air);
86 air.bus
87 }
88 };
89
90 let sha256 = Sha256VmAir::new(
91 inventory.system().port(),
92 bitwise_lu,
93 pointer_max_bits,
94 inventory.new_bus_idx(),
95 );
96 inventory.add_air(sha256);
97
98 Ok(())
99 }
100}
101
102pub struct Sha2CpuProverExt;
103impl<E, SC, RA> VmProverExtension<E, RA, Sha256> for Sha2CpuProverExt
106where
107 SC: StarkGenericConfig,
108 E: StarkEngine<SC = SC, PB = CpuBackend<SC>, PD = CpuDevice<SC>>,
109 RA: RowMajorMatrixArena<Val<SC>>,
110 Val<SC>: PrimeField32,
111{
112 fn extend_prover(
113 &self,
114 _: &Sha256,
115 inventory: &mut ChipInventory<SC, RA, CpuBackend<SC>>,
116 ) -> Result<(), ChipInventoryError> {
117 let range_checker = inventory.range_checker()?.clone();
118 let timestamp_max_bits = inventory.timestamp_max_bits();
119 let mem_helper = SharedMemoryHelper::new(range_checker.clone(), timestamp_max_bits);
120 let pointer_max_bits = inventory.airs().pointer_max_bits();
121
122 let bitwise_lu = {
123 let existing_chip = inventory
124 .find_chip::<SharedBitwiseOperationLookupChip<8>>()
125 .next();
126 if let Some(chip) = existing_chip {
127 chip.clone()
128 } else {
129 let air: &BitwiseOperationLookupAir<8> = inventory.next_air()?;
130 let chip = Arc::new(BitwiseOperationLookupChip::new(air.bus));
131 inventory.add_periphery_chip(chip.clone());
132 chip
133 }
134 };
135
136 inventory.next_air::<Sha256VmAir>()?;
137 let sha256 = Sha256VmChip::new(
138 Sha256VmFiller::new(bitwise_lu, pointer_max_bits),
139 mem_helper,
140 );
141 inventory.add_executor_chip(sha256);
142
143 Ok(())
144 }
145}