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