ethereum.forks.shanghai.state_trackerethereum.forks.cancun.state_tracker

State Tracking for Block Execution.

Track state changes on top of a read-only PreState. At block end, accumulated diffs feed into PreState.compute_state_root_and_trie_changes().

.. contents:: Table of Contents :backlinks: none :local:

Introduction

Replace the mutable State class with lightweight state trackers that record diffs. BlockState accumulates committed transaction changes across a block. TransactionState tracks in-flight changes within a single transaction and supports copy-on-write rollback.

BlockState

Accumulate committed transaction-level changes across a block.

Read chain: block writes -> pre_state.

storage_clears records addresses whose storage was wiped by a pre-EIP-6780 SELFDESTRUCT earlier in the block, so later reads must not fall back to pre_state storage.

39
@dataclass
class BlockState:

pre_state

47
    pre_state: PreState

account_writes

48
    account_writes: Dict[Address, Optional[Account]] = field(
49
        default_factory=dict
50
    )

storage_writes

51
    storage_writes: Dict[Address, Dict[Bytes32, U256]] = field(
52
        default_factory=dict
53
    )

code_writes

54
    code_writes: Dict[Hash32, Bytes] = field(default_factory=dict)

storage_clears

59
    storage_clears: Set[Address] = field(default_factory=set)

TransactionState

Track in-flight state changes within a single transaction.

Read chain: tx writes -> block writes -> pre_state.

57
@dataclass
class TransactionState:

parent

65
    parent: BlockState

account_writes

66
    account_writes: Dict[Address, Optional[Account]] = field(
67
        default_factory=dict
68
    )

storage_writes

69
    storage_writes: Dict[Address, Dict[Bytes32, U256]] = field(
70
        default_factory=dict
71
    )

code_writes

72
    code_writes: Dict[Hash32, Bytes] = field(default_factory=dict)

created_accounts

73
    created_accounts: Set[Address] = field(default_factory=set)

storage_clears

79
    storage_clears: Set[Address] = field(default_factory=set)

transient_storage

74
    transient_storage: Dict[Tuple[Address, Bytes32], U256] = field(
75
        default_factory=dict
76
    )

get_account_optional

Get the Account object at an address. Return None (rather than EMPTY_ACCOUNT) if there is no account at the address.

Parameters

tx_state : The transaction state. address : Address to look up.

Returns

account : Optional[Account] Account at address.

def get_account_optional(tx_state: TransactionState, ​​address: Address) -> Optional[Account]:
82
    """
83
    Get the ``Account`` object at an address. Return ``None`` (rather than
84
    ``EMPTY_ACCOUNT``) if there is no account at the address.
85
86
    Parameters
87
    ----------
88
    tx_state :
89
        The transaction state.
90
    address :
91
        Address to look up.
92
93
    Returns
94
    -------
95
    account : ``Optional[Account]``
96
        Account at address.
97
98
    """
99
    if address in tx_state.account_writes:
100
        return tx_state.account_writes[address]
101
    if address in tx_state.parent.account_writes:
102
        return tx_state.parent.account_writes[address]
103
    return tx_state.parent.pre_state.get_account_optional(address)

get_account

Get the Account object at an address. Return EMPTY_ACCOUNT if there is no account at the address.

Use get_account_optional() if you care about the difference between a non-existent account and EMPTY_ACCOUNT.

Parameters

tx_state : The transaction state. address : Address to look up.

Returns

account : Account Account at address.

def get_account(tx_state: TransactionState, ​​address: Address) -> Account:
107
    """
108
    Get the ``Account`` object at an address. Return ``EMPTY_ACCOUNT``
109
    if there is no account at the address.
110
111
    Use ``get_account_optional()`` if you care about the difference
112
    between a non-existent account and ``EMPTY_ACCOUNT``.
113
114
    Parameters
115
    ----------
116
    tx_state :
117
        The transaction state.
118
    address :
119
        Address to look up.
120
121
    Returns
122
    -------
123
    account : ``Account``
124
        Account at address.
125
126
    """
127
    account = get_account_optional(tx_state, address)
128
    if account is None:
129
        return EMPTY_ACCOUNT
130
    else:
131
        return account

get_code

Get the bytecode for a given code hash.

Read chain: tx code_writes -> block code_writes -> pre_state.

Parameters

tx_state : The transaction state. code_hash : Hash of the code to look up.

Returns

code : Bytes The bytecode.

