Skip to main content

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    /// Get the configuration and journal mutably
157    #[inline]
158    fn cfg_journal_mut(&mut self) -> (&Self::Cfg, &mut Self::Journal) {
159        let (_, _, cfg, journal, _, _) = self.all_mut();
160        (cfg, journal)
161    }
162}
163
164/// Inner Context error used for Interpreter to set error without returning it from instruction
165#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
166#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
167pub enum ContextError<DbError> {
168    /// Database error.
169    Db(DbError),
170    /// Custom string error.
171    Custom(String),
172}
173
174/// Take (drain) the stored context error and map it into an external error type.
175///
176/// This is used in multiple places (handlers/frames) to avoid duplicating the
177/// `mem::replace + match ContextError` boilerplate.
178#[inline]
179pub fn take_error<E, DbError>(err: &mut Result<(), ContextError<DbError>>) -> Result<(), E>
180where
181    E: From<DbError> + FromStringError,
182{
183    match core::mem::replace(err, Ok(())) {
184        Err(ContextError::Db(e)) => Err(e.into()),
185        Err(ContextError::Custom(e)) => Err(E::from_string(e)),
186        Ok(()) => Ok(()),
187    }
188}
189
190impl<DbError> FromStringError for ContextError<DbError> {
191    fn from_string(value: String) -> Self {
192        Self::Custom(value)
193    }
194}
195
196impl<DbError> From<DbError> for ContextError<DbError> {
197    fn from(value: DbError) -> Self {
198        Self::Db(value)
199    }
200}
201
202/// Represents the result of an `sstore` operation.
203#[derive(Clone, Debug, Default, PartialEq, Eq)]
204#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
205pub struct SStoreResult {
206    /// Value of the storage when it is first read
207    pub original_value: StorageValue,
208    /// Current value of the storage
209    pub present_value: StorageValue,
210    /// New value that is set
211    pub new_value: StorageValue,
212}
213
214impl SStoreResult {
215    /// Returns `true` if the new value is equal to the present value.
216    #[inline]
217    pub const fn is_new_eq_present(&self) -> bool {
218        self.new_value.const_eq(&self.present_value)
219    }
220
221    /// Returns `true` if the new values changes the present value.
222    #[inline]
223    pub const fn new_values_changes_present(&self) -> bool {
224        !self.is_new_eq_present()
225    }
226
227    /// Returns `true` if the original value is zero and the new value is not zero.
228    #[inline]
229    pub const fn have_changed_from_zero(&self) -> bool {
230        self.is_original_zero() && !self.is_new_zero()
231    }
232
233    /// Returns `true` if the original value is equal to the present value.
234    #[inline]
235    pub const fn is_original_eq_present(&self) -> bool {
236        self.original_value.const_eq(&self.present_value)
237    }
238
239    /// Returns `true` if the original value is equal to the new value.
240    #[inline]
241    pub const fn is_original_eq_new(&self) -> bool {
242        self.original_value.const_eq(&self.new_value)
243    }
244
245    /// Returns `true` if the original value is zero.
246    #[inline]
247    pub const fn is_original_zero(&self) -> bool {
248        self.original_value.const_is_zero()
249    }
250
251    /// Returns `true` if the present value is zero.
252    #[inline]
253    pub const fn is_present_zero(&self) -> bool {
254        self.present_value.const_is_zero()
255    }
256
257    /// Returns `true` if the new value is zero.
258    #[inline]
259    pub const fn is_new_zero(&self) -> bool {
260        self.new_value.const_is_zero()
261    }
262}
263
264/// Result of a selfdestruct action
265///
266/// Value returned are needed to calculate the gas spent.
267#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
268#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
269pub struct SelfDestructResult {
270    /// Whether the account had a value.
271    pub had_value: bool,
272    /// Whether the target account exists.
273    pub target_exists: bool,
274    /// Whether the account was previously destroyed.
275    pub previously_destroyed: bool,
276}
277
278/// Trait for setting the transaction and block in the context.
279pub trait ContextSetters: ContextTr {
280    /// Set the transaction
281    fn set_tx(&mut self, tx: Self::Tx);
282    /// Set the block
283    fn set_block(&mut self, block: Self::Block);
284}