revm_handler/
evm.rs

1use crate::{
2    instructions::InstructionProvider, EthFrame, Handler, MainnetHandler, PrecompileProvider,
3};
4use auto_impl::auto_impl;
5use context::{
6    result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction, ResultAndState},
7    Block, ContextSetters, ContextTr, Database, Evm, JournalOutput, JournalTr, Transaction,
8};
9use database_interface::DatabaseCommit;
10use interpreter::{
11    interpreter::EthInterpreter, Interpreter, InterpreterAction, InterpreterResult,
12    InterpreterTypes,
13};
14
15/// A trait that integrates context, instruction set, and precompiles to create an EVM struct.
16///
17/// In addition to execution capabilities, this trait provides getter methods for its component fields.
18#[auto_impl(&mut, Box)]
19pub trait EvmTr {
20    /// The context type that implements ContextTr to provide access to execution state
21    type Context: ContextTr;
22    /// The instruction set type that implements InstructionProvider to define available operations
23    type Instructions: InstructionProvider;
24    /// The type containing the available precompiled contracts
25    type Precompiles: PrecompileProvider<Self::Context>;
26
27    /// Executes the interpreter loop for the given interpreter instance.
28    /// Returns either a completion status or the next interpreter action to take.
29    fn run_interpreter(
30        &mut self,
31        interpreter: &mut Interpreter<
32            <Self::Instructions as InstructionProvider>::InterpreterTypes,
33        >,
34    ) -> <<Self::Instructions as InstructionProvider>::InterpreterTypes as InterpreterTypes>::Output;
35
36    /// Returns a mutable reference to the execution context
37    fn ctx(&mut self) -> &mut Self::Context;
38
39    /// Returns an immutable reference to the execution context
40    fn ctx_ref(&self) -> &Self::Context;
41
42    /// Returns mutable references to both the context and instruction set.
43    /// This enables atomic access to both components when needed.
44    fn ctx_instructions(&mut self) -> (&mut Self::Context, &mut Self::Instructions);
45
46    /// Returns mutable references to both the context and precompiles.
47    /// This enables atomic access to both components when needed.
48    fn ctx_precompiles(&mut self) -> (&mut Self::Context, &mut Self::Precompiles);
49}
50
51/// Execute EVM transactions. Main trait for transaction execution.
52pub trait ExecuteEvm {
53    /// Output of transaction execution.
54    type Output;
55    /// Transaction type.
56    type Tx: Transaction;
57    /// Block type.
58    type Block: Block;
59
60    /// Set the transaction.
61    fn set_tx(&mut self, tx: Self::Tx);
62
63    /// Set the block.
64    fn set_block(&mut self, block: Self::Block);
65
66    /// Transact the transaction that is set in the context.
67    fn replay(&mut self) -> Self::Output;
68
69    /// Transact the given transaction.
70    ///
71    /// Internally sets transaction in context and use `replay` to execute the transaction.
72    fn transact(&mut self, tx: Self::Tx) -> Self::Output {
73        self.set_tx(tx);
74        self.replay()
75    }
76}
77
78/// Extension of the [`ExecuteEvm`] trait that adds a method that commits the state after execution.
79pub trait ExecuteCommitEvm: ExecuteEvm {
80    /// Commit output of transaction execution.
81    type CommitOutput;
82
83    /// Transact the transaction and commit to the state.
84    fn replay_commit(&mut self) -> Self::CommitOutput;
85
86    /// Transact the transaction and commit to the state.
87    fn transact_commit(&mut self, tx: Self::Tx) -> Self::CommitOutput {
88        self.set_tx(tx);
89        self.replay_commit()
90    }
91}
92
93impl<CTX, INSP, I, P> EvmTr for Evm<CTX, INSP, I, P>
94where
95    CTX: ContextTr,
96    I: InstructionProvider<
97        Context = CTX,
98        InterpreterTypes: InterpreterTypes<Output = InterpreterAction>,
99    >,
100    P: PrecompileProvider<CTX>,
101{
102    type Context = CTX;
103    type Instructions = I;
104    type Precompiles = P;
105
106    #[inline]
107    fn run_interpreter(
108        &mut self,
109        interpreter: &mut Interpreter<
110            <Self::Instructions as InstructionProvider>::InterpreterTypes,
111        >,
112    ) -> <<Self::Instructions as InstructionProvider>::InterpreterTypes as InterpreterTypes>::Output
113    {
114        let context = &mut self.data.ctx;
115        let instructions = &mut self.instruction;
116        interpreter.run_plain(instructions.instruction_table(), context)
117    }
118    #[inline]
119    fn ctx(&mut self) -> &mut Self::Context {
120        &mut self.data.ctx
121    }
122
123    #[inline]
124    fn ctx_ref(&self) -> &Self::Context {
125        &self.data.ctx
126    }
127
128    #[inline]
129    fn ctx_instructions(&mut self) -> (&mut Self::Context, &mut Self::Instructions) {
130        (&mut self.data.ctx, &mut self.instruction)
131    }
132
133    #[inline]
134    fn ctx_precompiles(&mut self) -> (&mut Self::Context, &mut Self::Precompiles) {
135        (&mut self.data.ctx, &mut self.precompiles)
136    }
137}
138
139impl<CTX, INSP, INST, PRECOMPILES> ExecuteEvm for Evm<CTX, INSP, INST, PRECOMPILES>
140where
141    CTX: ContextTr<Journal: JournalTr<FinalOutput = JournalOutput>> + ContextSetters,
142    INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
143    PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
144{
145    type Output = Result<
146        ResultAndState<HaltReason>,
147        EVMError<<CTX::Db as Database>::Error, InvalidTransaction>,
148    >;
149
150    type Tx = <CTX as ContextTr>::Tx;
151
152    type Block = <CTX as ContextTr>::Block;
153
154    fn replay(&mut self) -> Self::Output {
155        let mut t = MainnetHandler::<_, _, EthFrame<_, _, _>>::default();
156        t.run(self)
157    }
158
159    fn set_tx(&mut self, tx: Self::Tx) {
160        self.data.ctx.set_tx(tx);
161    }
162
163    fn set_block(&mut self, block: Self::Block) {
164        self.data.ctx.set_block(block);
165    }
166}
167
168impl<CTX, INSP, INST, PRECOMPILES> ExecuteCommitEvm for Evm<CTX, INSP, INST, PRECOMPILES>
169where
170    CTX: ContextTr<Journal: JournalTr<FinalOutput = JournalOutput>, Db: DatabaseCommit>
171        + ContextSetters,
172    INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
173    PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
174{
175    type CommitOutput = Result<
176        ExecutionResult<HaltReason>,
177        EVMError<<CTX::Db as Database>::Error, InvalidTransaction>,
178    >;
179
180    fn replay_commit(&mut self) -> Self::CommitOutput {
181        self.replay().map(|r| {
182            self.db().commit(r.state);
183            r.result
184        })
185    }
186}