def get_code(tx_state: TransactionState, ​​code_hash: Hash32) -> Bytes:
135
    """
136
    Get the bytecode for a given code hash.
137
138
    Read chain: tx code_writes -> block code_writes -> pre_state.
139
140
    Parameters
141
    ----------
142
    tx_state :
143
        The transaction state.
144
    code_hash :
145
        Hash of the code to look up.
146
147
    Returns
148
    -------
149
    code : ``Bytes``
150
        The bytecode.
151
152
    """
153
    if code_hash == EMPTY_CODE_HASH:
154
        return b""
155
    if code_hash in tx_state.code_writes:
156
        return tx_state.code_writes[code_hash]
157
    if code_hash in tx_state.parent.code_writes:
158
        return tx_state.parent.code_writes[code_hash]
159
    return tx_state.parent.pre_state.get_code(code_hash)

get_storage

Get a value at a storage key on an account. Return U256(0) if the storage key has not been set previously.

Parameters

tx_state : The transaction state. address : Address of the account. key : Key to look up.

Returns

value : U256 Value at the key.

def get_storage(tx_state: TransactionState, ​​address: Address, ​​key: Bytes32) -> U256:
165
    """
166
    Get a value at a storage key on an account. Return ``U256(0)`` if
167
    the storage key has not been set previously.
168
169
    Parameters
170
    ----------
171
    tx_state :
172
        The transaction state.
173
    address :
174
        Address of the account.
175
    key :
176
        Key to look up.
177
178
    Returns
179
    -------
180
    value : ``U256``
181
        Value at the key.
182
183
    """
184
    if address in tx_state.storage_writes:
185
        if key in tx_state.storage_writes[address]:
186
            return tx_state.storage_writes[address][key]
193
    if address in tx_state.storage_clears:
194
        return U256(0)
187
    if address in tx_state.parent.storage_writes:
188
        if key in tx_state.parent.storage_writes[address]:
189
            return tx_state.parent.storage_writes[address][key]
198
    if address in tx_state.parent.storage_clears:
199
        return U256(0)
190
    return tx_state.parent.pre_state.get_storage(address, key)

get_storage_original

Get the original value in a storage slot i.e. the value before the current transaction began. Read from block-level writes, then pre_state. Return U256(0) for accounts created in the current transaction.

Parameters

tx_state : The transaction state. address : Address of the account to read the value from. key : Key of the storage slot.

def get_storage_original(tx_state: TransactionState, ​​address: Address, ​​key: Bytes32) -> U256:
196
    """
197
    Get the original value in a storage slot i.e. the value before the
198
    current transaction began. Read from block-level writes, then
199
    pre_state. Return ``U256(0)`` for accounts created in the current
200
    transaction.
201
202
    Parameters
203
    ----------
204
    tx_state :
205
        The transaction state.
206
    address :
207
        Address of the account to read the value from.
208
    key :
209
        Key of the storage slot.
210
211
    """
212
    if address in tx_state.created_accounts:
213
        return U256(0)
214
    if address in tx_state.parent.storage_writes:
215
        if key in tx_state.parent.storage_writes[address]:
216
            return tx_state.parent.storage_writes[address][key]
227
    if address in tx_state.parent.storage_clears:
228
        return U256(0)
217
    return tx_state.parent.pre_state.get_storage(address, key)

get_transient_storage

Get a value at a storage key on an account from transient storage. Return U256(0) if the storage key has not been set previously.

Parameters

tx_state : The transaction state. address : Address of the account. key : Key to look up.

Returns

value : U256 Value at the key.

def get_transient_storage(tx_state: TransactionState, ​​address: Address, ​​key: Bytes32) -> U256:
223
    """
224
    Get a value at a storage key on an account from transient storage.
225
    Return ``U256(0)`` if the storage key has not been set previously.
226
227
    Parameters
228
    ----------
229
    tx_state :
230
        The transaction state.
231
    address :
232
        Address of the account.
233
    key :
234
        Key to look up.
235
236
    Returns
237
    -------
238
    value : ``U256``
239
        Value at the key.
240
241
    """
242
    return tx_state.transient_storage.get((address, key), U256(0))

account_exists

Check if an account exists in the state trie.

Parameters

tx_state : The transaction state. address : Address of the account that needs to be checked.

Returns

account_exists : bool True if account exists in the state trie, False otherwise.

