rust-ethereum / evm

Pure Rust implementation of Ethereum Virtual Machine
Apache License 2.0
1.16k stars 355 forks source link

Remove touched empty accounts when empty_considered_exists is disabled. #249

Open Lohann opened 9 months ago

Lohann commented 9 months ago

Crate version: v0.41.0

While using this EVM to sync with ethereum mainnet, I've a found a sync mismatch when processing the spurious dragon hardfork at block 2675000 for this transaction: 0xad0efe76cb3983e9c2daf079af7eb6bfcd6d9b4174e66cc516378804d4e708a5

The reason is because this transaction touches the pre-compiled contract at 0x0000000000000000000000000000000000000004, which have an empty account:

An account is considered empty when it has no code and zero nonce and zero balance.

according to EIP-161 any empty account touched by the trasanction (including pre-compiled contracts) must be deleted at the end of the transaction:

d. At the end of the transaction, any account touched by the execution of that transaction which is now empty SHALL instead become non-existent (i.e. deleted).

But empty accounts should not be removed if the transaction reverts:

Addendum (2017-08-15) On 2016-11-24, a consensus bug occurred due to two implementations having different behavior in the case of state reverts.[3] The specification was amended to clarify that empty account deletions are reverted when the state is reverted.

Current Behavior

The vm doesn't execute Apply::Delete for touched empty accounts when config.empty_considered_exists is disabled.

Expected Behavior

The vm tracks touched accounts and cleanup empty account at the end of each transaction, including pre-compiled contract accounts, maybe include a new config like remove_touched_empty_accounts.