revm_interpreter/host.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
mod dummy;
pub use dummy::DummyHost;
use context_interface::{
journaled_state::{AccountLoad, Eip7702CodeLoad},
Block, Cfg, Transaction,
};
use primitives::{Address, Bytes, Log, B256, U256};
pub use context_interface::journaled_state::StateLoad;
/// EVM context host.
/// TODO move to context-interface
pub trait Host {
/// Chain specification.
type BLOCK: Block;
type TX: Transaction;
type CFG: Cfg;
/// Returns a reference to the environment.
fn tx(&self) -> &Self::TX;
/// Returns a mutable reference to the environment.
fn block(&self) -> &Self::BLOCK;
/// TODO make it generic in future
fn cfg(&self) -> &Self::CFG;
/// Load an account code.
fn load_account_delegated(&mut self, address: Address) -> Option<AccountLoad>;
/// Get the block hash of the given block `number`.
fn block_hash(&mut self, number: u64) -> Option<B256>;
/// Get balance of `address` and if the account is cold.
fn balance(&mut self, address: Address) -> Option<StateLoad<U256>>;
/// Get code of `address` and if the account is cold.
fn code(&mut self, address: Address) -> Option<Eip7702CodeLoad<Bytes>>;
/// Get code hash of `address` and if the account is cold.
fn code_hash(&mut self, address: Address) -> Option<Eip7702CodeLoad<B256>>;
/// Get storage value of `address` at `index` and if the account is cold.
fn sload(&mut self, address: Address, index: U256) -> Option<StateLoad<U256>>;
/// Set storage value of account address at index.
///
/// Returns [`StateLoad`] with [`SStoreResult`] that contains original/new/old storage value.
fn sstore(
&mut self,
address: Address,
index: U256,
value: U256,
) -> Option<StateLoad<SStoreResult>>;
/// Get the transient storage value of `address` at `index`.
fn tload(&mut self, address: Address, index: U256) -> U256;
/// Set the transient storage value of `address` at `index`.
fn tstore(&mut self, address: Address, index: U256, value: U256);
/// Emit a log owned by `address` with given `LogData`.
fn log(&mut self, log: Log);
/// Mark `address` to be deleted, with funds transferred to `target`.
fn selfdestruct(
&mut self,
address: Address,
target: Address,
) -> Option<StateLoad<SelfDestructResult>>;
}
/// Represents the result of an `sstore` operation.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SStoreResult {
/// Value of the storage when it is first read
pub original_value: U256,
/// Current value of the storage
pub present_value: U256,
/// New value that is set
pub new_value: U256,
}
impl SStoreResult {
/// Returns `true` if the new value is equal to the present value.
#[inline]
pub fn is_new_eq_present(&self) -> bool {
self.new_value == self.present_value
}
/// Returns `true` if the original value is equal to the present value.
#[inline]
pub fn is_original_eq_present(&self) -> bool {
self.original_value == self.present_value
}
/// Returns `true` if the original value is equal to the new value.
#[inline]
pub fn is_original_eq_new(&self) -> bool {
self.original_value == self.new_value
}
/// Returns `true` if the original value is zero.
#[inline]
pub fn is_original_zero(&self) -> bool {
self.original_value.is_zero()
}
/// Returns `true` if the present value is zero.
#[inline]
pub fn is_present_zero(&self) -> bool {
self.present_value.is_zero()
}
/// Returns `true` if the new value is zero.
#[inline]
pub fn is_new_zero(&self) -> bool {
self.new_value.is_zero()
}
}
/// Result of a selfdestruct action.
///
/// Value returned are needed to calculate the gas spent.
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SelfDestructResult {
pub had_value: bool,
pub target_exists: bool,
pub previously_destroyed: bool,
}
// TODO TEST
// #[cfg(test)]
// mod tests {
// use database_interface::EmptyDB;
// use context_interface::EthereumWiring;
// use super::*;
// fn assert_host<H: Host + ?Sized>() {}
// #[test]
// fn object_safety() {
// assert_host::<DummyHost<EthereumWiring<EmptyDB, ()>>>();
// assert_host::<dyn Host<EvmWiringT = EthereumWiring<EmptyDB, ()>>>();
// }
// }