def account_exists(tx_state: TransactionState, ​​address: Address) -> bool:
246
    """
247
    Check if an account exists in the state trie.
248
249
    Parameters
250
    ----------
251
    tx_state :
252
        The transaction state.
253
    address :
254
        Address of the account that needs to be checked.
255
256
    Returns
257
    -------
258
    account_exists : ``bool``
259
        True if account exists in the state trie, False otherwise.
260
261
    """
262
    return get_account_optional(tx_state, address) is not None

account_has_code_or_nonce

Check if an account has non-zero nonce or non-empty code.

Parameters

tx_state : The transaction state. address : Address of the account that needs to be checked.

Returns

has_code_or_nonce : bool True if the account has non-zero nonce or non-empty code, False otherwise.

def account_has_code_or_nonce(tx_state: TransactionState, ​​address: Address) -> bool:
268
    """
269
    Check if an account has non-zero nonce or non-empty code.
270
271
    Parameters
272
    ----------
273
    tx_state :
274
        The transaction state.
275
    address :
276
        Address of the account that needs to be checked.
277
278
    Returns
279
    -------
280
    has_code_or_nonce : ``bool``
281
        True if the account has non-zero nonce or non-empty code,
282
        False otherwise.
283
284
    """
285
    account = get_account(tx_state, address)
286
    return account.nonce != Uint(0) or account.code_hash != EMPTY_CODE_HASH

account_has_storage

Check if an account has storage.

Parameters

tx_state : The transaction state. address : Address of the account that needs to be checked.

Returns

has_storage : bool True if the account has storage, False otherwise.

def account_has_storage(tx_state: TransactionState, ​​address: Address) -> bool:
290
    """
291
    Check if an account has storage.
292
293
    Parameters
294
    ----------
295
    tx_state :
296
        The transaction state.
297
    address :
298
        Address of the account that needs to be checked.
299
300
    Returns
301
    -------
302
    has_storage : ``bool``
303
        True if the account has storage, False otherwise.
304
305
    """
306
    if tx_state.storage_writes.get(address):
307
        return True
320
    if address in tx_state.storage_clears:
321
        return False
308
    if tx_state.parent.storage_writes.get(address):
309
        return True
324
    if address in tx_state.parent.storage_clears:
325
        return False
310
    return tx_state.parent.pre_state.account_has_storage(address)

account_exists_and_is_empty

Check if an account exists and has zero nonce, empty code and zero balance.

Parameters

tx_state : The transaction state. address : Address of the account that needs to be checked.

Returns

exists_and_is_empty : bool True if an account exists and has zero nonce, empty code and zero balance, False otherwise.

def account_exists_and_is_empty(tx_state: TransactionState, ​​address: Address) -> bool:
316
    """
317
    Check if an account exists and has zero nonce, empty code and zero
318
    balance.
319
320
    Parameters
321
    ----------
322
    tx_state :
323
        The transaction state.
324
    address :
325
        Address of the account that needs to be checked.
326
327
    Returns
328
    -------
329
    exists_and_is_empty : ``bool``
330
        True if an account exists and has zero nonce, empty code and
331
        zero balance, False otherwise.
332
333
    """
334
    account = get_account_optional(tx_state, address)
335
    return (
336
        account is not None
337
        and account.nonce == Uint(0)
338
        and account.code_hash == EMPTY_CODE_HASH
339
        and account.balance == 0
340
    )

is_account_alive

Check whether an account is both in the state and non-empty.

Parameters

tx_state : The transaction state. address : Address of the account that needs to be checked.

Returns

is_alive : bool True if the account is alive.

def is_account_alive(tx_state: TransactionState, ​​address: Address) -> bool:
344
    """
345
    Check whether an account is both in the state and non-empty.
346
347
    Parameters
348
    ----------
349
    tx_state :
350
        The transaction state.
351
    address :
352
        Address of the account that needs to be checked.
353
354
    Returns
355
    -------
356
    is_alive : ``bool``
357
        True if the account is alive.
358
359
    """
360
    account = get_account_optional(tx_state, address)
361
    return account is not None and account != EMPTY_ACCOUNT

set_account

Set the Account object at an address. Setting to None deletes the account (but not its storage, see destroy_account()).

Parameters

tx_state : The transaction state. address : Address to set. account : Account to set at address.

