ethereum.forks.amsterdam.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.

account_reads and storage_reads accumulate across all transactions for BAL generation.

42
@dataclass
class BlockState:

pre_state

53
    pre_state: PreState

account_reads

54
    account_reads: Set[Address] = field(default_factory=set)

account_writes

55
    account_writes: Dict[Address, Optional[Account]] = field(
56
        default_factory=dict
57
    )

storage_reads

58
    storage_reads: Set[Tuple[Address, Bytes32]] = field(default_factory=set)

storage_writes

59
    storage_writes: Dict[Address, Dict[Bytes32, U256]] = field(
60
        default_factory=dict
61
    )

code_writes

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

TransactionState

Track in-flight state changes within a single transaction.

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

storage_reads and account_reads are shared references that survive rollback (reads from failed calls still appear in the Block Access List).

65
@dataclass
class TransactionState:

parent

77
    parent: BlockState

account_reads

78
    account_reads: Set[Address] = field(default_factory=set)

account_writes

79
    account_writes: Dict[Address, Optional[Account]] = field(
80
        default_factory=dict
81
    )

storage_reads

82
    storage_reads: Set[Tuple[Address, Bytes32]] = field(default_factory=set)

storage_writes

83
    storage_writes: Dict[Address, Dict[Bytes32, U256]] = field(
84
        default_factory=dict
85
    )

code_writes

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

created_accounts

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

transient_storage

88
    transient_storage: Dict[Tuple[Address, Bytes32], U256] = field(
89
        default_factory=dict
90
    )

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]:
96
    """
97
    Get the ``Account`` object at an address. Return ``None`` (rather than
98
    ``EMPTY_ACCOUNT``) if there is no account at the address.
99
100
    Parameters
101
    ----------
102
    tx_state :
103
        The transaction state.
104
    address :
105
        Address to look up.
106
107
    Returns
108
    -------
109
    account : ``Optional[Account]``
110
        Account at address.
111
112
    """
113
    tx_state.account_reads.add(address)
114
    if address in tx_state.account_writes:
115
        return tx_state.account_writes[address]
116
    if address in tx_state.parent.account_writes:
117
        return tx_state.parent.account_writes[address]
118
    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:
122
    """
123
    Get the ``Account`` object at an address. Return ``EMPTY_ACCOUNT``
124
    if there is no account at the address.
125
126
    Use ``get_account_optional()`` if you care about the difference
127
    between a non-existent account and ``EMPTY_ACCOUNT``.
128
129
    Parameters
130
    ----------
131
    tx_state :
132
        The transaction state.
133
    address :
134
        Address to look up.
135
136
    Returns
137
    -------
138
    account : ``Account``
139
        Account at address.
140
141
    """
142
    account = get_account_optional(tx_state, address)
143
    if account is None:
144
        return EMPTY_ACCOUNT
145
    else:
146
        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:
150
    """
151
    Get the bytecode for a given code hash.
152
153
    Read chain: tx code_writes -> block code_writes -> pre_state.
154
155
    Parameters
156
    ----------
157
    tx_state :
158
        The transaction state.
159
    code_hash :
160
        Hash of the code to look up.
161
162
    Returns
163
    -------
164
    code : ``Bytes``
165
        The bytecode.
166
167
    """
168
    if code_hash == EMPTY_CODE_HASH:
169
        return b""
170
    if code_hash in tx_state.code_writes:
171
        return tx_state.code_writes[code_hash]
172
    if code_hash in tx_state.parent.code_writes:
173
        return tx_state.parent.code_writes[code_hash]
174
    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:
180
    """
181
    Get a value at a storage key on an account. Return ``U256(0)`` if
182
    the storage key has not been set previously.
183
184
    Parameters
185
    ----------
186
    tx_state :
187
        The transaction state.
188
    address :
189
        Address of the account.
190
    key :
191
        Key to look up.
192
193
    Returns
194
    -------
195
    value : ``U256``
196
        Value at the key.
197
198
    """
199
    tx_state.storage_reads.add((address, key))
200
    if address in tx_state.storage_writes:
201
        if key in tx_state.storage_writes[address]:
202
            return tx_state.storage_writes[address][key]
203
    if address in tx_state.parent.storage_writes:
204
        if key in tx_state.parent.storage_writes[address]:
205
            return tx_state.parent.storage_writes[address][key]
206
    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:
