Skip to content

Commit 9db2937

Browse files
gurukamathSamWilsn
authored andcommitted
remove empty account handling code
1 parent 8707c28 commit 9db2937

File tree

25 files changed

+51
-340
lines changed

25 files changed

+51
-340
lines changed

src/ethereum/cancun/fork.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
TransientStorage,
3636
account_exists_and_is_empty,
3737
destroy_account,
38-
destroy_touched_empty_accounts,
3938
get_account,
4039
increment_nonce,
4140
modify_state,
@@ -538,15 +537,6 @@ def process_system_transaction(
538537

539538
system_tx_output = process_message_call(system_tx_message)
540539

541-
# TODO: Empty accounts in post-merge forks are impossible
542-
# see Ethereum Improvement Proposal 7523.
543-
# This line is only included to support invalid tests in the test suite
544-
# and will have to be removed in the future.
545-
# See https://github.com/ethereum/execution-specs/issues/955
546-
destroy_touched_empty_accounts(
547-
block_env.state, system_tx_output.touched_accounts
548-
)
549-
550540
return system_tx_output
551541

552542

@@ -722,8 +712,6 @@ def process_transaction(
722712
for address in tx_output.accounts_to_delete:
723713
destroy_account(block_env.state, address)
724714

725-
destroy_touched_empty_accounts(block_env.state, tx_output.touched_accounts)
726-
727715
block_output.block_gas_used += tx_gas_used
728716
block_output.blob_gas_used += tx_blob_gas_used
729717

src/ethereum/cancun/state.py

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,8 @@ def modify_state(
510510
Modify an `Account` in the `State`.
511511
"""
512512
set_account(state, address, modify(get_account(state, address), f))
513+
if account_exists_and_is_empty(state, address):
514+
destroy_account(state, address)
513515

514516

515517
def move_ether(
@@ -556,22 +558,6 @@ def set_balance(account: Account) -> None:
556558
modify_state(state, address, set_balance)
557559

558560

559-
def touch_account(state: State, address: Address) -> None:
560-
"""
561-
Initializes an account to state.
562-
563-
Parameters
564-
----------
565-
state:
566-
The current state.
567-
568-
address:
569-
The address of the account that need to initialised.
570-
"""
571-
if not account_exists(state, address):
572-
set_account(state, address, EMPTY_ACCOUNT)
573-
574-
575561
def increment_nonce(state: State, address: Address) -> None:
576562
"""
577563
Increments the nonce of an account.
@@ -702,20 +688,3 @@ def set_transient_storage(
702688
trie_set(trie, key, value)
703689
if trie._data == {}:
704690
del transient_storage._tries[address]
705-
706-
707-
def destroy_touched_empty_accounts(
708-
state: State, touched_accounts: Set[Address]
709-
) -> None:
710-
"""
711-
Destroy all touched accounts that are empty.
712-
Parameters
713-
----------
714-
state: `State`
715-
The current state.
716-
touched_accounts: `Set[Address]`
717-
All the accounts that have been touched in the current transaction.
718-
"""
719-
for address in touched_accounts:
720-
if account_exists_and_is_empty(state, address):
721-
destroy_account(state, address)

src/ethereum/cancun/vm/__init__.py

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@
2424

2525
from ..blocks import Log, Receipt, Withdrawal
2626
from ..fork_types import Address, VersionedHash
27-
from ..state import State, TransientStorage, account_exists_and_is_empty
27+
from ..state import State, TransientStorage
2828
from ..transactions import LegacyTransaction
2929
from ..trie import Trie
30-
from .precompiled_contracts import RIPEMD160_ADDRESS
3130

3231
__all__ = ("Environment", "Evm", "Message")
3332

@@ -145,7 +144,6 @@ class Evm:
145144
message: Message
146145
output: Bytes
147146
accounts_to_delete: Set[Address]
148-
touched_accounts: Set[Address]
149147
return_data: Bytes
150148
error: Optional[EthereumException]
151149
accessed_addresses: Set[Address]
@@ -167,11 +165,6 @@ def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None:
167165
evm.logs += child_evm.logs
168166
evm.refund_counter += child_evm.refund_counter
169167
evm.accounts_to_delete.update(child_evm.accounts_to_delete)
170-
evm.touched_accounts.update(child_evm.touched_accounts)
171-
if account_exists_and_is_empty(
172-
evm.message.block_env.state, child_evm.message.current_target
173-
):
174-
evm.touched_accounts.add(child_evm.message.current_target)
175168
evm.accessed_addresses.update(child_evm.accessed_addresses)
176169
evm.accessed_storage_keys.update(child_evm.accessed_storage_keys)
177170

@@ -187,18 +180,4 @@ def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None:
187180
child_evm :
188181
The child evm to incorporate.
189182
"""
190-
# In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was
191-
# cleared despite running out of gas. This is an obscure edge case that can
192-
# only happen to a precompile.
193-
# According to the general rules governing clearing of empty accounts, the
194-
# touch should have been reverted. Due to client bugs, this event went
195-
# unnoticed and 0x3 has been exempted from the rule that touches are
196-
# reverted in order to preserve this historical behaviour.
197-
if RIPEMD160_ADDRESS in child_evm.touched_accounts:
198-
evm.touched_accounts.add(RIPEMD160_ADDRESS)
199-
if child_evm.message.current_target == RIPEMD160_ADDRESS:
200-
if account_exists_and_is_empty(
201-
evm.message.block_env.state, child_evm.message.current_target
202-
):
203-
evm.touched_accounts.add(RIPEMD160_ADDRESS)
204183
evm.gas_left += child_evm.gas_left

src/ethereum/cancun/vm/instructions/system.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
from ...fork_types import Address
2121
from ...state import (
22-
account_exists_and_is_empty,
2322
account_has_code_or_nonce,
2423
account_has_storage,
2524
get_account,
@@ -546,10 +545,6 @@ def selfdestruct(evm: Evm) -> None:
546545
set_account_balance(evm.message.block_env.state, originator, U256(0))
547546
evm.accounts_to_delete.add(originator)
548547

549-
# mark beneficiary as touched
550-
if account_exists_and_is_empty(evm.message.block_env.state, beneficiary):
551-
evm.touched_accounts.add(beneficiary)
552-
553548
# HALT the execution
554549
evm.running = False
555550

src/ethereum/cancun/vm/interpreter.py

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
from ..blocks import Log
3434
from ..fork_types import Address
3535
from ..state import (
36-
account_exists_and_is_empty,
3736
account_has_code_or_nonce,
3837
account_has_storage,
3938
begin_transaction,
@@ -44,7 +43,6 @@
4443
move_ether,
4544
rollback_transaction,
4645
set_code,
47-
touch_account,
4846
)
4947
from ..vm import Message
5048
from ..vm.gas import GAS_CODE_DEPOSIT, charge_gas
@@ -77,15 +75,13 @@ class MessageCallOutput:
7775
2. `refund_counter`: gas to refund after execution.
7876
3. `logs`: list of `Log` generated during execution.
7977
4. `accounts_to_delete`: Contracts which have self-destructed.
80-
5. `touched_accounts`: Accounts that have been touched.
81-
6. `error`: The error from the execution if any.
78+
5. `error`: The error from the execution if any.
8279
"""
8380

8481
gas_left: Uint
8582
refund_counter: U256
8683
logs: Tuple[Log, ...]
8784
accounts_to_delete: Set[Address]
88-
touched_accounts: Set[Address]
8985
error: Optional[EthereumException]
9086

9187

@@ -112,25 +108,19 @@ def process_message_call(message: Message) -> MessageCallOutput:
112108
) or account_has_storage(block_env.state, message.current_target)
113109
if is_collision:
114110
return MessageCallOutput(
115-
Uint(0), U256(0), tuple(), set(), set(), AddressCollision()
111+
Uint(0), U256(0), tuple(), set(), AddressCollision()
116112
)
117113
else:
118114
evm = process_create_message(message)
119115
else:
120116
evm = process_message(message)
121-
if account_exists_and_is_empty(
122-
block_env.state, Address(message.target)
123-
):
124-
evm.touched_accounts.add(Address(message.target))
125117

126118
if evm.error:
127119
logs: Tuple[Log, ...] = ()
128120
accounts_to_delete = set()
129-
touched_accounts = set()
130121
else:
131122
logs = evm.logs
132123
accounts_to_delete = evm.accounts_to_delete
133-
touched_accounts = evm.touched_accounts
134124
refund_counter += U256(evm.refund_counter)
135125

136126
tx_end = TransactionEnd(
@@ -143,7 +133,6 @@ def process_message_call(message: Message) -> MessageCallOutput:
143133
refund_counter=refund_counter,
144134
logs=logs,
145135
accounts_to_delete=accounts_to_delete,
146-
touched_accounts=touched_accounts,
147136
error=evm.error,
148137
)
149138

@@ -232,8 +221,6 @@ def process_message(message: Message) -> Evm:
232221
# take snapshot of state before processing the message
233222
begin_transaction(state, transient_storage)
234223

235-
touch_account(state, message.current_target)
236-
237224
if message.should_transfer_value and message.value != 0:
238225
move_ether(
239226
state, message.caller, message.current_target, message.value
@@ -281,7 +268,6 @@ def execute_code(message: Message) -> Evm:
281268
message=message,
282269
output=b"",
283270
accounts_to_delete=set(),
284-
touched_accounts=set(),
285271
return_data=b"",
286272
error=None,
287273
accessed_addresses=message.accessed_addresses,

src/ethereum/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ class InvalidBlock(EthereumException):
1616
"""
1717

1818

19+
class StateWithEmptyAccount(EthereumException):
20+
"""
21+
Thrown when the state has empty account.
22+
"""
23+
24+
1925
class InvalidTransaction(EthereumException):
2026
"""
2127
Thrown when a transaction being processed is found to be invalid.

src/ethereum/paris/fork.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
State,
3535
account_exists_and_is_empty,
3636
destroy_account,
37-
destroy_touched_empty_accounts,
3837
get_account,
3938
increment_nonce,
4039
set_account_balance,
@@ -564,8 +563,6 @@ def process_transaction(
564563
for address in tx_output.accounts_to_delete:
565564
destroy_account(block_env.state, address)
566565

567-
destroy_touched_empty_accounts(block_env.state, tx_output.touched_accounts)
568-
569566
block_output.block_gas_used += tx_gas_used
570567

571568
receipt = make_receipt(

src/ethereum/paris/state.py

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
`EMPTY_ACCOUNT`.
1818
"""
1919
from dataclasses import dataclass, field
20-
from typing import Callable, Dict, Iterable, List, Optional, Set, Tuple
20+
from typing import Callable, Dict, List, Optional, Set, Tuple
2121

2222
from ethereum_types.bytes import Bytes, Bytes32
2323
from ethereum_types.frozen import modify
@@ -477,6 +477,8 @@ def modify_state(
477477
Modify an `Account` in the `State`.
478478
"""
479479
set_account(state, address, modify(get_account(state, address), f))
480+
if account_exists_and_is_empty(state, address):
481+
destroy_account(state, address)
480482

481483

482484
def move_ether(
@@ -523,22 +525,6 @@ def set_balance(account: Account) -> None:
523525
modify_state(state, address, set_balance)
524526

525527

526-
def touch_account(state: State, address: Address) -> None:
527-
"""
528-
Initializes an account to state.
529-
530-
Parameters
531-
----------
532-
state:
533-
The current state.
534-
535-
address:
536-
The address of the account that need to initialised.
537-
"""
538-
if not account_exists(state, address):
539-
set_account(state, address, EMPTY_ACCOUNT)
540-
541-
542528
def increment_nonce(state: State, address: Address) -> None:
543529
"""
544530
Increments the nonce of an account.
@@ -611,20 +597,3 @@ def get_storage_original(state: State, address: Address, key: Bytes32) -> U256:
611597
assert isinstance(original_value, U256)
612598

613599
return original_value
614-
615-
616-
def destroy_touched_empty_accounts(
617-
state: State, touched_accounts: Iterable[Address]
618-
) -> None:
619-
"""
620-
Destroy all touched accounts that are empty.
621-
Parameters
622-
----------
623-
state: `State`
624-
The current state.
625-
touched_accounts: `Iterable[Address]`
626-
All the accounts that have been touched in the current transaction.
627-
"""
628-
for address in touched_accounts:
629-
if account_exists_and_is_empty(state, address):
630-
destroy_account(state, address)

src/ethereum/paris/vm/__init__.py

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@
2424

2525
from ..blocks import Log, Receipt
2626
from ..fork_types import Address
27-
from ..state import State, account_exists_and_is_empty
27+
from ..state import State
2828
from ..transactions import LegacyTransaction
2929
from ..trie import Trie
30-
from .precompiled_contracts import RIPEMD160_ADDRESS
3130

3231
__all__ = ("Environment", "Evm", "Message")
3332

@@ -133,7 +132,6 @@ class Evm:
133132
message: Message
134133
output: Bytes
135134
accounts_to_delete: Set[Address]
136-
touched_accounts: Set[Address]
137135
return_data: Bytes
138136
error: Optional[EthereumException]
139137
accessed_addresses: Set[Address]
@@ -155,11 +153,6 @@ def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None:
155153
evm.logs += child_evm.logs
156154
evm.refund_counter += child_evm.refund_counter
157155
evm.accounts_to_delete.update(child_evm.accounts_to_delete)
158-
evm.touched_accounts.update(child_evm.touched_accounts)
159-
if account_exists_and_is_empty(
160-
evm.message.block_env.state, child_evm.message.current_target
161-
):
162-
evm.touched_accounts.add(child_evm.message.current_target)
163156
evm.accessed_addresses.update(child_evm.accessed_addresses)
164157
evm.accessed_storage_keys.update(child_evm.accessed_storage_keys)
165158

@@ -175,18 +168,4 @@ def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None:
175168
child_evm :
176169
The child evm to incorporate.
177170
"""
178-
# In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was
179-
# cleared despite running out of gas. This is an obscure edge case that can
180-
# only happen to a precompile.
181-
# According to the general rules governing clearing of empty accounts, the
182-
# touch should have been reverted. Due to client bugs, this event went
183-
# unnoticed and 0x3 has been exempted from the rule that touches are
184-
# reverted in order to preserve this historical behaviour.
185-
if RIPEMD160_ADDRESS in child_evm.touched_accounts:
186-
evm.touched_accounts.add(RIPEMD160_ADDRESS)
187-
if child_evm.message.current_target == RIPEMD160_ADDRESS:
188-
if account_exists_and_is_empty(
189-
evm.message.block_env.state, child_evm.message.current_target
190-
):
191-
evm.touched_accounts.add(RIPEMD160_ADDRESS)
192171
evm.gas_left += child_evm.gas_left

0 commit comments

Comments
 (0)