def set_account(tx_state: TransactionState, ​​address: Address, ​​account: Optional[Account]) -> None:
369
    """
370
    Set the ``Account`` object at an address. Setting to ``None``
371
    deletes the account (but not its storage, see
372
    ``destroy_account()``).
373
374
    Parameters
375
    ----------
376
    tx_state :
377
        The transaction state.
378
    address :
379
        Address to set.
380
    account :
381
        Account to set at address.
382
383
    """
384
    tx_state.account_writes[address] = account

set_storage

Set a value at a storage key on an account.

Parameters

tx_state : The transaction state. address : Address of the account. key : Key to set. value : Value to set at the key.

def set_storage(tx_state: TransactionState, ​​address: Address, ​​key: Bytes32, ​​value: U256) -> None:
393
    """
394
    Set a value at a storage key on an account.
395
396
    Parameters
397
    ----------
398
    tx_state :
399
        The transaction state.
400
    address :
401
        Address of the account.
402
    key :
403
        Key to set.
404
    value :
405
        Value to set at the key.
406
407
    """
408
    assert get_account_optional(tx_state, address) is not None
409
    if address not in tx_state.storage_writes:
410
        tx_state.storage_writes[address] = {}
411
    tx_state.storage_writes[address][key] = value

destroy_account

Completely remove the account at address and all of its storage.

This function is made available exclusively for the SELFDESTRUCT opcode. It is expected that SELFDESTRUCT will be disabled in a future hardfork and this function will be removed. Only supports same transaction destruction.

Parameters

tx_state : The transaction state. address : Address of account to destroy.

def destroy_account(tx_state: TransactionState, ​​address: Address) -> None:
415
    """
416
    Completely remove the account at ``address`` and all of its storage.
417
418
    This function is made available exclusively for the ``SELFDESTRUCT``
419
    opcode. It is expected that ``SELFDESTRUCT`` will be disabled in a
420
    future hardfork and this function will be removed. Only supports same
421
    transaction destruction.
422
423
    Parameters
424
    ----------
425
    tx_state :
426
        The transaction state.
427
    address :
428
        Address of account to destroy.
429
430
    """
431
    destroy_storage(tx_state, address)
432
    set_account(tx_state, address, None)

destroy_storage

Completely remove the storage at address.

Only supports same transaction destruction.

Parameters

tx_state : The transaction state. address : Address of account whose storage is to be deleted.

def destroy_storage(tx_state: TransactionState, ​​address: Address) -> None:
436
    """
437
    Completely remove the storage at ``address``.
438
439
    Only supports same transaction destruction.
440
441
    Parameters
442
    ----------
443
    tx_state :
444
        The transaction state.
445
    address :
446
        Address of account whose storage is to be deleted.
447
448
    """
449
    if address in tx_state.storage_writes:
466
        del tx_state.storage_writes[address]
467
    tx_state.storage_clears.add(address)
450
        del tx_state.storage_writes[address]

mark_account_created

Mark an account as having been created in the current transaction. This information is used by get_storage_original() to handle an obscure edgecase, and to respect the constraints added to SELFDESTRUCT by EIP-6780.

The marker is not removed even if the account creation reverts. Since the account cannot have had code prior to its creation and can't call get_storage_original(), this is harmless.

Parameters

tx_state : The transaction state. address : Address of the account that has been created.

def mark_account_created(tx_state: TransactionState, ​​address: Address) -> None:
454
    """
455
    Mark an account as having been created in the current transaction.
456
    This information is used by ``get_storage_original()`` to handle an
457
    obscure edgecase, and to respect the constraints added to
458
    SELFDESTRUCT by EIP-6780.
459
460
    The marker is not removed even if the account creation reverts.
461
    Since the account cannot have had code prior to its creation and
462
    can't call ``get_storage_original()``, this is harmless.
463
464
    Parameters
465
    ----------
466
    tx_state :
467
        The transaction state.
468
    address :
469
        Address of the account that has been created.
470
471
    """
472
    tx_state.created_accounts.add(address)

set_transient_storage

Set a value at a storage key on an account in transient storage.

Parameters

tx_state : The transaction state. address : Address of the account. key : Key to set. value : Value to set at the key.

def set_transient_storage(tx_state: TransactionState, ​​address: Address, ​​key: Bytes32, ​​value: U256) -> None:
481
    """
482
    Set a value at a storage key on an account in transient storage.
483
484
    Parameters
485
    ----------
486
    tx_state :
487
        The transaction state.
488
    address :
489
        Address of the account.
490
    key :
491
        Key to set.
492
    value :
493
        Value to set at the key.
494
495
    """