212
    """
213
    Get the original value in a storage slot i.e. the value before the
214
    current transaction began. Read from block-level writes, then
215
    pre_state. Return ``U256(0)`` for accounts created in the current
216
    transaction.
217
218
    Parameters
219
    ----------
220
    tx_state :
221
        The transaction state.
222
    address :
223
        Address of the account to read the value from.
224
    key :
225
        Key of the storage slot.
226
227
    """
228
    if address in tx_state.created_accounts:
229
        return U256(0)
230
    if address in tx_state.parent.storage_writes:
231
        if key in tx_state.parent.storage_writes[address]:
232
            return tx_state.parent.storage_writes[address][key]
233
    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:
239
    """
240
    Get a value at a storage key on an account from transient storage.
241
    Return ``U256(0)`` if the storage key has not been set previously.
242
243
    Parameters
244
    ----------
245
    tx_state :
246
        The transaction state.
247
    address :
248
        Address of the account.
249
    key :
250
        Key to look up.
251
252
    Returns
253
    -------
254
    value : ``U256``
255
        Value at the key.
256
257
    """
258
    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:
262
    """
263
    Check if an account exists in the state trie.
264
265
    Parameters
266
    ----------
267
    tx_state :
268
        The transaction state.
269
    address :
270
        Address of the account that needs to be checked.
271
272
    Returns
273
    -------
274
    account_exists : ``bool``
275
        True if account exists in the state trie, False otherwise.
276
277
    """
278
    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:
284
    """
285
    Check if an account has non-zero nonce or non-empty code.
286
287
    Parameters
288
    ----------
289
    tx_state :
290
        The transaction state.
291
    address :
292
        Address of the account that needs to be checked.
293
294
    Returns
295
    -------
296
    has_code_or_nonce : ``bool``
297
        True if the account has non-zero nonce or non-empty code,
298
        False otherwise.
299
300
    """
301
    account = get_account(tx_state, address)
302
    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:
306
    """
307
    Check if an account has storage.
308
309
    Parameters
310
    ----------
311
    tx_state :
312
        The transaction state.
313
    address :
314
        Address of the account that needs to be checked.
315
316
    Returns
317
    -------
318
    has_storage : ``bool``
319
        True if the account has storage, False otherwise.
320
321
    """
322
    if tx_state.storage_writes.get(address):
323
        return True
324
    if tx_state.parent.storage_writes.get(address):
325
        return True
326
    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:
332
    """
333
    Check if an account exists and has zero nonce, empty code and zero
334
    balance.
335
336
    Parameters
337
    ----------
338
    tx_state :
339
        The transaction state.
340
    address :
341
        Address of the account that needs to be checked.
342
343
    Returns
344
    -------
345
    exists_and_is_empty : ``bool``
346
        True if an account exists and has zero nonce, empty code and
347
        zero balance, False otherwise.
348
349
    """
350
    account = get_account_optional(tx_state, address)
351
    return (
352
        account is not None
353
        and account.nonce == Uint(0)
354
        and account.code_hash == EMPTY_CODE_HASH
355
        and account.balance == 0
356
    )

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:
360
    """
361
    Check whether an account is both in the state and non-empty.
362
363
    Parameters
364
    ----------
365
    tx_state :
366
        The transaction state.
367
    address :
368
        Address of the account that needs to be checked.
369
370
    Returns
371
    -------
372
    is_alive : ``bool``
373
        True if the account is alive.
374
375
    """
376
    account = get_account_optional(tx_state, address)
377
    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:
385
    """
386
    Set the ``Account`` object at an address. Setting to ``None``
387
    deletes the account (but not its storage, see
388
    ``destroy_account()``).
389
390
    Parameters
391
    ----------
392
    tx_state :
393
        The transaction state.
394
    address :
395
        Address to set.
396
    account :
397
        Account to set at address.
398
399
    """
400
    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:
409
    """
410
    Set a value at a storage key on an account.
411
412
    Parameters
413
    ----------
414
    tx_state :
415
        The transaction state.
416
    address :
417
        Address of the account.
418
    key :
419
        Key to set.
420
    value :
421
        Value to set at the key.
422
423
    """
424
    assert get_account_optional(tx_state, address) is not None
425
    if address not in tx_state.storage_writes:
426
        tx_state.storage_writes[address] = {}
427
    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:
431
    """
432
    Completely remove the account at ``address`` and all of its storage.
433
434
    This function is made available exclusively for the ``SELFDESTRUCT``
435
    opcode. It is expected that ``SELFDESTRUCT`` will be disabled in a
436
    future hardfork and this function will be removed. Only supports same
437
    transaction destruction.
438
439
    Parameters
440
    ----------
441
    tx_state :
442
        The transaction state.
443
    address :
444
        Address of account to destroy.
445
446
    """
447
    destroy_storage(tx_state, address)
448
    set_account(tx_state, address, None)

destroy_storage

Completely remove the storage at address.

Convert storage writes to reads before deleting so that accesses from created-then-destroyed accounts appear in the Block Access List. 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:
452
    """
453
    Completely remove the storage at ``address``.
454
455
    Convert storage writes to reads before deleting so that accesses
456
    from created-then-destroyed accounts appear in the Block Access
457
    List. Only supports same transaction destruction.
458
459
    Parameters
460
    ----------
461
    tx_state :
462
        The transaction state.
463
    address :
464
        Address of account whose storage is to be deleted.
465
466
    """
467
    if address in tx_state.storage_writes:
468
        for key in tx_state.storage_writes[address]:
469
            tx_state.storage_reads.add((address, key))
470
        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:
474
    """
475
    Mark an account as having been created in the current transaction.
476
    This information is used by ``get_storage_original()`` to handle an
477
    obscure edgecase, and to respect the constraints added to
478
    SELFDESTRUCT by EIP-6780.
479
480
    The marker is not removed even if the account creation reverts.
481
    Since the account cannot have had code prior to its creation and
482
    can't call ``get_storage_original()``, this is harmless.
483
484
    Parameters
485
    ----------
486
    tx_state :
487
        The transaction state.
488
    address :
489
        Address of the account that has been created.
490
491
    """
492
    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:
501
    """
502
    Set a value at a storage key on an account in transient storage.
503
504
    Parameters
505
    ----------
506
    tx_state :
507
        The transaction state.
508
    address :
509
        Address of the account.
510
    key :
511
        Key to set.
512
    value :
513
        Value to set at the key.
514
515
    """
516
    if value == U256(0):
517
        tx_state.transient_storage.pop((address, key), None)
518
    else:
519
        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:
527
    """
528
    Modify an ``Account`` in the state. If, after modification, the
529
    account exists and has zero nonce, empty code, and zero balance, it
530
    is destroyed.
531
    """
532
    set_account(tx_state, address, modify(get_account(tx_state, address), f))
533
    if account_exists_and_is_empty(tx_state, address):
534
        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:
543
    """
544
    Move funds between accounts.
545
546
    Parameters
547
    ----------
548
    tx_state :
549
        The transaction state.
550
    sender_address :
551
        Address of the sender.
552
    recipient_address :
553
        Address of the recipient.
554
    amount :
555
        The amount to transfer.
556
557
    """
558
559
    def reduce_sender_balance(sender: Account) -> None:
560
        if sender.balance < amount:
561
            raise AssertionError
562
        sender.balance -= amount
563
564
    def increase_recipient_balance(recipient: Account) -> None:
565
        recipient.balance += amount
566
567
    modify_state(tx_state, sender_address, reduce_sender_balance)
568
    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:
574
    """
575
    Add newly created ether to an account.
576
577
    Parameters
578
    ----------
579
    tx_state :
580
        The transaction state.
581
    address :
582
        Address of the account to which ether is added.
583
    amount :
584
        The amount of ether to be added to the account of interest.
585
586
    """
587
588
    def increase_balance(account: Account) -> None:
589
        account.balance += amount
590
591
    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:
597
    """
598
    Set the balance of an account.
599
600
    Parameters
601
    ----------
602
    tx_state :
603
        The transaction state.
604
    address :
605
        Address of the account whose balance needs to be set.
606
    amount :
607
        The amount that needs to be set in the balance.
608
609
    """
610
611
    def set_balance(account: Account) -> None:
612
        account.balance = amount
613
614
    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:
618
    """
619
    Increment the nonce of an account.
620
621
    Parameters
622
    ----------
623
    tx_state :
624
        The transaction state.
625
    address :
626
        Address of the account whose nonce needs to be incremented.
627
628
    """
629
630
    def increase_nonce(sender: Account) -> None:
631
        sender.nonce += Uint(1)
632
633
    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:
