revm_state/account_info.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 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
use bytecode::Bytecode;
use core::hash::{Hash, Hasher};
use primitives::{B256, KECCAK_EMPTY, U256};
/// AccountInfo account information
#[derive(Clone, Debug, Eq, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AccountInfo {
/// Account balance
pub balance: U256,
/// Account nonce
pub nonce: u64,
/// code hash
pub code_hash: B256,
/// [`Bytecode`] data associated with this account
///
/// If [None], `code_hash` will be used to fetch it if code needs to be loaded from
/// inside `revm`.
pub code: Option<Bytecode>,
}
impl Default for AccountInfo {
fn default() -> Self {
Self {
balance: U256::ZERO,
code_hash: KECCAK_EMPTY,
code: Some(Bytecode::default()),
nonce: 0,
}
}
}
impl PartialEq for AccountInfo {
fn eq(&self, other: &Self) -> bool {
self.balance == other.balance
&& self.nonce == other.nonce
&& self.code_hash == other.code_hash
}
}
impl Hash for AccountInfo {
fn hash<H: Hasher>(&self, state: &mut H) {
self.balance.hash(state);
self.nonce.hash(state);
self.code_hash.hash(state);
}
}
impl AccountInfo {
/// Creates a new [`AccountInfo`] with the given fields.
#[inline]
pub fn new(balance: U256, nonce: u64, code_hash: B256, code: Bytecode) -> Self {
Self {
balance,
nonce,
code: Some(code),
code_hash,
}
}
/// Returns a copy of this account with the [`Bytecode`] removed.
///
/// This is useful when creating journals or snapshots of the state, where it is
/// desirable to store the code blobs elsewhere.
///
/// ## Note
///
/// This is distinct from [`without_code`][Self::without_code] in that it returns
/// a new [`AccountInfo`] instance with the code removed.
///
/// [`without_code`][Self::without_code] will modify and return the same instance.
#[inline]
pub fn copy_without_code(&self) -> Self {
Self {
balance: self.balance,
nonce: self.nonce,
code_hash: self.code_hash,
code: None,
}
}
/// Strips the [`Bytecode`] from this account and drop it.
///
/// This is useful when creating journals or snapshots of the state, where it is
/// desirable to store the code blobs elsewhere.
///
/// ## Note
///
/// This is distinct from [`copy_without_code`][Self::copy_without_code] in that it
/// modifies the account in place.
///
/// [`copy_without_code`][Self::copy_without_code]
/// will copy the non-code fields and return a new [`AccountInfo`] instance.
pub fn without_code(mut self) -> Self {
self.take_bytecode();
self
}
/// Returns if an account is empty.
///
/// An account is empty if the following conditions are met.
/// - code hash is zero or set to the Keccak256 hash of the empty string `""`
/// - balance is zero
/// - nonce is zero
#[inline]
pub fn is_empty(&self) -> bool {
let code_empty = self.is_empty_code_hash() || self.code_hash.is_zero();
code_empty && self.balance.is_zero() && self.nonce == 0
}
/// Returns `true` if the account is not empty.
#[inline]
pub fn exists(&self) -> bool {
!self.is_empty()
}
/// Returns `true` if account has no nonce and code.
#[inline]
pub fn has_no_code_and_nonce(&self) -> bool {
self.is_empty_code_hash() && self.nonce == 0
}
/// Returns bytecode hash associated with this account.
///
/// If account does not have code, it returns `KECCAK_EMPTY` hash.
#[inline]
pub fn code_hash(&self) -> B256 {
self.code_hash
}
/// Returns true if the code hash is the Keccak256 hash of the empty string `""`.
#[inline]
pub fn is_empty_code_hash(&self) -> bool {
self.code_hash == KECCAK_EMPTY
}
/// Takes bytecode from account.
///
/// Code will be set to [None].
#[inline]
pub fn take_bytecode(&mut self) -> Option<Bytecode> {
self.code.take()
}
/// Initializes an [`AccountInfo`] with the given balance, setting all other fields to their
/// default values.
#[inline]
pub fn from_balance(balance: U256) -> Self {
AccountInfo {
balance,
..Default::default()
}
}
/// Initializes an [`AccountInfo`] with the given bytecode, setting its balance to zero, its
/// nonce to `1`, and calculating the code hash from the given bytecode.
#[inline]
pub fn from_bytecode(bytecode: Bytecode) -> Self {
let hash = bytecode.hash_slow();
AccountInfo {
balance: U256::ZERO,
nonce: 1,
code: Some(bytecode),
code_hash: hash,
}
}
}