TLA Line data Source code
1 : // evmone: Fast Ethereum Virtual Machine implementation
2 : // Copyright 2022 The evmone Authors.
3 : // SPDX-License-Identifier: Apache-2.0
4 :
5 : #include "host.hpp"
6 : #include "precompiles.hpp"
7 : #include "rlp.hpp"
8 : #include <evmone/eof.hpp>
9 :
10 : namespace evmone::state
11 : {
12 UBC 0 : bool Host::account_exists(const address& addr) const noexcept
13 : {
14 0 : const auto* const acc = m_state.find(addr);
15 0 : return acc != nullptr && (m_rev < EVMC_SPURIOUS_DRAGON || !acc->is_empty());
16 : }
17 :
18 GBC 2 : bytes32 Host::get_storage(const address& addr, const bytes32& key) const noexcept
19 : {
20 2 : const auto& acc = m_state.get(addr);
21 2 : if (const auto it = acc.storage.find(key); it != acc.storage.end())
22 2 : return it->second.current;
23 UBC 0 : return {};
24 : }
25 :
26 CBC 286 : evmc_storage_status Host::set_storage(
27 : const address& addr, const bytes32& key, const bytes32& value) noexcept
28 : {
29 : // Follow EVMC documentation https://evmc.ethereum.org/storagestatus.html#autotoc_md3
30 : // and EIP-2200 specification https://eips.ethereum.org/EIPS/eip-2200.
31 :
32 286 : auto& storage_slot = m_state.get(addr).storage[key];
33 286 : const auto& [current, original, _] = storage_slot;
34 :
35 286 : const auto dirty = original != current;
36 286 : const auto restored = original == value;
37 286 : const auto current_is_zero = is_zero(current);
38 286 : const auto value_is_zero = is_zero(value);
39 :
40 286 : auto status = EVMC_STORAGE_ASSIGNED; // All other cases.
41 286 : if (!dirty && !restored)
42 : {
43 263 : if (current_is_zero)
44 4 : status = EVMC_STORAGE_ADDED; // 0 → 0 → Z
45 259 : else if (value_is_zero)
46 60 : status = EVMC_STORAGE_DELETED; // X → X → 0
47 : else
48 199 : status = EVMC_STORAGE_MODIFIED; // X → X → Z
49 : }
50 GBC 23 : else if (dirty && !restored)
51 : {
52 3 : if (current_is_zero && !value_is_zero)
53 UBC 0 : status = EVMC_STORAGE_DELETED_ADDED; // X → 0 → Z
54 GBC 3 : else if (!current_is_zero && value_is_zero)
55 1 : status = EVMC_STORAGE_MODIFIED_DELETED; // X → Y → 0
56 : }
57 20 : else if (dirty && restored)
58 : {
59 UBC 0 : if (current_is_zero)
60 0 : status = EVMC_STORAGE_DELETED_RESTORED; // X → 0 → X
61 0 : else if (value_is_zero)
62 0 : status = EVMC_STORAGE_ADDED_DELETED; // 0 → Y → 0
63 : else
64 0 : status = EVMC_STORAGE_MODIFIED_RESTORED; // X → Y → X
65 : }
66 :
67 : // In Berlin this is handled in access_storage().
68 CBC 286 : if (m_rev < EVMC_BERLIN)
69 UBC 0 : m_state.journal_storage_change(addr, key, storage_slot);
70 CBC 286 : storage_slot.current = value; // Update current value.
71 286 : return status;
72 : }
73 :
74 UBC 0 : uint256be Host::get_balance(const address& addr) const noexcept
75 : {
76 0 : const auto* const acc = m_state.find(addr);
77 0 : return (acc != nullptr) ? intx::be::store<uint256be>(acc->balance) : uint256be{};
78 : }
79 :
80 0 : size_t Host::get_code_size(const address& addr) const noexcept
81 : {
82 0 : const auto* const acc = m_state.find(addr);
83 0 : return (acc != nullptr) ? acc->code.size() : 0;
84 : }
85 :
86 0 : bytes32 Host::get_code_hash(const address& addr) const noexcept
87 : {
88 : // TODO: Cache code hash. It will be needed also to compute the MPT hash.
89 0 : const auto* const acc = m_state.find(addr);
90 0 : return (acc != nullptr && !acc->is_empty()) ? keccak256(acc->code) : bytes32{};
91 : }
92 :
93 0 : size_t Host::copy_code(const address& addr, size_t code_offset, uint8_t* buffer_data,
94 : size_t buffer_size) const noexcept
95 : {
96 0 : const auto* const acc = m_state.find(addr);
97 0 : const auto code = (acc != nullptr) ? bytes_view{acc->code} : bytes_view{};
98 0 : const auto code_slice = code.substr(std::min(code_offset, code.size()));
99 0 : const auto num_bytes = std::min(buffer_size, code_slice.size());
100 0 : std::copy_n(code_slice.begin(), num_bytes, buffer_data);
101 0 : return num_bytes;
102 : }
103 :
104 0 : bool Host::selfdestruct(const address& addr, const address& beneficiary) noexcept
105 : {
106 0 : if (m_state.find(beneficiary) == nullptr)
107 0 : m_state.journal_create(beneficiary, false);
108 0 : auto& acc = m_state.get(addr);
109 0 : const auto balance = acc.balance;
110 0 : auto& beneficiary_acc = m_state.touch(beneficiary);
111 :
112 0 : m_state.journal_balance_change(beneficiary, beneficiary_acc.balance);
113 0 : m_state.journal_balance_change(addr, balance);
114 :
115 0 : if (m_rev >= EVMC_CANCUN && !acc.just_created)
116 : {
117 : // EIP-6780:
118 : // "SELFDESTRUCT is executed in a transaction that is not the same
119 : // as the contract invoking SELFDESTRUCT was created"
120 0 : acc.balance = 0;
121 0 : beneficiary_acc.balance += balance; // Keep balance if acc is the beneficiary.
122 :
123 : // Return "selfdestruct not registered".
124 : // In practice this affects only refunds before Cancun.
125 0 : return false;
126 : }
127 :
128 : // Transfer may happen multiple times per single account as account's balance
129 : // can be increased with a call following previous selfdestruct.
130 0 : beneficiary_acc.balance += balance;
131 0 : acc.balance = 0; // Zero balance if acc is the beneficiary.
132 :
133 : // Mark the destruction if not done already.
134 0 : if (!acc.destructed)
135 : {
136 0 : m_state.journal_destruct(addr);
137 0 : acc.destructed = true;
138 0 : return true;
139 : }
140 0 : return false;
141 : }
142 :
143 0 : address compute_create_address(const address& sender, uint64_t sender_nonce) noexcept
144 : {
145 : // TODO: Compute CREATE address without using RLP library.
146 0 : const auto rlp_list = rlp::encode_tuple(sender, sender_nonce);
147 0 : const auto base_hash = keccak256(rlp_list);
148 0 : address addr;
149 0 : std::copy_n(&base_hash.bytes[sizeof(base_hash) - sizeof(addr)], sizeof(addr), addr.bytes);
150 0 : return addr;
151 0 : }
152 :
153 0 : address compute_create2_address(
154 : const address& sender, const bytes32& salt, bytes_view init_code) noexcept
155 : {
156 0 : const auto init_code_hash = keccak256(init_code);
157 : uint8_t buffer[1 + sizeof(sender) + sizeof(salt) + sizeof(init_code_hash)];
158 : static_assert(std::size(buffer) == 85);
159 0 : auto it = std::begin(buffer);
160 0 : *it++ = 0xff;
161 0 : it = std::copy_n(sender.bytes, sizeof(sender), it);
162 0 : it = std::copy_n(salt.bytes, sizeof(salt), it);
163 0 : std::copy_n(init_code_hash.bytes, sizeof(init_code_hash), it);
164 0 : const auto base_hash = keccak256({buffer, std::size(buffer)});
165 0 : address addr;
166 0 : std::copy_n(&base_hash.bytes[sizeof(base_hash) - sizeof(addr)], sizeof(addr), addr.bytes);
167 0 : return addr;
168 : }
169 :
170 CBC 105 : std::optional<evmc_message> Host::prepare_message(evmc_message msg)
171 : {
172 105 : if (msg.depth == 0 || msg.kind == EVMC_CREATE || msg.kind == EVMC_CREATE2)
173 : {
174 53 : auto& sender_acc = m_state.get(msg.sender);
175 53 : const auto sender_nonce = sender_acc.nonce;
176 :
177 : // EIP-2681 (already checked for depth 0 during transaction validation).
178 53 : if (sender_nonce == Account::NonceMax)
179 UBC 0 : return {}; // Light early exception.
180 :
181 CBC 53 : if (msg.depth != 0)
182 UBC 0 : m_state.journal_bump_nonce(msg.sender);
183 CBC 53 : ++sender_acc.nonce; // Bump sender nonce.
184 :
185 53 : if (msg.kind == EVMC_CREATE || msg.kind == EVMC_CREATE2)
186 : {
187 : // Compute and set the address of the account being created.
188 UBC 0 : assert(msg.recipient == address{});
189 0 : assert(msg.code_address == address{});
190 0 : msg.recipient = (msg.kind == EVMC_CREATE) ?
191 0 : compute_create_address(msg.sender, sender_nonce) :
192 0 : compute_create2_address(
193 : msg.sender, msg.create2_salt, {msg.input_data, msg.input_size});
194 :
195 : // By EIP-2929, the access to new created address is never reverted.
196 0 : access_account(msg.recipient);
197 : }
198 : }
199 :
200 CBC 105 : return msg;
201 : }
202 :
203 UBC 0 : evmc::Result Host::create(const evmc_message& msg) noexcept
204 : {
205 0 : assert(msg.kind == EVMC_CREATE || msg.kind == EVMC_CREATE2);
206 :
207 : // Check collision as defined in pseudo-EIP https://github.com/ethereum/EIPs/issues/684.
208 : // All combinations of conditions (nonce, code, storage) are tested.
209 : // TODO(EVMC): Add specific error codes for creation failures.
210 0 : if (const auto collision_acc = m_state.find(msg.recipient);
211 0 : collision_acc != nullptr && (collision_acc->nonce != 0 || !collision_acc->code.empty()))
212 0 : return evmc::Result{EVMC_FAILURE};
213 :
214 : // TODO: msg.recipient lookup is done 3x here.
215 0 : const bool exists = m_state.find(msg.recipient) != nullptr;
216 0 : auto& new_acc = m_state.get_or_insert(msg.recipient);
217 0 : m_state.journal_create(msg.recipient, exists);
218 0 : assert(new_acc.nonce == 0);
219 0 : if (m_rev >= EVMC_SPURIOUS_DRAGON)
220 0 : new_acc.nonce = 1; // No need to journal: create revert will 0 the nonce.
221 :
222 0 : new_acc.just_created = true;
223 :
224 : // Clear the new account storage, but keep the access status (from tx access list).
225 : // This is only needed for tests and cannot happen in real networks.
226 0 : for (auto& [k, v] : new_acc.storage) [[unlikely]]
227 : {
228 0 : m_state.journal_storage_change(msg.recipient, k, v);
229 0 : v = StorageValue{.access_status = v.access_status};
230 : }
231 :
232 0 : auto& sender_acc = m_state.get(msg.sender); // TODO: Duplicated account lookup.
233 0 : const auto value = intx::be::load<intx::uint256>(msg.value);
234 0 : assert(sender_acc.balance >= value && "EVM must guarantee balance");
235 0 : m_state.journal_balance_change(msg.sender, sender_acc.balance);
236 0 : m_state.journal_balance_change(msg.recipient, new_acc.balance);
237 0 : sender_acc.balance -= value;
238 0 : new_acc.balance += value; // The new account may be prefunded.
239 :
240 0 : auto create_msg = msg;
241 0 : const bytes_view initcode{msg.input_data, msg.input_size};
242 0 : create_msg.input_data = nullptr;
243 0 : create_msg.input_size = 0;
244 :
245 0 : if (m_rev >= EVMC_PRAGUE && (is_eof_container(initcode) || is_eof_container(sender_acc.code)))
246 : {
247 0 : if (validate_eof(m_rev, initcode) != EOFValidationError::success)
248 0 : return evmc::Result{EVMC_CONTRACT_VALIDATION_FAILURE};
249 : }
250 :
251 0 : auto result = m_vm.execute(*this, m_rev, create_msg, msg.input_data, msg.input_size);
252 0 : if (result.status_code != EVMC_SUCCESS)
253 : {
254 0 : result.create_address = msg.recipient;
255 0 : return result;
256 : }
257 :
258 0 : auto gas_left = result.gas_left;
259 0 : assert(gas_left >= 0);
260 :
261 0 : const bytes_view code{result.output_data, result.output_size};
262 0 : if (m_rev >= EVMC_SPURIOUS_DRAGON && code.size() > max_code_size)
263 0 : return evmc::Result{EVMC_FAILURE};
264 :
265 : // Code deployment cost.
266 0 : const auto cost = std::ssize(code) * 200;
267 0 : gas_left -= cost;
268 0 : if (gas_left < 0)
269 : {
270 0 : return (m_rev == EVMC_FRONTIER) ?
271 0 : evmc::Result{EVMC_SUCCESS, result.gas_left, result.gas_refund, msg.recipient} :
272 0 : evmc::Result{EVMC_FAILURE};
273 : }
274 :
275 0 : if (m_rev >= EVMC_PRAGUE && (is_eof_container(initcode) || is_eof_container(code)))
276 : {
277 0 : if (validate_eof(m_rev, code) != EOFValidationError::success)
278 0 : return evmc::Result{EVMC_CONTRACT_VALIDATION_FAILURE};
279 : }
280 0 : else if (m_rev >= EVMC_LONDON && !code.empty() && code[0] == 0xEF) // Reject EF code.
281 0 : return evmc::Result{EVMC_CONTRACT_VALIDATION_FAILURE};
282 :
283 0 : new_acc.code = code;
284 :
285 0 : return evmc::Result{result.status_code, gas_left, result.gas_refund, msg.recipient};
286 0 : }
287 :
288 CBC 105 : evmc::Result Host::execute_message(const evmc_message& msg) noexcept
289 : {
290 105 : if (msg.kind == EVMC_CREATE || msg.kind == EVMC_CREATE2)
291 UBC 0 : return create(msg);
292 :
293 CBC 105 : if (msg.kind == EVMC_CALL)
294 : {
295 79 : const auto exists = m_state.find(msg.recipient) != nullptr;
296 79 : if (!exists)
297 UBC 0 : m_state.journal_create(msg.recipient, exists);
298 : }
299 :
300 CBC 105 : assert(msg.kind != EVMC_CALL || evmc::address{msg.recipient} == msg.code_address);
301 : auto* const dst_acc =
302 105 : (msg.kind == EVMC_CALL) ? &m_state.touch(msg.recipient) : m_state.find(msg.code_address);
303 :
304 105 : if (msg.kind == EVMC_CALL && !evmc::is_zero(msg.value))
305 : {
306 : // Transfer value: sender → recipient.
307 : // The sender's balance is already checked therefore the sender account must exist.
308 UBC 0 : const auto value = intx::be::load<intx::uint256>(msg.value);
309 0 : assert(m_state.get(msg.sender).balance >= value);
310 0 : m_state.journal_balance_change(msg.sender, m_state.get(msg.sender).balance);
311 0 : m_state.journal_balance_change(msg.recipient, dst_acc->balance);
312 0 : m_state.get(msg.sender).balance -= value;
313 0 : dst_acc->balance += value;
314 : }
315 :
316 CBC 105 : if (is_precompile(m_rev, msg.code_address))
317 UBC 0 : return call_precompile(m_rev, msg);
318 :
319 CBC 105 : const auto code = dst_acc != nullptr ? bytes_view{dst_acc->code} : bytes_view{};
320 105 : return m_vm.execute(*this, m_rev, msg, code.data(), code.size());
321 : }
322 :
323 105 : evmc::Result Host::call(const evmc_message& orig_msg) noexcept
324 : {
325 105 : const auto msg = prepare_message(orig_msg);
326 105 : if (!msg.has_value())
327 UBC 0 : return evmc::Result{EVMC_FAILURE, orig_msg.gas}; // Light exception.
328 :
329 CBC 105 : const auto logs_checkpoint = m_logs.size();
330 105 : const auto state_checkpoint = m_state.checkpoint();
331 :
332 105 : auto result = execute_message(*msg);
333 :
334 105 : if (result.status_code != EVMC_SUCCESS)
335 : {
336 : static constexpr auto addr_03 = 0x03_address;
337 34 : auto* const acc_03 = m_state.find(addr_03);
338 34 : const auto is_03_touched = acc_03 != nullptr && acc_03->erase_if_empty;
339 :
340 : // Revert.
341 34 : m_state.rollback(state_checkpoint);
342 34 : m_logs.resize(logs_checkpoint);
343 :
344 : // The 0x03 quirk: the touch on this address is never reverted.
345 34 : if (is_03_touched && m_rev >= EVMC_SPURIOUS_DRAGON)
346 UBC 0 : m_state.touch(addr_03);
347 : }
348 CBC 105 : return result;
349 105 : }
350 :
351 UBC 0 : evmc_tx_context Host::get_tx_context() const noexcept
352 : {
353 : // TODO: The effective gas price is already computed in transaction validation.
354 : // TODO: The effective gas price calculation is broken for system calls (gas price 0).
355 0 : assert(m_tx.max_gas_price >= m_block.base_fee || m_tx.max_gas_price == 0);
356 : const auto priority_gas_price =
357 0 : std::min(m_tx.max_priority_gas_price, m_tx.max_gas_price - m_block.base_fee);
358 0 : const auto effective_gas_price = m_block.base_fee + priority_gas_price;
359 :
360 : return evmc_tx_context{
361 0 : intx::be::store<uint256be>(effective_gas_price), // By EIP-1559.
362 0 : m_tx.sender,
363 0 : m_block.coinbase,
364 0 : m_block.number,
365 0 : m_block.timestamp,
366 0 : m_block.gas_limit,
367 0 : m_block.prev_randao,
368 0 : 0x01_bytes32, // Chain ID is expected to be 1.
369 0 : uint256be{m_block.base_fee},
370 0 : intx::be::store<uint256be>(m_block.blob_base_fee),
371 0 : m_tx.blob_hashes.data(),
372 0 : m_tx.blob_hashes.size(),
373 0 : };
374 : }
375 :
376 0 : bytes32 Host::get_block_hash(int64_t block_number) const noexcept
377 : {
378 0 : if (const auto& it = m_block.known_block_hashes.find(block_number);
379 0 : it != m_block.known_block_hashes.end())
380 0 : return it->second;
381 :
382 : // Convention for testing: if the block hash in unknown return the predefined "fake" value.
383 : // https://github.com/ethereum/go-ethereum/blob/v1.12.2/tests/state_test_util.go#L432
384 0 : const auto s = std::to_string(block_number);
385 0 : return keccak256({reinterpret_cast<const uint8_t*>(s.data()), s.size()});
386 0 : }
387 :
388 0 : void Host::emit_log(const address& addr, const uint8_t* data, size_t data_size,
389 : const bytes32 topics[], size_t topics_count) noexcept
390 : {
391 0 : m_logs.push_back({addr, {data, data_size}, {topics, topics + topics_count}});
392 0 : }
393 :
394 CBC 158 : evmc_access_status Host::access_account(const address& addr) noexcept
395 : {
396 158 : if (m_rev < EVMC_BERLIN)
397 UBC 0 : return EVMC_ACCESS_COLD; // Ignore before Berlin.
398 :
399 CBC 158 : auto& acc = m_state.get_or_insert(addr, {.erase_if_empty = true});
400 :
401 158 : if (acc.access_status == EVMC_ACCESS_WARM || is_precompile(m_rev, addr))
402 24 : return EVMC_ACCESS_WARM;
403 :
404 134 : m_state.journal_access_account(addr);
405 134 : acc.access_status = EVMC_ACCESS_WARM;
406 134 : return EVMC_ACCESS_COLD;
407 : }
408 :
409 288 : evmc_access_status Host::access_storage(const address& addr, const bytes32& key) noexcept
410 : {
411 288 : auto& storage_slot = m_state.get(addr).storage[key];
412 288 : m_state.journal_storage_change(addr, key, storage_slot);
413 288 : return std::exchange(storage_slot.access_status, EVMC_ACCESS_WARM);
414 : }
415 :
416 :
417 178 : evmc::bytes32 Host::get_transient_storage(const address& addr, const bytes32& key) const noexcept
418 : {
419 178 : const auto& acc = m_state.get(addr);
420 178 : const auto it = acc.transient_storage.find(key);
421 356 : return it != acc.transient_storage.end() ? it->second : bytes32{};
422 : }
423 :
424 153 : void Host::set_transient_storage(
425 : const address& addr, const bytes32& key, const bytes32& value) noexcept
426 : {
427 153 : auto& slot = m_state.get(addr).transient_storage[key];
428 153 : m_state.journal_transient_storage_change(addr, key, slot);
429 153 : slot = value;
430 153 : }
431 : } // namespace evmone::state
|