1mod handle_types;
3pub mod mainnet;
4pub mod register;
5
6pub use handle_types::*;
8
9use crate::{
11 interpreter::{opcode::InstructionTables, Host, InterpreterAction, SharedMemory},
12 primitives::{db::Database, spec_to_generic, EVMError, HandlerCfg, Spec, SpecId},
13 Context, Frame,
14};
15use core::mem;
16use register::{EvmHandler, HandleRegisters};
17use std::vec::Vec;
18
19use self::register::{HandleRegister, HandleRegisterBox};
20
21pub struct Handler<'a, H: Host + 'a, EXT, DB: Database> {
25 pub cfg: HandlerCfg,
27 pub instruction_table: InstructionTables<'a, H>,
29 pub registers: Vec<HandleRegisters<'a, EXT, DB>>,
31 pub validation: ValidationHandler<'a, EXT, DB>,
33 pub pre_execution: PreExecutionHandler<'a, EXT, DB>,
35 pub post_execution: PostExecutionHandler<'a, EXT, DB>,
37 pub execution: ExecutionHandler<'a, EXT, DB>,
39}
40
41impl<'a, EXT, DB: Database> EvmHandler<'a, EXT, DB> {
42 pub fn new(cfg: HandlerCfg) -> Self {
47 cfg_if::cfg_if! {
48 if #[cfg(feature = "optimism")] {
49 if cfg.is_optimism {
50 Handler::optimism_with_spec(cfg.spec_id)
51 } else {
52 Handler::mainnet_with_spec(cfg.spec_id)
53 }
54 } else {
55 Handler::mainnet_with_spec(cfg.spec_id)
56 }
57 }
58 }
59
60 pub fn mainnet<SPEC: Spec>() -> Self {
62 Self {
63 cfg: HandlerCfg::new(SPEC::SPEC_ID),
64 instruction_table: InstructionTables::new_plain::<SPEC>(),
65 registers: Vec::new(),
66 validation: ValidationHandler::new::<SPEC>(),
67 pre_execution: PreExecutionHandler::new::<SPEC>(),
68 post_execution: PostExecutionHandler::new::<SPEC>(),
69 execution: ExecutionHandler::new::<SPEC>(),
70 }
71 }
72
73 pub fn is_optimism(&self) -> bool {
75 self.cfg.is_optimism()
76 }
77
78 #[cfg(feature = "optimism")]
80 pub fn optimism<SPEC: Spec>() -> Self {
81 let mut handler = Self::mainnet::<SPEC>();
82 handler.cfg.is_optimism = true;
83 handler.append_handler_register(HandleRegisters::Plain(
84 crate::optimism::optimism_handle_register::<DB, EXT>,
85 ));
86 handler
87 }
88
89 #[cfg(feature = "optimism")]
91 pub fn optimism_with_spec(spec_id: SpecId) -> Self {
92 spec_to_generic!(spec_id, Self::optimism::<SPEC>())
93 }
94
95 pub fn mainnet_with_spec(spec_id: SpecId) -> Self {
98 spec_to_generic!(spec_id, Self::mainnet::<SPEC>())
99 }
100
101 pub fn cfg(&self) -> HandlerCfg {
103 self.cfg
104 }
105
106 pub fn spec_id(&self) -> SpecId {
108 self.cfg.spec_id
109 }
110
111 pub fn execute_frame(
113 &self,
114 frame: &mut Frame,
115 shared_memory: &mut SharedMemory,
116 context: &mut Context<EXT, DB>,
117 ) -> Result<InterpreterAction, EVMError<DB::Error>> {
118 self.execution
119 .execute_frame(frame, shared_memory, &self.instruction_table, context)
120 }
121
122 pub fn take_instruction_table(&mut self) -> InstructionTables<'a, Context<EXT, DB>> {
124 let spec_id = self.spec_id();
125 mem::replace(
126 &mut self.instruction_table,
127 spec_to_generic!(spec_id, InstructionTables::new_plain::<SPEC>()),
128 )
129 }
130
131 pub fn set_instruction_table(&mut self, table: InstructionTables<'a, Context<EXT, DB>>) {
133 self.instruction_table = table;
134 }
135
136 pub fn pre_execution(&self) -> &PreExecutionHandler<'a, EXT, DB> {
138 &self.pre_execution
139 }
140
141 pub fn post_execution(&self) -> &PostExecutionHandler<'a, EXT, DB> {
143 &self.post_execution
144 }
145
146 pub fn execution(&self) -> &ExecutionHandler<'a, EXT, DB> {
148 &self.execution
149 }
150
151 pub fn validation(&self) -> &ValidationHandler<'a, EXT, DB> {
153 &self.validation
154 }
155
156 pub fn append_handler_register(&mut self, register: HandleRegisters<'a, EXT, DB>) {
158 register.register(self);
159 self.registers.push(register);
160 }
161
162 pub fn append_handler_register_plain(&mut self, register: HandleRegister<EXT, DB>) {
164 register(self);
165 self.registers.push(HandleRegisters::Plain(register));
166 }
167
168 pub fn append_handler_register_box(&mut self, register: HandleRegisterBox<'a, EXT, DB>) {
170 register(self);
171 self.registers.push(HandleRegisters::Box(register));
172 }
173
174 pub fn pop_handle_register(&mut self) -> Option<HandleRegisters<'a, EXT, DB>> {
176 let out = self.registers.pop();
177 if out.is_some() {
178 let registers = core::mem::take(&mut self.registers);
179 let mut base_handler = Handler::mainnet_with_spec(self.cfg.spec_id);
180 for register in registers {
182 base_handler.append_handler_register(register)
183 }
184 *self = base_handler;
185 }
186 out
187 }
188
189 pub fn create_handle_generic<SPEC: Spec>(&mut self) -> EvmHandler<'a, EXT, DB> {
191 let registers = core::mem::take(&mut self.registers);
192 let mut base_handler = Handler::mainnet::<SPEC>();
193 for register in registers {
195 base_handler.append_handler_register(register)
196 }
197 base_handler
198 }
199
200 pub fn modify_spec_id(&mut self, spec_id: SpecId) {
202 if self.cfg.spec_id == spec_id {
203 return;
204 }
205
206 let registers = core::mem::take(&mut self.registers);
207 let mut handler = Handler::mainnet_with_spec(spec_id);
209 for register in registers {
211 handler.append_handler_register(register)
212 }
213 handler.cfg = self.cfg();
214 handler.cfg.spec_id = spec_id;
215 *self = handler;
216 }
217}
218
219#[cfg(test)]
220mod test {
221 use core::cell::RefCell;
222
223 use crate::{db::EmptyDB, primitives::EVMError};
224 use std::{rc::Rc, sync::Arc};
225
226 use super::*;
227
228 #[test]
229 fn test_handler_register_pop() {
230 let register = |inner: &Rc<RefCell<i32>>| -> HandleRegisterBox<'_, (), EmptyDB> {
231 let inner = inner.clone();
232 Box::new(move |h| {
233 *inner.borrow_mut() += 1;
234 h.post_execution.output = Arc::new(|_, _| Err(EVMError::Custom("test".to_string())))
235 })
236 };
237
238 let mut handler = EvmHandler::<(), EmptyDB>::new(HandlerCfg::new(SpecId::LATEST));
239 let test = Rc::new(RefCell::new(0));
240
241 handler.append_handler_register_box(register(&test));
242 assert_eq!(*test.borrow(), 1);
243
244 handler.append_handler_register_box(register(&test));
245 assert_eq!(*test.borrow(), 2);
246
247 assert!(handler.pop_handle_register().is_some());
248
249 assert_eq!(*test.borrow(), 3);
251 }
252}