From 2befbb17a0ebc06bf5a3949b4710efdb9a972ffb Mon Sep 17 00:00:00 2001 From: rodiazet Date: Mon, 4 Sep 2023 16:19:49 +0200 Subject: [PATCH] state: Delete empty accounts after each tx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Delete empty accounts after each transaction and after applying withdrawals and block rewards. Co-authored-by: Paweł Bylica --- test/state/state.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/test/state/state.cpp b/test/state/state.cpp index 39ff748fa1..b8563df8bc 100644 --- a/test/state/state.cpp +++ b/test/state/state.cpp @@ -135,6 +135,18 @@ std::variant validate_transaction(const Account& sende return execution_gas_limit; } +namespace +{ +/// Deletes "touched" (marked as erasable) empty accounts in the state. +void delete_empty_accounts(State& state) +{ + std::erase_if(state.get_accounts(), [](const std::pair& p) noexcept { + const auto& acc = p.second; + return acc.erasable && acc.is_empty(); + }); +} +} // namespace + void finalize(State& state, evmc_revision rev, const address& coinbase, std::optional block_reward, std::span ommers, std::span withdrawals) @@ -158,14 +170,9 @@ void finalize(State& state, evmc_revision rev, const address& coinbase, for (const auto& withdrawal : withdrawals) state.touch(withdrawal.recipient).balance += withdrawal.get_amount(); + // Delete potentially empty block reward recipients. if (rev >= EVMC_SPURIOUS_DRAGON) - { - std::erase_if( - state.get_accounts(), [](const std::pair& p) noexcept { - const auto& acc = p.second; - return acc.erasable && acc.is_empty(); - }); - } + delete_empty_accounts(state); } std::variant transition(State& state, const BlockInfo& block, @@ -241,6 +248,12 @@ std::variant transition(State& state, const // Cannot put it into constructor call because logs are std::moved from host instance. receipt.logs_bloom_filter = compute_bloom_filter(receipt.logs); + // Delete empty accounts after every transaction. This is strictly required until Byzantium + // where intermediate state root hashes are part of the transaction receipt. + // TODO: Consider limiting this only to Spurious Dragon. + if (rev >= EVMC_SPURIOUS_DRAGON) + delete_empty_accounts(state); + // Set accounts and their storage access status to cold in the end of transition process for (auto& acc : state.get_accounts()) {