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 mut outputs = Vec::new();
94        for (index, tx) in txs.enumerate() {
95            outputs.push(
96                self.transact_one(tx)
97                    .inspect_err(|_| {
98                        let _ = self.finalize();
99                    })
100                    .map_err(|error| TransactionIndexedError::new(error, index))?,
101            );
102        }
103        Ok(outputs)
104    }
105
106    /// Execute multiple transactions and finalize the state in a single operation.
107    ///
108    /// Internally calls [`ExecuteEvm::transact_many`] followed by [`ExecuteEvm::finalize`].
109    #[inline]
110    fn transact_many_finalize(
111        &mut self,
112        txs: impl Iterator<Item = Self::Tx>,
113    ) -> TransactManyFinalizeResult<Self::ExecutionResult, Self::State, Self::Error> {
114        // on error transact_multi will clear the journal
115        let result = self.transact_many(txs)?;
116        let state = self.finalize();
117        Ok(ExecResultAndState::new(result, state))
118    }
119
120    /// Execute previous transaction and finalize it.
121    fn replay(
122        &mut self,
123    ) -> Result<ExecResultAndState<Self::ExecutionResult, Self::State>, Self::Error>;
124}
125
126/// Extension of the [`ExecuteEvm`] trait that adds a method that commits the state after execution.
127pub trait ExecuteCommitEvm: ExecuteEvm {
128    /// Commit the state.
129    fn commit(&mut self, state: Self::State);
130
131    /// Finalize the state and commit it to the database.
132    ///
133    /// Internally calls `finalize` and `commit` functions.
134    #[inline]
135    fn commit_inner(&mut self) {
136        let state = self.finalize();
137        self.commit(state);
138    }
139
140    /// Transact the transaction and commit to the state.
141    #[inline]
142    fn transact_commit(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
143        let output = self.transact_one(tx)?;
144        self.commit_inner();
145        Ok(output)
146    }
147
148    /// Transact multiple transactions and commit to the state.
149    ///
150    /// Internally calls `transact_many` and `commit_inner` functions.
151    #[inline]
152    fn transact_many_commit(
153        &mut self,
154        txs: impl Iterator<Item = Self::Tx>,
155    ) -> Result<Vec<Self::ExecutionResult>, TransactionIndexedError<Self::Error>> {
156        let outputs = self.transact_many(txs)?;
157        self.commit_inner();
158        Ok(outputs)
159    }
160
161    /// Replay the transaction and commit to the state.
162    ///
163    /// Internally calls `replay` and `commit` functions.
164    #[inline]
165    fn replay_commit(&mut self) -> Result<Self::ExecutionResult, Self::Error> {
166        let result = self.replay()?;
167        self.commit(result.state);
168        Ok(result.result)
169    }
170}
171
172impl<CTX, INSP, INST, PRECOMPILES> ExecuteEvm
173    for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
174where
175    CTX: ContextTr<Journal: JournalTr<State = EvmState>> + ContextSetters,
176    INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
177    PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
178{
179    type ExecutionResult = ExecutionResult<HaltReason>;
180    type State = EvmState;
181    type Error = EVMError<<CTX::Db as Database>::Error, InvalidTransaction>;
182    type Tx = <CTX as ContextTr>::Tx;
183    type Block = <CTX as ContextTr>::Block;
184
185    #[inline]
186    fn transact_one(&mut self, tx: Self::Tx) -> Result<Self::ExecutionResult, Self::Error> {
187        self.ctx.set_tx(tx);
188        MainnetHandler::default().run(self)
189    }
190
191    #[inline]
192    fn finalize(&mut self) -> Self::State {
193        self.journal_mut().finalize()
194    }
195
196    #[inline]
197    fn set_block(&mut self, block: Self::Block) {
198        self.ctx.set_block(block);
199    }
200
201    #[inline]
202    fn replay(&mut self) -> Result<ResultAndState<HaltReason>, Self::Error> {
203        MainnetHandler::default().run(self).map(|result| {
204            let state = self.finalize();
205            ResultAndState::new(result, state)
206        })
207    }
208}
209
210impl<CTX, INSP, INST, PRECOMPILES> ExecuteCommitEvm
211    for Evm<CTX, INSP, INST, PRECOMPILES, EthFrame<EthInterpreter>>
212where
213    CTX: ContextTr<Journal: JournalTr<State = EvmState>, Db: DatabaseCommit> + ContextSetters,
214    INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
215    PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
216{
217    #[inline]
218    fn commit(&mut self, state: Self::State) {
219        self.db_mut().commit(state);
220    }
221}