revm_handler/
handler.rs

1use crate::{
2    execution, instructions::InstructionProvider, post_execution, pre_execution, validation, Frame,
3    FrameInitOrResult, FrameOrResult, FrameResult, ItemOrResult,
4};
5use auto_impl::auto_impl;
6use context::Evm;
7use context_interface::ContextTr;
8use context_interface::{
9    result::{HaltReasonTr, InvalidHeader, InvalidTransaction, ResultAndState},
10    Cfg, Database, Journal, Transaction,
11};
12use core::mem;
13use interpreter::{FrameInput, Host, InitialAndFloorGas, Interpreter, InterpreterAction};
14use precompile::PrecompileError;
15use primitives::Log;
16use state::EvmState;
17use std::{vec, vec::Vec};
18
19pub trait EvmTrError<EVM: EvmTr>:
20    From<InvalidTransaction>
21    + From<InvalidHeader>
22    + From<<<EVM::Context as ContextTr>::Db as Database>::Error>
23    + From<PrecompileError>
24{
25}
26
27impl<
28        EVM: EvmTr,
29        T: From<InvalidTransaction>
30            + From<InvalidHeader>
31            + From<<<EVM::Context as ContextTr>::Db as Database>::Error>
32            + From<PrecompileError>,
33    > EvmTrError<EVM> for T
34{
35}
36
37impl<CTX, INSP, I, P> EvmTr for Evm<CTX, INSP, I, P>
38where
39    CTX: ContextTr + Host,
40    I: InstructionProvider<Context = CTX, Output = InterpreterAction>,
41{
42    type Context = CTX;
43    type Instructions = I;
44    type Precompiles = P;
45
46    #[inline]
47    fn run_interpreter(
48        &mut self,
49        interpreter: &mut Interpreter<
50            <Self::Instructions as InstructionProvider>::InterpreterTypes,
51        >,
52    ) -> <Self::Instructions as InstructionProvider>::Output {
53        let context = &mut self.data.ctx;
54        let instructions = &mut self.instruction;
55        interpreter.run_plain(instructions.instruction_table(), context)
56    }
57    #[inline]
58    fn ctx(&mut self) -> &mut Self::Context {
59        &mut self.data.ctx
60    }
61
62    #[inline]
63    fn ctx_ref(&self) -> &Self::Context {
64        &self.data.ctx
65    }
66
67    #[inline]
68    fn ctx_instructions(&mut self) -> (&mut Self::Context, &mut Self::Instructions) {
69        (&mut self.data.ctx, &mut self.instruction)
70    }
71
72    #[inline]
73    fn ctx_precompiles(&mut self) -> (&mut Self::Context, &mut Self::Precompiles) {
74        (&mut self.data.ctx, &mut self.precompiles)
75    }
76}
77
78#[auto_impl(&mut, Box)]
79pub trait EvmTr {
80    type Context: ContextTr;
81    type Instructions: InstructionProvider;
82    type Precompiles;
83
84    fn run_interpreter(
85        &mut self,
86        interpreter: &mut Interpreter<
87            <Self::Instructions as InstructionProvider>::InterpreterTypes,
88        >,
89    ) -> <Self::Instructions as InstructionProvider>::Output;
90
91    fn ctx(&mut self) -> &mut Self::Context;
92
93    fn ctx_ref(&self) -> &Self::Context;
94
95    fn ctx_instructions(&mut self) -> (&mut Self::Context, &mut Self::Instructions);
96
97    fn ctx_precompiles(&mut self) -> (&mut Self::Context, &mut Self::Precompiles);
98}
99
100pub trait Handler {
101    type Evm: EvmTr<Context: ContextTr<Journal: Journal<FinalOutput = (EvmState, Vec<Log>)>>>;
102    type Error: EvmTrError<Self::Evm>;
103    // TODO `FrameResult` should be a generic trait.
104    // TODO `FrameInit` should be a generic.
105    type Frame: Frame<
106        Evm = Self::Evm,
107        Error = Self::Error,
108        FrameResult = FrameResult,
109        FrameInit = FrameInput,
110    >;
111    // TODO `HaltReason` should be part of the output.
112    type HaltReason: HaltReasonTr;
113
114    #[inline]
115    fn run(
116        &mut self,
117        evm: &mut Self::Evm,
118    ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
119        let init_and_floor_gas = self.validate(evm)?;
120        let eip7702_refund = self.pre_execution(evm)? as i64;
121        let exec_result = self.execution(evm, &init_and_floor_gas)?;
122        self.post_execution(evm, exec_result, init_and_floor_gas, eip7702_refund)
123    }
124    /// Call all validation functions
125    #[inline]
126    fn validate(&self, evm: &mut Self::Evm) -> Result<InitialAndFloorGas, Self::Error> {
127        self.validate_env(evm)?;
128        self.validate_tx_against_state(evm)?;
129        self.validate_initial_tx_gas(evm)
130    }
131
132    /// Call all Pre execution functions.
133    #[inline]
134    fn pre_execution(&self, evm: &mut Self::Evm) -> Result<u64, Self::Error> {
135        self.load_accounts(evm)?;
136        self.deduct_caller(evm)?;
137        let gas = self.apply_eip7702_auth_list(evm)?;
138        Ok(gas)
139    }
140
141    #[inline]
142    fn execution(
143        &mut self,
144        evm: &mut Self::Evm,
145        init_and_floor_gas: &InitialAndFloorGas,
146    ) -> Result<FrameResult, Self::Error> {
147        let gas_limit = evm.ctx().tx().gas_limit() - init_and_floor_gas.initial_gas;
148
149        // Create first frame action
150        let first_frame = self.create_first_frame(evm, gas_limit)?;
151        let mut frame_result = match first_frame {
152            ItemOrResult::Item(frame) => self.run_exec_loop(evm, frame)?,
153            ItemOrResult::Result(result) => result,
154        };
155
156        self.last_frame_result(evm, &mut frame_result)?;
157        Ok(frame_result)
158    }
159
160    #[inline]
161    fn post_execution(
162        &self,
163        evm: &mut Self::Evm,
164        mut exec_result: FrameResult,
165        init_and_floor_gas: InitialAndFloorGas,
166        eip7702_gas_refund: i64,
167    ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
168        // Calculate final refund and add EIP-7702 refund to gas.
169        self.refund(evm, &mut exec_result, eip7702_gas_refund);
170        // Check if gas floor is met and spent at least a floor gas.
171        self.eip7623_check_gas_floor(evm, &mut exec_result, init_and_floor_gas);
172        // Reimburse the caller
173        self.reimburse_caller(evm, &mut exec_result)?;
174        // Reward beneficiary
175        self.reward_beneficiary(evm, &mut exec_result)?;
176        // Prepare output of transaction.
177        let output = self.output(evm, exec_result)?;
178        // Clear any internal state.
179        self.clear(evm);
180        // Return output
181        Ok(output)
182    }
183
184    /* VALIDATION */
185
186    /// Validate env.
187    #[inline]
188    fn validate_env(&self, evm: &mut Self::Evm) -> Result<(), Self::Error> {
189        validation::validate_env(evm.ctx())
190    }
191
192    /// Validate transactions against state.
193    #[inline]
194    fn validate_tx_against_state(&self, evm: &mut Self::Evm) -> Result<(), Self::Error> {
195        validation::validate_tx_against_state(evm.ctx())
196    }
197
198    /// Validate initial gas.
199    #[inline]
200    fn validate_initial_tx_gas(&self, evm: &Self::Evm) -> Result<InitialAndFloorGas, Self::Error> {
201        let ctx = evm.ctx_ref();
202        validation::validate_initial_tx_gas(ctx.tx(), ctx.cfg().spec().into()).map_err(From::from)
203    }
204
205    /* PRE EXECUTION */
206
207    #[inline]
208    fn load_accounts(&self, evm: &mut Self::Evm) -> Result<(), Self::Error> {
209        pre_execution::load_accounts(evm.ctx())
210    }
211
212    #[inline]
213    fn apply_eip7702_auth_list(&self, evm: &mut Self::Evm) -> Result<u64, Self::Error> {
214        pre_execution::apply_eip7702_auth_list(evm.ctx())
215    }
216
217    #[inline]
218    fn deduct_caller(&self, evm: &mut Self::Evm) -> Result<(), Self::Error> {
219        pre_execution::deduct_caller(evm.ctx()).map_err(From::from)
220    }
221
222    /* EXECUTION */
223    #[inline]
224    fn create_first_frame(
225        &mut self,
226        evm: &mut Self::Evm,
227        gas_limit: u64,
228    ) -> Result<FrameOrResult<Self::Frame>, Self::Error> {
229        let ctx = evm.ctx_ref();
230        let init_frame = execution::create_init_frame(ctx.tx(), ctx.cfg().spec().into(), gas_limit);
231        self.frame_init_first(evm, init_frame)
232    }
233
234    #[inline]
235    fn last_frame_result(
236        &self,
237        evm: &mut Self::Evm,
238        frame_result: &mut <Self::Frame as Frame>::FrameResult,
239    ) -> Result<(), Self::Error> {
240        execution::last_frame_result(evm.ctx(), frame_result);
241        Ok(())
242    }
243
244    /* FRAMES */
245
246    #[inline]
247    fn frame_init_first(
248        &mut self,
249        evm: &mut Self::Evm,
250        frame_input: <Self::Frame as Frame>::FrameInit,
251    ) -> Result<FrameOrResult<Self::Frame>, Self::Error> {
252        Self::Frame::init_first(evm, frame_input)
253    }
254
255    #[inline]
256    fn frame_init(
257        &mut self,
258        frame: &Self::Frame,
259        evm: &mut Self::Evm,
260        frame_input: <Self::Frame as Frame>::FrameInit,
261    ) -> Result<FrameOrResult<Self::Frame>, Self::Error> {
262        Frame::init(frame, evm, frame_input)
263    }
264
265    #[inline]
266    fn frame_call(
267        &mut self,
268        frame: &mut Self::Frame,
269        evm: &mut Self::Evm,
270    ) -> Result<FrameInitOrResult<Self::Frame>, Self::Error> {
271        Frame::run(frame, evm)
272    }
273
274    #[inline]
275    fn frame_return_result(
276        &mut self,
277        frame: &mut Self::Frame,
278        evm: &mut Self::Evm,
279        result: <Self::Frame as Frame>::FrameResult,
280    ) -> Result<(), Self::Error> {
281        Self::Frame::return_result(frame, evm, result)
282    }
283
284    #[inline]
285    fn run_exec_loop(
286        &mut self,
287        evm: &mut Self::Evm,
288        frame: Self::Frame,
289    ) -> Result<FrameResult, Self::Error> {
290        let mut frame_stack: Vec<Self::Frame> = vec![frame];
291        loop {
292            let frame = frame_stack.last_mut().unwrap();
293            let call_or_result = self.frame_call(frame, evm)?;
294
295            let result = match call_or_result {
296                ItemOrResult::Item(init) => {
297                    match self.frame_init(frame, evm, init)? {
298                        ItemOrResult::Item(new_frame) => {
299                            frame_stack.push(new_frame);
300                            continue;
301                        }
302                        // Dont pop the frame as new frame was not created.
303                        ItemOrResult::Result(result) => result,
304                    }
305                }
306                ItemOrResult::Result(result) => {
307                    // Pop frame that returned result
308                    frame_stack.pop();
309                    result
310                }
311            };
312
313            let Some(frame) = frame_stack.last_mut() else {
314                return Ok(result);
315            };
316            self.frame_return_result(frame, evm, result)?;
317        }
318    }
319
320    /* POST EXECUTION */
321
322    /// Calculate final refund.
323    #[inline]
324    fn eip7623_check_gas_floor(
325        &self,
326        _evm: &mut Self::Evm,
327        exec_result: &mut <Self::Frame as Frame>::FrameResult,
328        init_and_floor_gas: InitialAndFloorGas,
329    ) {
330        post_execution::eip7623_check_gas_floor(exec_result.gas_mut(), init_and_floor_gas)
331    }
332
333    /// Calculate final refund.
334    #[inline]
335    fn refund(
336        &self,
337        evm: &mut Self::Evm,
338        exec_result: &mut <Self::Frame as Frame>::FrameResult,
339        eip7702_refund: i64,
340    ) {
341        let spec = evm.ctx().cfg().spec().into();
342        post_execution::refund(spec, exec_result.gas_mut(), eip7702_refund)
343    }
344
345    /// Reimburse the caller with balance it didn't spent.
346    #[inline]
347    fn reimburse_caller(
348        &self,
349        evm: &mut Self::Evm,
350        exec_result: &mut <Self::Frame as Frame>::FrameResult,
351    ) -> Result<(), Self::Error> {
352        post_execution::reimburse_caller(evm.ctx(), exec_result.gas_mut()).map_err(From::from)
353    }
354
355    /// Reward beneficiary with transaction rewards.
356    #[inline]
357    fn reward_beneficiary(
358        &self,
359        evm: &mut Self::Evm,
360        exec_result: &mut <Self::Frame as Frame>::FrameResult,
361    ) -> Result<(), Self::Error> {
362        post_execution::reward_beneficiary(evm.ctx(), exec_result.gas_mut()).map_err(From::from)
363    }
364
365    /// Main return handle, takes state from journal and transforms internal result to output.
366    #[inline]
367    fn output(
368        &self,
369        evm: &mut Self::Evm,
370        result: <Self::Frame as Frame>::FrameResult,
371    ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
372        let ctx = evm.ctx();
373        mem::replace(ctx.error(), Ok(()))?;
374        Ok(post_execution::output(ctx, result))
375    }
376
377    /// Called when execution ends.
378    ///
379    /// End handle in comparison to output handle will be called every time after execution.
380    ///
381    /// While output will be omitted in case of the error.
382    #[inline]
383    fn end(
384        &self,
385        _evm: &mut Self::Evm,
386        end_output: Result<ResultAndState<Self::HaltReason>, Self::Error>,
387    ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
388        end_output
389    }
390
391    /// Clean handler. It resets internal Journal state to default one.
392    ///
393    /// This handle is called every time regardless of the result of the transaction.
394    #[inline]
395    fn clear(&self, evm: &mut Self::Evm) {
396        evm.ctx().journal().clear();
397    }
398}