revm/handler/handle_types/
execution.rs

1use crate::{
2    frame::EOFCreateFrame,
3    handler::mainnet,
4    interpreter::{CallInputs, CreateInputs, SharedMemory},
5    primitives::{db::Database, EVMError, Spec},
6    CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult,
7};
8use revm_interpreter::{
9    opcode::InstructionTables, CallOutcome, CreateOutcome, EOFCreateInputs, InterpreterAction,
10    InterpreterResult,
11};
12use std::{boxed::Box, sync::Arc};
13
14/// Handles first frame return handle.
15pub type LastFrameReturnHandle<'a, EXT, DB> = Arc<
16    dyn Fn(&mut Context<EXT, DB>, &mut FrameResult) -> Result<(), EVMError<<DB as Database>::Error>>
17        + 'a,
18>;
19
20/// Executes a single frame. Errors can be returned in the EVM context.
21pub type ExecuteFrameHandle<'a, EXT, DB> = Arc<
22    dyn Fn(
23            &mut Frame,
24            &mut SharedMemory,
25            &InstructionTables<'_, Context<EXT, DB>>,
26            &mut Context<EXT, DB>,
27        ) -> Result<InterpreterAction, EVMError<<DB as Database>::Error>>
28        + 'a,
29>;
30
31/// Handle sub call.
32pub type FrameCallHandle<'a, EXT, DB> = Arc<
33    dyn Fn(
34            &mut Context<EXT, DB>,
35            Box<CallInputs>,
36        ) -> Result<FrameOrResult, EVMError<<DB as Database>::Error>>
37        + 'a,
38>;
39
40/// Handle call return
41pub type FrameCallReturnHandle<'a, EXT, DB> = Arc<
42    dyn Fn(
43            &mut Context<EXT, DB>,
44            Box<CallFrame>,
45            InterpreterResult,
46        ) -> Result<CallOutcome, EVMError<<DB as Database>::Error>>
47        + 'a,
48>;
49
50/// Insert call outcome to the parent
51pub type InsertCallOutcomeHandle<'a, EXT, DB> = Arc<
52    dyn Fn(
53            &mut Context<EXT, DB>,
54            &mut Frame,
55            &mut SharedMemory,
56            CallOutcome,
57        ) -> Result<(), EVMError<<DB as Database>::Error>>
58        + 'a,
59>;
60
61/// Handle sub create.
62pub type FrameCreateHandle<'a, EXT, DB> = Arc<
63    dyn Fn(
64            &mut Context<EXT, DB>,
65            Box<CreateInputs>,
66        ) -> Result<FrameOrResult, EVMError<<DB as Database>::Error>>
67        + 'a,
68>;
69
70/// Handle create return
71pub type FrameCreateReturnHandle<'a, EXT, DB> = Arc<
72    dyn Fn(
73            &mut Context<EXT, DB>,
74            Box<CreateFrame>,
75            InterpreterResult,
76        ) -> Result<CreateOutcome, EVMError<<DB as Database>::Error>>
77        + 'a,
78>;
79
80/// Insert call outcome to the parent
81pub type InsertCreateOutcomeHandle<'a, EXT, DB> = Arc<
82    dyn Fn(
83            &mut Context<EXT, DB>,
84            &mut Frame,
85            CreateOutcome,
86        ) -> Result<(), EVMError<<DB as Database>::Error>>
87        + 'a,
88>;
89
90/// Handle EOF sub create.
91pub type FrameEOFCreateHandle<'a, EXT, DB> = Arc<
92    dyn Fn(
93            &mut Context<EXT, DB>,
94            Box<EOFCreateInputs>,
95        ) -> Result<FrameOrResult, EVMError<<DB as Database>::Error>>
96        + 'a,
97>;
98
99/// Handle EOF create return
100pub type FrameEOFCreateReturnHandle<'a, EXT, DB> = Arc<
101    dyn Fn(
102            &mut Context<EXT, DB>,
103            Box<EOFCreateFrame>,
104            InterpreterResult,
105        ) -> Result<CreateOutcome, EVMError<<DB as Database>::Error>>
106        + 'a,
107>;
108
109/// Insert EOF crate outcome to the parent
110pub type InsertEOFCreateOutcomeHandle<'a, EXT, DB> = Arc<
111    dyn Fn(
112            &mut Context<EXT, DB>,
113            &mut Frame,
114            CreateOutcome,
115        ) -> Result<(), EVMError<<DB as Database>::Error>>
116        + 'a,
117>;
118
119/// Handles related to stack frames.
120pub struct ExecutionHandler<'a, EXT, DB: Database> {
121    /// Handles last frame return, modified gas for refund and
122    /// sets tx gas limit.
123    pub last_frame_return: LastFrameReturnHandle<'a, EXT, DB>,
124    /// Executes a single frame.
125    pub execute_frame: ExecuteFrameHandle<'a, EXT, DB>,
126    /// Frame call
127    pub call: FrameCallHandle<'a, EXT, DB>,
128    /// Call return
129    pub call_return: FrameCallReturnHandle<'a, EXT, DB>,
130    /// Insert call outcome
131    pub insert_call_outcome: InsertCallOutcomeHandle<'a, EXT, DB>,
132    /// Frame crate
133    pub create: FrameCreateHandle<'a, EXT, DB>,
134    /// Crate return
135    pub create_return: FrameCreateReturnHandle<'a, EXT, DB>,
136    /// Insert create outcome.
137    pub insert_create_outcome: InsertCreateOutcomeHandle<'a, EXT, DB>,
138    /// Frame EOFCreate
139    pub eofcreate: FrameEOFCreateHandle<'a, EXT, DB>,
140    /// EOFCreate return
141    pub eofcreate_return: FrameEOFCreateReturnHandle<'a, EXT, DB>,
142    /// Insert EOFCreate outcome.
143    pub insert_eofcreate_outcome: InsertEOFCreateOutcomeHandle<'a, EXT, DB>,
144}
145
146impl<'a, EXT: 'a, DB: Database + 'a> ExecutionHandler<'a, EXT, DB> {
147    /// Creates mainnet ExecutionHandler.
148    pub fn new<SPEC: Spec + 'a>() -> Self {
149        Self {
150            last_frame_return: Arc::new(mainnet::last_frame_return::<SPEC, EXT, DB>),
151            execute_frame: Arc::new(mainnet::execute_frame::<SPEC, EXT, DB>),
152            call: Arc::new(mainnet::call::<SPEC, EXT, DB>),
153            call_return: Arc::new(mainnet::call_return::<EXT, DB>),
154            insert_call_outcome: Arc::new(mainnet::insert_call_outcome),
155            create: Arc::new(mainnet::create::<SPEC, EXT, DB>),
156            create_return: Arc::new(mainnet::create_return::<SPEC, EXT, DB>),
157            insert_create_outcome: Arc::new(mainnet::insert_create_outcome),
158            eofcreate: Arc::new(mainnet::eofcreate::<SPEC, EXT, DB>),
159            eofcreate_return: Arc::new(mainnet::eofcreate_return::<SPEC, EXT, DB>),
160            insert_eofcreate_outcome: Arc::new(mainnet::insert_eofcreate_outcome),
161        }
162    }
163}
164
165impl<EXT, DB: Database> ExecutionHandler<'_, EXT, DB> {
166    /// Executes single frame.
167    #[inline]
168    pub fn execute_frame(
169        &self,
170        frame: &mut Frame,
171        shared_memory: &mut SharedMemory,
172        instruction_tables: &InstructionTables<'_, Context<EXT, DB>>,
173        context: &mut Context<EXT, DB>,
174    ) -> Result<InterpreterAction, EVMError<DB::Error>> {
175        (self.execute_frame)(frame, shared_memory, instruction_tables, context)
176    }
177
178    /// Handle call return, depending on instruction result gas will be reimbursed or not.
179    #[inline]
180    pub fn last_frame_return(
181        &self,
182        context: &mut Context<EXT, DB>,
183        frame_result: &mut FrameResult,
184    ) -> Result<(), EVMError<DB::Error>> {
185        (self.last_frame_return)(context, frame_result)
186    }
187
188    /// Call frame call handler.
189    #[inline]
190    pub fn call(
191        &self,
192        context: &mut Context<EXT, DB>,
193        inputs: Box<CallInputs>,
194    ) -> Result<FrameOrResult, EVMError<DB::Error>> {
195        (self.call)(context, inputs)
196    }
197
198    /// Call registered handler for call return.
199    #[inline]
200    pub fn call_return(
201        &self,
202        context: &mut Context<EXT, DB>,
203        frame: Box<CallFrame>,
204        interpreter_result: InterpreterResult,
205    ) -> Result<CallOutcome, EVMError<DB::Error>> {
206        (self.call_return)(context, frame, interpreter_result)
207    }
208
209    /// Call registered handler for inserting call outcome.
210    #[inline]
211    pub fn insert_call_outcome(
212        &self,
213        context: &mut Context<EXT, DB>,
214        frame: &mut Frame,
215        shared_memory: &mut SharedMemory,
216        outcome: CallOutcome,
217    ) -> Result<(), EVMError<DB::Error>> {
218        (self.insert_call_outcome)(context, frame, shared_memory, outcome)
219    }
220
221    /// Call Create frame
222    #[inline]
223    pub fn create(
224        &self,
225        context: &mut Context<EXT, DB>,
226        inputs: Box<CreateInputs>,
227    ) -> Result<FrameOrResult, EVMError<DB::Error>> {
228        (self.create)(context, inputs)
229    }
230
231    /// Call handler for create return.
232    #[inline]
233    pub fn create_return(
234        &self,
235        context: &mut Context<EXT, DB>,
236        frame: Box<CreateFrame>,
237        interpreter_result: InterpreterResult,
238    ) -> Result<CreateOutcome, EVMError<DB::Error>> {
239        (self.create_return)(context, frame, interpreter_result)
240    }
241
242    /// Call handler for inserting create outcome.
243    #[inline]
244    pub fn insert_create_outcome(
245        &self,
246        context: &mut Context<EXT, DB>,
247        frame: &mut Frame,
248        outcome: CreateOutcome,
249    ) -> Result<(), EVMError<DB::Error>> {
250        (self.insert_create_outcome)(context, frame, outcome)
251    }
252
253    /// Call Create frame
254    #[inline]
255    pub fn eofcreate(
256        &self,
257        context: &mut Context<EXT, DB>,
258        inputs: Box<EOFCreateInputs>,
259    ) -> Result<FrameOrResult, EVMError<DB::Error>> {
260        (self.eofcreate)(context, inputs)
261    }
262
263    /// Call handler for create return.
264    #[inline]
265    pub fn eofcreate_return(
266        &self,
267        context: &mut Context<EXT, DB>,
268        frame: Box<EOFCreateFrame>,
269        interpreter_result: InterpreterResult,
270    ) -> Result<CreateOutcome, EVMError<DB::Error>> {
271        (self.eofcreate_return)(context, frame, interpreter_result)
272    }
273
274    /// Call handler for inserting create outcome.
275    #[inline]
276    pub fn insert_eofcreate_outcome(
277        &self,
278        context: &mut Context<EXT, DB>,
279        frame: &mut Frame,
280        outcome: CreateOutcome,
281    ) -> Result<(), EVMError<DB::Error>> {
282        (self.insert_eofcreate_outcome)(context, frame, outcome)
283    }
284}