Skip to content

Commit

Permalink
state: Delete empty accounts after each tx
Browse files Browse the repository at this point in the history
Delete empty accounts after each transaction
and after applying withdrawals and block rewards.

Co-authored-by: Paweł Bylica <pawel@ethereum.org>
  • Loading branch information
rodiazet and chfast committed Sep 26, 2023
1 parent 6ce4e70 commit 2befbb1
Showing 1 changed file with 20 additions and 7 deletions.
27 changes: 20 additions & 7 deletions test/state/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,18 @@ std::variant<int64_t, std::error_code> 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<const address, Account>& 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<uint64_t> block_reward, std::span<Ommer> ommers,
std::span<Withdrawal> withdrawals)
Expand All @@ -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<const address, Account>& p) noexcept {
const auto& acc = p.second;
return acc.erasable && acc.is_empty();
});
}
delete_empty_accounts(state);
}

std::variant<TransactionReceipt, std::error_code> transition(State& state, const BlockInfo& block,
Expand Down Expand Up @@ -241,6 +248,12 @@ std::variant<TransactionReceipt, std::error_code> 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())
{
Expand Down

0 comments on commit 2befbb1

Please sign in to comment.