revm_context_interface/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 crate::journaled_state::StateLoad;
pub use dummy::DummyHost;
use crate::{
journaled_state::{AccountLoad, Eip7702CodeLoad},
Block, Cfg, Transaction,
};
use primitives::{Address, Bytes, Log, B256, U256};
/// 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;
/// Loads an account code.
fn load_account_delegated(&mut self, address: Address) -> Option<AccountLoad>;
/// Gets the block hash of the given block `number`.
fn block_hash(&mut self, number: u64) -> Option<B256>;
/// Gets balance of `address` and if the account is cold.
fn balance(&mut self, address: Address) -> Option<StateLoad<U256>>;
/// Gets code of `address` and if the account is cold.
fn code(&mut self, address: Address) -> Option<Eip7702CodeLoad<Bytes>>;
/// Gets code hash of `address` and if the account is cold.
fn code_hash(&mut self, address: Address) -> Option<Eip7702CodeLoad<B256>>;
/// Gets storage value of `address` at `index` and if the account is cold.
fn sload(&mut self, address: Address, index: U256) -> Option<StateLoad<U256>>;
/// Sets 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>>;
/// Gets the transient storage value of `address` at `index`.
fn tload(&mut self, address: Address, index: U256) -> U256;
/// Sets the transient storage value of `address` at `index`.
fn tstore(&mut self, address: Address, index: U256, value: U256);
/// Emits a log owned by `address` with given `LogData`.
fn log(&mut self, log: Log);
/// Marks `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, ()>>>();
// }
// }