revm_handler/
api.rs

1use crate::{
2    frame::EthFrame, instructions::InstructionProvider, Handler, MainnetHandler, PrecompileProvider,
3};
4use context::{
5    result::{
6        EVMError, ExecResultAndState, ExecutionResult, HaltReason, InvalidTransaction,
7        ResultAndState, ResultVecAndState,
8    },
9    Block, ContextSetters, ContextTr, Database, Evm, JournalTr, Transaction,
10};
11use database_interface::DatabaseCommit;
12use interpreter::{interpreter::EthInterpreter, InterpreterResult};
13use state::EvmState;
14use std::vec::Vec;
15
16/// Execute EVM transactions. Main trait for transaction execution.
17pub trait ExecuteEvm {
18    /// Output of transaction execution.
19    type ExecutionResult;
20    /// Output state type representing changes after execution.
21    type State;
22    /// Error type
23    type Error;
24    /// Transaction type.
25    type Tx: Transaction;
26    /// Block type.
27    type Block: Block;
28
29    /// Set the block.
30    fn set_block(&mut self, block: Self::Block);
31
32    /// Execute transaction and store state inside journal. Returns output of transaction execution.
33    ///
34    /// # Return Value
35    /// Returns only the execution result
36    ///
37    /// # Error Handling
38    /// If the transaction fails, the journal will revert all changes of given transaction.
39    /// For quicker error handling, use [`ExecuteEvm::transact`] that will drop the journal.
40    ///
41    /// # State Management
42    /// State changes are stored in the internal journal.
43    /// To retrieve the state, call [`ExecuteEvm::finalize`] after transaction execution.
44    ///
45    /// # History Note
46    /// Previously this function returned both output and state.
47    /// Now it follows a two-step process: execute then finalize.
48    fn transact_one(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error>;
49
50    /// Finalize execution, clearing the journal and returning the accumulated state changes.
51    ///
52    /// # State Management
53    /// Journal is cleared and can be used for next transaction.
54    fn finalize(&mut self) -> Self::State;
55
56    /// Transact the given transaction and finalize in a single operation.
57    ///
58    /// Internally calls [`ExecuteEvm::transact_one`] followed by [`ExecuteEvm::finalize`].
59    ///
60    /// # Outcome of Error
61    ///
62    /// If the transaction fails, the journal is considered broken.
63    #[inline]
64    fn transact(
65        &mut self,
66        tx: Self::Tx,
67    ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error> {
68        let output_or_error = self.transact_one(tx);
69        // finalize will clear the journal
70        let state = self.finalize();
71        let output = output_or_error?;
72        Ok(ExecResultAndState::new(output, state))
73    }
74
75    /// Execute multiple transactions without finalizing the state.
76    ///
77    /// Returns a vector of execution results. State changes are accumulated in the journal
78    /// but not finalized. Call [`ExecuteEvm::finalize`] after execution to retrieve state changes.
79    ///
80    /// # Outcome of Error
81    ///
82    /// If any transaction fails, the journal is finalized and the last error is returned.
83    ///
84    /// TODO add tx index to the error.
85    #[inline]
86    fn transact_many(
87        &mut self,
88        txs: impl Iterator<Item = Self::Tx>,
89    ) -> Result<Vec<Self::ExecutionResult>, Self::Error> {
90        let mut outputs = Vec::new();
91        for tx in txs {
92            outputs.push(self.transact_one(tx).inspect_err(|_| {
93                let _ = self.finalize();
94            })?);
95        }
96        Ok(outputs)
97    }
98
99    /// Execute multiple transactions and finalize the state in a single operation.
100    ///
101    /// Internally calls [`ExecuteEvm::transact_many`] followed by [`ExecuteEvm::finalize`].
102    #[inline]
103    fn transact_many_finalize(
104        &mut self,
105        txs: impl Iterator<Item = Self::Tx>,
106    ) -> Result<ResultVecAndState<Self::ExecutionResult, Self::State>, Self::Error> {
107        // on error transact_multi will clear the journal
108        let result = self.transact_many(txs)?;
109        let state = self.finalize();
110        Ok(ExecResultAndState::new(result, state))
111    }
112
113    /// Execute previous transaction and finalize it.
114    fn replay(
115        &mut self,
116    ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error>;
117}
118
119/// Extension of the [`ExecuteEvm`] trait that adds a method that commits the state after execution.
120pub trait ExecuteCommitEvm: ExecuteEvm {
121    /// Commit the state.
122    fn commit(&mut self, state: Self::State);
123
124    /// Finalize the state and commit it to the database.
125    ///
126    /// Internally calls `finalize` and `commit` functions.
127    #[inline]
128    fn commit_inner(&mut self) {
129        let state = self.finalize();
130        self.commit(state);
131    }
132
133    /// Transact the transaction and commit to the state.
134    #[inline]
135    fn transact_commit(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
136        let output = self.transact_one(tx)?;
137        self.commit_inner();
138        Ok(output)
139    }
140
141    /// Transact multiple transactions and commit to the state.
142    ///
143    /// Internally calls `transact_many` and `commit_inner` functions.
144    #[inline]
145    fn transact_many_commit(
146        &mut self,
147        txs: impl Iterator<Item = Self::Tx>,
148    ) -> Result<Vec<Self::ExecutionResult>, Self::Error> {
149        let outputs = self.transact_many(txs)?;
150        self.commit_inner();
151        Ok(outputs)
152    }
153
154    /// Replay the transaction and commit to the state.
155    ///
156    /// Internally calls `replay` and `commit` functions.
157    #[inline]
158    fn replay_commit(&mut self) -> Result<Self::ExecutionResult, Self::Error> {
159        let result = self.replay()?;
160        self.commit(result.state);
161        Ok(result.result)
162    }
163}
164
165impl<CTX, INSP, INST, PRECOMPILES> ExecuteEvm
166    for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
167where
168    CTX: ContextTr<Journal: JournalTr<State = EvmState>> + ContextSetters,
169    INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
170    PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
171{
172    type ExecutionResult = ExecutionResult<HaltReason>;
173    type State = EvmState;
174    type Error = EVMError<<CTX::Db as Database>::Error, InvalidTransaction>;
175    type Tx = <CTX as ContextTr>::Tx;
176    type Block = <CTX as ContextTr>::Block;
177
178    #[inline]
179    fn transact_one(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
180        self.ctx.set_tx(tx);
181        MainnetHandler::default().run(self)
182    }
183
184    #[inline]
185    fn finalize(&mut self) -> Self::State {
186        self.journal_mut().finalize()
187    }
188
189    #[inline]
190    fn set_block(&mut self, block: Self::Block) {
191        self.ctx.set_block(block);
192    }
193
194    #[inline]
195    fn replay(&mut self) -> Result<ResultAndState<HaltReason>, Self::Error> {
196        MainnetHandler::default().run(self).map(|result| {
197            let state = self.finalize();
198            ResultAndState::new(result, state)
199        })
200    }
201}
202
203impl<CTX, INSP, INST, PRECOMPILES> ExecuteCommitEvm
204    for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
205where
206    CTX: ContextTr<Journal: JournalTr<State = EvmState>, Db: DatabaseCommit> + ContextSetters,
207    INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
208    PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
209{
210    #[inline]
211    fn commit(&mut self, state: Self::State) {
212        self.db_mut().commit(state);
213    }
214}