496
    if value == U256(0):
497
        tx_state.transient_storage.pop((address, key), None)
498
    else:
499
        tx_state.transient_storage[(address, key)] = value

modify_state

Modify an Account in the state. If, after modification, the account exists and has zero nonce, empty code, and zero balance, it is destroyed.

def modify_state(tx_state: TransactionState, ​​address: Address, ​​f: Callable[[Account], None]) -> None:
507
    """
508
    Modify an ``Account`` in the state. If, after modification, the
509
    account exists and has zero nonce, empty code, and zero balance, it
510
    is destroyed.
511
    """
512
    set_account(tx_state, address, modify(get_account(tx_state, address), f))
513
    if account_exists_and_is_empty(tx_state, address):
514
        destroy_account(tx_state, address)

move_ether

Move funds between accounts.

Parameters

tx_state : The transaction state. sender_address : Address of the sender. recipient_address : Address of the recipient. amount : The amount to transfer.

def move_ether(tx_state: TransactionState, ​​sender_address: Address, ​​recipient_address: Address, ​​amount: U256) -> None:
523
    """
524
    Move funds between accounts.
525
526
    Parameters
527
    ----------
528
    tx_state :
529
        The transaction state.
530
    sender_address :
531
        Address of the sender.
532
    recipient_address :
533
        Address of the recipient.
534
    amount :
535
        The amount to transfer.
536
537
    """
538
539
    def reduce_sender_balance(sender: Account) -> None:
540
        if sender.balance < amount:
541
            raise AssertionError
542
        sender.balance -= amount
543
544
    def increase_recipient_balance(recipient: Account) -> None:
545
        recipient.balance += amount
546
547
    modify_state(tx_state, sender_address, reduce_sender_balance)
548
    modify_state(tx_state, recipient_address, increase_recipient_balance)

create_ether

Add newly created ether to an account.

Parameters

tx_state : The transaction state. address : Address of the account to which ether is added. amount : The amount of ether to be added to the account of interest.

def create_ether(tx_state: TransactionState, ​​address: Address, ​​amount: U256) -> None:
554
    """
555
    Add newly created ether to an account.
556
557
    Parameters
558
    ----------
559
    tx_state :
560
        The transaction state.
561
    address :
562
        Address of the account to which ether is added.
563
    amount :
564
        The amount of ether to be added to the account of interest.
565
566
    """
567
568
    def increase_balance(account: Account) -> None:
569
        account.balance += amount
570
571
    modify_state(tx_state, address, increase_balance)

set_account_balance

Set the balance of an account.

Parameters

tx_state : The transaction state. address : Address of the account whose balance needs to be set. amount : The amount that needs to be set in the balance.

def set_account_balance(tx_state: TransactionState, ​​address: Address, ​​amount: U256) -> None:
577
    """
578
    Set the balance of an account.
579
580
    Parameters
581
    ----------
582
    tx_state :
583
        The transaction state.
584
    address :
585
        Address of the account whose balance needs to be set.
586
    amount :
587
        The amount that needs to be set in the balance.
588
589
    """
590
591
    def set_balance(account: Account) -> None:
592
        account.balance = amount
593
594
    modify_state(tx_state, address, set_balance)

increment_nonce

Increment the nonce of an account.

Parameters

tx_state : The transaction state. address : Address of the account whose nonce needs to be incremented.

def increment_nonce(tx_state: TransactionState, ​​address: Address) -> None:
598
    """
599
    Increment the nonce of an account.
600
601
    Parameters
602
    ----------
603
    tx_state :
604
        The transaction state.
605
    address :
606
        Address of the account whose nonce needs to be incremented.
607
608
    """
609
610
    def increase_nonce(sender: Account) -> None:
611
        sender.nonce += Uint(1)
612
613
    modify_state(tx_state, address, increase_nonce)

set_code

Set Account code.

Parameters

tx_state : The transaction state. address : Address of the account whose code needs to be updated. code : The bytecode that needs to be set.

def set_code(tx_state: TransactionState, ​​address: Address, ​​code: Bytes) -> None:
619
    """
620
    Set Account code.
621
622
    Parameters
623
    ----------
624
    tx_state :
625
        The transaction state.
626
    address :
627
        Address of the account whose code needs to be updated.
628
    code :
629
        The bytecode that needs to be set.
630
631
    """