639
    """
640
    Set Account code.
641
642
    Parameters
643
    ----------
644
    tx_state :
645
        The transaction state.
646
    address :
647
        Address of the account whose code needs to be updated.
648
    code :
649
        The bytecode that needs to be set.
650
651
    """
652
    code_hash = keccak256(code)
653
    if code_hash != EMPTY_CODE_HASH:
654
        tx_state.code_writes[code_hash] = code
655
656
    def write_code_hash(sender: Account) -> None:
657
        sender.code_hash = code_hash
658
659
    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, created_accounts, storage_reads, and account_reads 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:
666
    """
667
    Create a snapshot of the transaction state for rollback.
668
669
    Deep-copy writes and transient storage.  The parent reference,
670
    ``created_accounts``, ``storage_reads``, and ``account_reads``
671
    are shared (not rolled back).
672
673
    Parameters
674
    ----------
675
    tx_state :
676
        The transaction state to snapshot.
677
678
    Returns
679
    -------
680
    snapshot : ``TransactionState``
681
        A copy of the transaction state.
682
683
    """
684
    return TransactionState(
685
        parent=tx_state.parent,
686
        account_writes=dict(tx_state.account_writes),
687
        storage_writes={
688
            addr: dict(slots)
689
            for addr, slots in tx_state.storage_writes.items()
690
        },
691
        code_writes=dict(tx_state.code_writes),
692
        created_accounts=tx_state.created_accounts,
693
        transient_storage=dict(tx_state.transient_storage),
694
        storage_reads=tx_state.storage_reads,
695
        account_reads=tx_state.account_reads,
696
    )

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:
702
    """
703
    Restore transaction state from a snapshot (rollback on failure).
704
705
    Parameters
706
    ----------
707
    tx_state :
708
        The transaction state to restore.
709
    snapshot :
710
        The snapshot to restore from.
711
712
    """
713
    tx_state.account_writes = snapshot.account_writes
714
    tx_state.storage_writes = snapshot.storage_writes
715
    tx_state.code_writes = snapshot.code_writes
716
    tx_state.transient_storage = snapshot.transient_storage

incorporate_tx_into_block

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

Update the BAL builder incrementally by diffing this transaction's writes against the block's cumulative state. Merge reads and touches into block-level sets.

Parameters

tx_state : The transaction state to commit. builder : The BAL builder for incremental updates.

def incorporate_tx_into_block(tx_state: TransactionState, ​​builder: "BlockAccessListBuilder") -> None:
726
    """
727
    Merge transaction writes into the block state and clear for reuse.
728
729
    Update the BAL builder incrementally by diffing this transaction's
730
    writes against the block's cumulative state.  Merge reads and
731
    touches into block-level sets.
732
733
    Parameters
734
    ----------
735
    tx_state :
736
        The transaction state to commit.
737
    builder :
738
        The BAL builder for incremental updates.
739
740
    """
741
    from .block_access_lists import update_builder_from_tx
742
743
    block = tx_state.parent
744
745
    # Update BAL builder before merging writes into block state
746
    update_builder_from_tx(builder, tx_state)
747
748
    # Merge reads and touches into block-level sets
749
    block.storage_reads.update(tx_state.storage_reads)
750
    block.account_reads.update(tx_state.account_reads)
751
752
    # Merge cumulative writes
753
    for address, account in tx_state.account_writes.items():
754
        block.account_writes[address] = account
755
756
    for address, slots in tx_state.storage_writes.items():
757
        if address not in block.storage_writes:
758
            block.storage_writes[address] = {}
759
        block.storage_writes[address].update(slots)
760
761
    block.code_writes.update(tx_state.code_writes)
762
763
    tx_state.account_writes.clear()
764
    tx_state.storage_writes.clear()
765
    tx_state.code_writes.clear()
766
    tx_state.created_accounts.clear()
767
    tx_state.transient_storage.clear()
768
    tx_state.storage_reads = set()
769
    tx_state.account_reads = set()

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:
773
    """
774
    Extract account, storage, and code diff from the block state.
775
776
    Parameters
777
    ----------
778
    block_state :
779
        The block state.
780
781
    Returns
782
    -------
783
    diff : `BlockDiff`
784
        Account, storage, and code changes accumulated during block execution.
785
786
    """
787
    return BlockDiff(
788
        account_changes=block_state.account_writes,
789
        storage_changes=block_state.storage_writes,
790
        code_changes=block_state.code_writes,
791
    )