Skip to content
Merged
Show file tree
Hide file tree
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
25 changes: 13 additions & 12 deletions src/ethereum/forks/amsterdam/block_access_lists/tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class StateChangeTracker:
"""
Cache of pre-transaction balance values, keyed by address.
This cache is cleared at the start of each transaction and used by
finalize_transaction_changes to filter out balance changes where
normalize_balance_changes to filter out balance changes where
the final balance equals the initial balance.
"""

Expand Down Expand Up @@ -293,7 +293,7 @@ def capture_pre_balance(
to ensure we capture the pre-transaction balance correctly. The cache is
cleared at the beginning of each transaction.

This is used by finalize_transaction_changes to determine which balance
This is used by normalize_balance_changes to determine which balance
changes should be filtered out.

Parameters
Expand Down Expand Up @@ -331,9 +331,7 @@ def track_balance_change(
Track a balance change for an account.

Records the new balance after any balance-affecting operation, including
transfers, gas payments, block rewards, and withdrawals. The balance is
encoded as a 16-byte value (uint128) which is sufficient for the total
ETH supply.
transfers, gas payments, block rewards, and withdrawals.

Parameters
----------
Expand Down Expand Up @@ -454,7 +452,7 @@ def handle_in_transaction_selfdestruct(
code changes from the current transaction are also removed.

Note: Balance changes are handled separately by
finalize_transaction_changes.
normalize_balance_changes.

Parameters
----------
Expand Down Expand Up @@ -495,22 +493,25 @@ def handle_in_transaction_selfdestruct(
]


def finalize_transaction_changes(
def normalize_balance_changes(
tracker: StateChangeTracker, state: "State"
) -> None:
"""
Finalize changes for the current transaction.
Normalize balance changes for the current block access index.

This method is called at the end of each transaction execution to filter
out spurious balance changes. It removes all balance changes for addresses
where the post-transaction balance equals the pre-transaction balance.
This method filters out spurious balance changes by removing all balance
changes for addresses where the post-execution balance equals the
pre-execution balance.

This is crucial for handling cases like:
- In-transaction self-destructs where an account with 0 balance is created
and destroyed, resulting in no net balance change
- Round-trip transfers where an account receives and sends equal amounts
- Zero-amount withdrawals where the balance doesn't actually change

Only actual state changes are recorded in the Block Access List.
This should be called at the end of any operation that tracks balance
changes (transactions, withdrawals, etc.). Only actual state changes are
recorded in the Block Access List.

Parameters
----------
Expand Down
21 changes: 18 additions & 3 deletions src/ethereum/forks/amsterdam/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
from .block_access_lists.builder import build_block_access_list
from .block_access_lists.rlp_utils import compute_block_access_list_hash
from .block_access_lists.tracker import (
finalize_transaction_changes,
capture_pre_balance,
handle_in_transaction_selfdestruct,
normalize_balance_changes,
set_block_access_index,
track_balance_change,
)
Expand Down Expand Up @@ -1022,9 +1023,9 @@ def process_transaction(
)
destroy_account(block_env.state, address)

# EIP-7928: Finalize transaction changes
# EIP-7928: Normalize balance changes for this transaction
# Remove balance changes where post-tx balance equals pre-tx balance
finalize_transaction_changes(
normalize_balance_changes(
block_env.state.change_tracker,
block_env.state,
)
Expand Down Expand Up @@ -1067,6 +1068,12 @@ def increase_recipient_balance(recipient: Account) -> None:
rlp.encode(wd),
)

# Capture pre-balance before modification (even for zero withdrawals)
# This ensures the address appears in BAL per EIP-7928
capture_pre_balance(
block_env.state.change_tracker, wd.address, block_env.state
)

modify_state(block_env.state, wd.address, increase_recipient_balance)

# Track balance change for BAL
Expand All @@ -1076,6 +1083,14 @@ def increase_recipient_balance(recipient: Account) -> None:
block_env.state.change_tracker, wd.address, U256(new_balance)
)

# EIP-7928: Normalize balance changes for this withdrawal
# Remove balance changes where post-withdrawal balance
# equals pre-withdrawal balance
normalize_balance_changes(
block_env.state.change_tracker,
block_env.state,
)

if account_exists_and_is_empty(block_env.state, wd.address):
destroy_account(block_env.state, wd.address)

Expand Down
Loading