632
    code_hash = keccak256(code)
633
    if code_hash != EMPTY_CODE_HASH:
634
        tx_state.code_writes[code_hash] = code
635
636
    def write_code_hash(sender: Account) -> None:
637
        sender.code_hash = code_hash
638
639
    modify_state(tx_state, address, write_code_hash)

copy_tx_state

Create a snapshot of the transaction state for rollback.

Deep-copy writes and transient storage. The parent reference and created_accounts are shared (not rolled back).

Parameters

tx_state : The transaction state to snapshot.

Returns

snapshot : TransactionState A copy of the transaction state.

def copy_tx_state(tx_state: TransactionState) -> TransactionState:
646
    """
647
    Create a snapshot of the transaction state for rollback.
648
649
    Deep-copy writes and transient storage.  The parent reference and
650
    ``created_accounts`` are shared (not rolled back).
651
652
    Parameters
653
    ----------
654
    tx_state :
655
        The transaction state to snapshot.
656
657
    Returns
658
    -------
659
    snapshot : ``TransactionState``
660
        A copy of the transaction state.
661
662
    """
663
    return TransactionState(
664
        parent=tx_state.parent,
665
        account_writes=dict(tx_state.account_writes),
666
        storage_writes={
667
            addr: dict(slots)
668
            for addr, slots in tx_state.storage_writes.items()
669
        },
670
        code_writes=dict(tx_state.code_writes),
671
        created_accounts=tx_state.created_accounts,
689
        storage_clears=set(tx_state.storage_clears),
672
        transient_storage=dict(tx_state.transient_storage),
673
    )

restore_tx_state

Restore transaction state from a snapshot (rollback on failure).

Parameters

tx_state : The transaction state to restore. snapshot : The snapshot to restore from.

def restore_tx_state(tx_state: TransactionState, ​​snapshot: TransactionState) -> None:
679
    """
680
    Restore transaction state from a snapshot (rollback on failure).
681
682
    Parameters
683
    ----------
684
    tx_state :
685
        The transaction state to restore.
686
    snapshot :
687
        The snapshot to restore from.
688
689
    """
690
    tx_state.account_writes = snapshot.account_writes
691
    tx_state.storage_writes = snapshot.storage_writes
692
    tx_state.code_writes = snapshot.code_writes
711
    tx_state.storage_clears = snapshot.storage_clears
693
    tx_state.transient_storage = snapshot.transient_storage

incorporate_tx_into_block

Merge transaction writes into the block state and clear for reuse.

Parameters

tx_state : The transaction state to commit.

def incorporate_tx_into_block(tx_state: TransactionState) -> None:
700
    """
701
    Merge transaction writes into the block state and clear for reuse.
702
703
    Parameters
704
    ----------
705
    tx_state :
706
        The transaction state to commit.
707
708
    """
709
    block = tx_state.parent
710
711
    for address, account in tx_state.account_writes.items():
712
        block.account_writes[address] = account
713
733
    for address in tx_state.storage_clears:
734
        block.storage_clears.add(address)
735
        block.storage_writes.pop(address, None)
736
714
    for address, slots in tx_state.storage_writes.items():
715
        if address not in block.storage_writes:
716
            block.storage_writes[address] = {}
717
        block.storage_writes[address].update(slots)
718
719
    block.code_writes.update(tx_state.code_writes)
720
721
    tx_state.account_writes.clear()
722
    tx_state.storage_writes.clear()
723
    tx_state.code_writes.clear()
724
    tx_state.created_accounts.clear()
748
    tx_state.storage_clears.clear()
725
    tx_state.transient_storage.clear()

extract_block_diff

Extract account, storage, and code diff from the block state.

Parameters

block_state : The block state.

Returns

diff : BlockDiff Account, storage, and code changes accumulated during block execution.

def extract_block_diff(block_state: BlockState) -> BlockDiff:
729
    """
730
    Extract account, storage, and code diff from the block state.
731
732
    Parameters
733
    ----------
734
    block_state :
735
        The block state.
736
737
    Returns
738
    -------
739
    diff : `BlockDiff`
740
        Account, storage, and code changes accumulated during block execution.
741
742
    """
743
    return BlockDiff(
744
        account_changes=block_state.account_writes,
745
        storage_changes=block_state.storage_writes,
746
        code_changes=block_state.code_writes,
771
        storage_clears=block_state.storage_clears,
747
    )