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