Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

state: Delete empty accounts after each tx #701

Merged
merged 1 commit into from
Sep 26, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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