revm_handler/
api.rs

1use crate::{
2    instructions::InstructionProvider, EthFrame, Handler, MainnetHandler, PrecompileProvider,
3};
4use context::{
5    result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction, ResultAndState},
6    Block, ContextSetters, ContextTr, Database, Evm, JournalOutput, JournalTr, Transaction,
7};
8use database_interface::DatabaseCommit;
9use interpreter::{interpreter::EthInterpreter, InterpreterResult};
10
11/// Execute EVM transactions. Main trait for transaction execution.
12pub trait ExecuteEvm {
13    /// Output of transaction execution.
14    type Output;
15    /// Transaction type.
16    type Tx: Transaction;
17    /// Block type.
18    type Block: Block;
19
20    /// Set the transaction.
21    fn set_tx(&mut self, tx: Self::Tx);
22
23    /// Set the block.
24    fn set_block(&mut self, block: Self::Block);
25
26    /// Transact the transaction that is set in the context.
27    fn replay(&mut self) -> Self::Output;
28
29    /// Transact the given transaction.
30    ///
31    /// Internally sets transaction in context and use `replay` to execute the transaction.
32    fn transact(&mut self, tx: Self::Tx) -> Self::Output {
33        self.set_tx(tx);
34        self.replay()
35    }
36}
37
38/// Extension of the [`ExecuteEvm`] trait that adds a method that commits the state after execution.
39pub trait ExecuteCommitEvm: ExecuteEvm {
40    /// Commit output of transaction execution.
41    type CommitOutput;
42
43    /// Transact the transaction and commit to the state.
44    fn replay_commit(&mut self) -> Self::CommitOutput;
45
46    /// Transact the transaction and commit to the state.
47    fn transact_commit(&mut self, tx: Self::Tx) -> Self::CommitOutput {
48        self.set_tx(tx);
49        self.replay_commit()
50    }
51}
52
53impl<CTX, INSP, INST, PRECOMPILES> ExecuteEvm for Evm<CTX, INSP, INST, PRECOMPILES>
54where
55    CTX: ContextTr<Journal: JournalTr<FinalOutput = JournalOutput>> + ContextSetters,
56    INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
57    PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
58{
59    type Output = Result<
60        ResultAndState<HaltReason>,
61        EVMError<<CTX::Db as Database>::Error, InvalidTransaction>,
62    >;
63
64    type Tx = <CTX as ContextTr>::Tx;
65
66    type Block = <CTX as ContextTr>::Block;
67
68    fn replay(&mut self) -> Self::Output {
69        let mut t = MainnetHandler::<_, _, EthFrame<_, _, _>>::default();
70        t.run(self)
71    }
72
73    fn set_tx(&mut self, tx: Self::Tx) {
74        self.data.ctx.set_tx(tx);
75    }
76
77    fn set_block(&mut self, block: Self::Block) {
78        self.data.ctx.set_block(block);
79    }
80}
81
82impl<CTX, INSP, INST, PRECOMPILES> ExecuteCommitEvm for Evm<CTX, INSP, INST, PRECOMPILES>
83where
84    CTX: ContextTr<Journal: JournalTr<FinalOutput = JournalOutput>, Db: DatabaseCommit>
85        + ContextSetters,
86    INST: InstructionProvider<Context = CTX, InterpreterTypes = EthInterpreter>,
87    PRECOMPILES: PrecompileProvider<CTX, Output = InterpreterResult>,
88{
89    type CommitOutput = Result<
90        ExecutionResult<HaltReason>,
91        EVMError<<CTX::Db as Database>::Error, InvalidTransaction>,
92    >;
93
94    fn replay_commit(&mut self) -> Self::CommitOutput {
95        self.replay().map(|r| {
96            self.db().commit(r.state);
97            r.result
98        })
99    }
100}