revm_context_interface/
context.rs

1#![allow(clippy::type_complexity)]
2//! Context trait and related types.
3pub use crate::journaled_state::StateLoad;
4use crate::{
5    result::FromStringError, Block, Cfg, Database, Host, JournalTr, LocalContextTr, Transaction,
6};
7use auto_impl::auto_impl;
8use primitives::StorageValue;
9use std::string::String;
10
11/// Trait that defines the context of the EVM execution.
12///
13/// This trait is used to access the environment and state of the EVM.
14/// It is used to access the transaction, block, configuration, database, journal, and chain.
15/// It is also used to set the error of the EVM.
16///
17/// All functions have a `*_mut` variant except the function for [`ContextTr::tx`] and [`ContextTr::block`].
18#[auto_impl(&mut, Box)]
19pub trait ContextTr: Host {
20    /// Block type
21    type Block: Block;
22    /// Transaction type
23    type Tx: Transaction;
24    /// Configuration type
25    type Cfg: Cfg;
26    /// Database type
27    type Db: Database;
28    /// Journal type
29    type Journal: JournalTr<Database = Self::Db>;
30    /// Chain type
31    type Chain;
32    /// Local context type
33    type Local: LocalContextTr;
34
35    /// Get all contexts
36    fn all(
37        &self,
38    ) -> (
39        &Self::Block,
40        &Self::Tx,
41        &Self::Cfg,
42        &Self::Db,
43        &Self::Journal,
44        &Self::Chain,
45        &Self::Local,
46    );
47
48    /// Get all contexts mutably
49    fn all_mut(
50        &mut self,
51    ) -> (
52        &Self::Block,
53        &Self::Tx,
54        &Self::Cfg,
55        &mut Self::Journal,
56        &mut Self::Chain,
57        &mut Self::Local,
58    );
59
60    /// Get the transaction
61    fn tx(&self) -> &Self::Tx {
62        let (_, tx, _, _, _, _, _) = self.all();
63        tx
64    }
65    /// Get the block
66    fn block(&self) -> &Self::Block {
67        let (block, _, _, _, _, _, _) = self.all();
68        block
69    }
70    /// Get the configuration
71    fn cfg(&self) -> &Self::Cfg {
72        let (_, _, cfg, _, _, _, _) = self.all();
73        cfg
74    }
75    /// Get the journal
76    fn journal(&self) -> &Self::Journal {
77        let (_, _, _, _, journal, _, _) = self.all();
78        journal
79    }
80    /// Get the journal mutably
81    fn journal_mut(&mut self) -> &mut Self::Journal {
82        let (_, _, _, journal, _, _) = self.all_mut();
83        journal
84    }
85    /// Get the journal reference
86    fn journal_ref(&self) -> &Self::Journal {
87        self.journal()
88    }
89    /// Get the database
90    fn db(&self) -> &Self::Db {
91        let (_, _, _, db, _, _, _) = self.all();
92        db
93    }
94    /// Get the database mutably
95    fn db_mut(&mut self) -> &mut Self::Db {
96        let db = self.journal_mut().db_mut();
97        db
98    }
99    /// Get the database reference
100    fn db_ref(&self) -> &Self::Db {
101        self.db()
102    }
103    /// Get the chain
104    fn chain(&self) -> &Self::Chain {
105        let (_, _, _, _, _, chain, _) = self.all();
106        chain
107    }
108    /// Get the chain mutably
109    fn chain_mut(&mut self) -> &mut Self::Chain {
110        let (_, _, _, _, chain, _) = self.all_mut();
111        chain
112    }
113    /// Get the chain reference
114    fn chain_ref(&self) -> &Self::Chain {
115        self.chain()
116    }
117    /// Get the local context
118    fn local(&self) -> &Self::Local {
119        let (_, _, _, _, _, _, local) = self.all();
120        local
121    }
122    /// Get the local context mutably
123    fn local_mut(&mut self) -> &mut Self::Local {
124        let (_, _, _, _, _, local) = self.all_mut();
125        local
126    }
127    /// Get the local context reference
128    fn local_ref(&self) -> &Self::Local {
129        self.local()
130    }
131    /// Get the error
132    fn error(&mut self) -> &mut Result<(), ContextError<<Self::Db as Database>::Error>>;
133
134    /// Get the transaction and journal. It is used to efficiently load access list
135    /// into journal without copying them from transaction.
136    fn tx_journal_mut(&mut self) -> (&Self::Tx, &mut Self::Journal) {
137        let (_, tx, _, journal, _, _) = self.all_mut();
138        (tx, journal)
139    }
140
141    /// Get the transaction, configuration and mutable journal.
142    fn tx_block_cfg_journal_mut(
143        &mut self,
144    ) -> (&Self::Tx, &Self::Block, &Self::Cfg, &mut Self::Journal) {
145        let (block, tx, cfg, journal, _, _) = self.all_mut();
146        (tx, block, cfg, journal)
147    }
148
149    /// Get the transaction and local context. It is used to efficiently load initcode
150    /// into local context without copying them from transaction.
151    fn tx_local_mut(&mut self) -> (&Self::Tx, &mut Self::Local) {
152        let (_, tx, _, _, _, local) = self.all_mut();
153        (tx, local)
154    }
155}
156
157/// Inner Context error used for Interpreter to set error without returning it from instruction
158#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
159#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
160pub enum ContextError<DbError> {
161    /// Database error.
162    Db(DbError),
163    /// Custom string error.
164    Custom(String),
165}
166
167impl<DbError> FromStringError for ContextError<DbError> {
168    fn from_string(value: String) -> Self {
169        Self::Custom(value)
170    }
171}
172
173impl<DbError> From<DbError> for ContextError<DbError> {
174    fn from(value: DbError) -> Self {
175        Self::Db(value)
176    }
177}
178
179/// Represents the result of an `sstore` operation.
180#[derive(Clone, Debug, Default, PartialEq, Eq)]
181#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
182pub struct SStoreResult {
183    /// Value of the storage when it is first read
184    pub original_value: StorageValue,
185    /// Current value of the storage
186    pub present_value: StorageValue,
187    /// New value that is set
188    pub new_value: StorageValue,
189}
190
191impl SStoreResult {
192    /// Returns `true` if the new value is equal to the present value.
193    #[inline]
194    pub const fn is_new_eq_present(&self) -> bool {
195        self.new_value.const_eq(&self.present_value)
196    }
197
198    /// Returns `true` if the original value is equal to the present value.
199    #[inline]
200    pub const fn is_original_eq_present(&self) -> bool {
201        self.original_value.const_eq(&self.present_value)
202    }
203
204    /// Returns `true` if the original value is equal to the new value.
205    #[inline]
206    pub const fn is_original_eq_new(&self) -> bool {
207        self.original_value.const_eq(&self.new_value)
208    }
209
210    /// Returns `true` if the original value is zero.
211    #[inline]
212    pub const fn is_original_zero(&self) -> bool {
213        self.original_value.const_is_zero()
214    }
215
216    /// Returns `true` if the present value is zero.
217    #[inline]
218    pub const fn is_present_zero(&self) -> bool {
219        self.present_value.const_is_zero()
220    }
221
222    /// Returns `true` if the new value is zero.
223    #[inline]
224    pub const fn is_new_zero(&self) -> bool {
225        self.new_value.const_is_zero()
226    }
227}
228
229/// Result of a selfdestruct action
230///
231/// Value returned are needed to calculate the gas spent.
232#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
233#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
234pub struct SelfDestructResult {
235    /// Whether the account had a value.
236    pub had_value: bool,
237    /// Whether the target account exists.
238    pub target_exists: bool,
239    /// Whether the account was previously destroyed.
240    pub previously_destroyed: bool,
241}
242
243/// Trait for setting the transaction and block in the context.
244pub trait ContextSetters: ContextTr {
245    /// Set the transaction
246    fn set_tx(&mut self, tx: Self::Tx);
247    /// Set the block
248    fn set_block(&mut self, block: Self::Block);
249}