9 #include <unordered_map> 15 using bytes = std::basic_string<uint8_t>;
31 : value{_value},
dirty{_dirty}
51 std::unordered_map<bytes32, storage_value>
storage;
57 for (std::size_t i = 0; i <
sizeof(x); ++i)
58 balance.
bytes[
sizeof(balance) - 1 - i] =
static_cast<uint8_t
>(x >> (8 * i));
81 return creator == other.creator && data == other.data && topics == other.topics;
97 return selfdestructed == other.selfdestructed && beneficiary == other.beneficiary;
102 std::unordered_map<address, MockedAccount>
accounts;
121 static constexpr
auto max_recorded_account_accesses = 200;
128 static constexpr
auto max_recorded_calls = 100;
138 std::vector<bytes> m_recorded_calls_inputs;
145 if (recorded_account_accesses.empty())
146 recorded_account_accesses.reserve(max_recorded_account_accesses);
148 if (recorded_account_accesses.size() < max_recorded_account_accesses)
149 recorded_account_accesses.emplace_back(addr);
155 record_account_access(addr);
156 return accounts.count(addr) != 0;
162 record_account_access(addr);
164 const auto account_iter = accounts.find(addr);
165 if (account_iter == accounts.end())
168 const auto storage_iter = account_iter->second.storage.find(key);
169 if (storage_iter != account_iter->second.storage.end())
170 return storage_iter->second.value;
179 record_account_access(addr);
180 const auto it = accounts.find(addr);
181 if (it == accounts.end())
184 auto& old = it->second.storage[key];
189 if (old.value ==
value)
213 record_account_access(addr);
214 const auto it = accounts.find(addr);
215 if (it == accounts.end())
218 return it->second.balance;
224 record_account_access(addr);
225 const auto it = accounts.find(addr);
226 if (it == accounts.end())
228 return it->second.code.size();
234 record_account_access(addr);
235 const auto it = accounts.find(addr);
236 if (it == accounts.end())
238 return it->second.codehash;
244 uint8_t* buffer_data,
245 size_t buffer_size)
const noexcept
override 247 record_account_access(addr);
248 const auto it = accounts.find(addr);
249 if (it == accounts.end())
252 const auto& code = it->second.code;
254 if (code_offset >= code.size())
257 const auto n = std::min(buffer_size, code.size() - code_offset);
260 std::copy_n(&code[code_offset], n, buffer_data);
267 record_account_access(addr);
268 recorded_selfdestructs.push_back({addr, beneficiary});
274 record_account_access(msg.destination);
276 if (recorded_calls.empty())
278 recorded_calls.reserve(max_recorded_calls);
279 m_recorded_calls_inputs.reserve(max_recorded_calls);
282 if (recorded_calls.size() < max_recorded_calls)
284 recorded_calls.emplace_back(msg);
285 auto& call_msg = recorded_calls.back();
286 if (call_msg.input_size > 0)
288 m_recorded_calls_inputs.emplace_back(call_msg.input_data, call_msg.input_size);
289 const auto& input_copy = m_recorded_calls_inputs.back();
290 call_msg.input_data = input_copy.data();
293 return result{call_result};
302 recorded_blockhashes.emplace_back(block_number);
311 size_t topics_count) noexcept
override 313 recorded_logs.push_back({addr, {data, data_size}, {topics, topics + topics_count}});
bool dirty
True means this value has been modified already by the current transaction.
bytes32 codehash
The code hash. Can be a value not related to the actual code.
std::basic_string< uint8_t > bytes
The string of bytes.
A storage item has been deleted: X -> 0.
bytes32 get_block_hash(int64_t block_number) const noexcept override
Get the block header hash (EVMC host method).
address beneficiary
The address of the beneficiary account.
std::unordered_map< address, MockedAccount > accounts
The set of all accounts in the Host, organized by their addresses.
Mocked EVMC Host implementation.
std::vector< log_record > recorded_logs
The record of all LOGs passed to the emit_log() method.
evmc_storage_status
The effect of an attempt to modify a contract storage item.
std::vector< bytes32 > topics
The log topics.
The EVM code execution result.
uint256be balance
The account balance.
The fixed size array of 32 bytes for storing 256-bit EVM values.
bool account_exists(const address &addr) const noexcept override
Returns true if an account exists (EVMC Host method).
bool operator==(const log_record &other) const noexcept
Equal operator.
bytes data
The data attached to the log.
void emit_log(const address &addr, const uint8_t *data, size_t data_size, const bytes32 topics[], size_t topics_count) noexcept override
Emit LOG (EVMC host method).
storage_value(const bytes32 &_value, bool _dirty=false) noexcept
Constructor.
evmc_tx_context get_tx_context() const noexcept override
Get transaction context (EVMC host method).
std::vector< selfdestuct_record > recorded_selfdestructs
The record of all SELFDESTRUCTs from the selfdestruct() method.
bytes32 get_storage(const address &addr, const bytes32 &key) const noexcept override
Get the account's storage value at the given key (EVMC Host method).
bytes32 get_code_hash(const address &addr) const noexcept override
Get the account's code hash (EVMC host method).
The value of a storage item has been modified: X -> Y.
std::vector< evmc_message > recorded_calls
The record of all call messages requested in the call() method.
uint8_t bytes[32]
The 32 bytes.
void record_account_access(const address &addr) const
Record an account access.
bytes code
The account code.
uint256be get_balance(const address &addr) const noexcept override
Get the account's balance (EVMC Host method).
std::vector< int64_t > recorded_blockhashes
The record of all block numbers for which get_block_hash() was called.
result call(const evmc_message &msg) noexcept override
Call/create other contract (EVMC host method).
The message describing an EVM call, including a zero-depth calls from a transaction origin...
address selfdestructed
The address of the account which has self-destructed.
bytes32 value
The storage value.
void selfdestruct(const address &addr, const address &beneficiary) noexcept override
Selfdestruct the account (EVMC host method).
storage_value() noexcept=default
Default constructor.
address creator
The address of the account which created the log.
std::unordered_map< bytes32, storage_value > storage
The account storage map.
A storage item has been modified after being modified before: X -> Y -> Z.
bool operator==(const selfdestuct_record &other) const noexcept
Equal operator.
The EVM code execution result.
The big-endian 160-bit hash suitable for keeping an Ethereum address.
size_t copy_code(const address &addr, size_t code_offset, uint8_t *buffer_data, size_t buffer_size) const noexcept override
Copy the account's code to the given buffer (EVMC host method).
evmc_storage_status set_storage(const address &addr, const bytes32 &key, const bytes32 &value) noexcept override
Set the account's storage value (EVMC Host method).
The value of a storage item has been left unchanged: 0 -> 0 and X -> X.
Abstract class to be used by Host implementations.
EVMC C++ API - wrappers and bindings for C++.
void set_balance(uint64_t x) noexcept
Helper method for setting balance by numeric type.
size_t get_code_size(const address &addr) const noexcept override
Get the account's code size (EVMC host method).
A new storage item has been added: 0 -> X.
Extended value (by dirty flag) for account storage.
EVMC C++ API - wrappers and bindings for C++.
The transaction and block data for execution.
std::vector< address > recorded_account_accesses
The record of all account accesses.