ethereum.forks.bpo3.stateethereum.forks.bpo4.state

State.

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

Introduction

The state contains all information that is preserved between transactions.

It consists of a main account trie and storage tries for each contract.

There is a distinction between an account that does not exist and EMPTY_ACCOUNT.

State

Contains all information that is preserved between transactions.

38
@dataclass
class State:

_main_trie

44
    _main_trie: Trie[Address, Optional[Account]] = field(
45
        default_factory=lambda: Trie(secured=True, default=None)
46
    )

_storage_tries

47
    _storage_tries: Dict[Address, Trie[Bytes32, U256]] = field(
48
        default_factory=dict
49
    )

_snapshots

50
    _snapshots: List[
51
        Tuple[
52
            Trie[Address, Optional[Account]],
53
            Dict[Address, Trie[Bytes32, U256]],
54
        ]
55
    ] = field(default_factory=list)

created_accounts

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

_code_store

57
    _code_store: Dict[Hash32, Bytes] = field(
58
        default_factory=dict, compare=False
59
    )

get_code

Get the bytecode for a given code hash.

Return b"" for EMPTY_CODE_HASH.

def get_code(self, ​​code_hash: Hash32) -> Bytes:
62
        """
63
        Get the bytecode for a given code hash.
64
65
        Return ``b""`` for ``EMPTY_CODE_HASH``.
66
        """
67
        if code_hash == EMPTY_CODE_HASH:
68
            return b""
69
        return self._code_store[code_hash]

TransientStorage

Contains all information that is preserved between message calls within a transaction.

72
@dataclass
class TransientStorage:

_tries

79
    _tries: Dict[Address, Trie[Bytes32, U256]] = field(default_factory=dict)

_snapshots

80
    _snapshots: List[Dict[Address, Trie[Bytes32, U256]]] = field(
81
        default_factory=list
82
    )

close_state

Free resources held by the state. Used by optimized implementations to release file descriptors.

def close_state(state: State) -> None:
86
    """
87
    Free resources held by the state. Used by optimized implementations to
88
    release file descriptors.
89
    """
90
    del state._main_trie
91
    del state._storage_tries
92
    del state._snapshots
93
    del state.created_accounts
94
    del state._code_store

begin_transaction

Start a state transaction.

Transactions are entirely implicit and can be nested. It is not possible to calculate the state root during a transaction.

Parameters

state : State The state. transient_storage : TransientStorage The transient storage of the transaction.

def begin_transaction(state: State, ​​transient_storage: TransientStorage) -> None:
100
    """
101
    Start a state transaction.
102
103
    Transactions are entirely implicit and can be nested. It is not possible to
104
    calculate the state root during a transaction.
105
106
    Parameters
107
    ----------
108
    state : State
109
        The state.
110
    transient_storage : TransientStorage
111
        The transient storage of the transaction.
112
113
    """
114
    state._snapshots.append(
115
        (
116
            copy_trie(state._main_trie),
117
            {k: copy_trie(t) for (k, t) in state._storage_tries.items()},
118
        )
119
    )
120
    transient_storage._snapshots.append(
121
        {k: copy_trie(t) for (k, t) in transient_storage._tries.items()}
122
    )

commit_transaction

Commit a state transaction.

Parameters

state : State The state. transient_storage : TransientStorage The transient storage of the transaction.

def commit_transaction(state: State, ​​transient_storage: TransientStorage) -> None:
128
    """
129
    Commit a state transaction.
130
131
    Parameters
132
    ----------
133
    state : State
134
        The state.
135
    transient_storage : TransientStorage
136
        The transient storage of the transaction.
137
138
    """
139
    state._snapshots.pop()
140
    if not state._snapshots:
141
        state.created_accounts.clear()
142
143
    transient_storage._snapshots.pop()

rollback_transaction

Rollback a state transaction, resetting the state to the point when the corresponding begin_transaction() call was made.

Parameters

state : State The state. transient_storage : TransientStorage The transient storage of the transaction.

def rollback_transaction(state: State, ​​transient_storage: TransientStorage) -> None:
149
    """
150
    Rollback a state transaction, resetting the state to the point when the
151
    corresponding `begin_transaction()` call was made.
152
153
    Parameters
154
    ----------
155
    state : State
156
        The state.
157
    transient_storage : TransientStorage
158
        The transient storage of the transaction.
159
160
    """
161
    state._main_trie, state._storage_tries = state._snapshots.pop()
162
    if not state._snapshots:
163
        state.created_accounts.clear()
164
165
    transient_storage._tries = transient_storage._snapshots.pop()

get_account

Get the Account object at an address. Returns 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

state: State The state address : Address Address to lookup.

Returns

account : Account Account at address.

def get_account(state: State, ​​address: Address) -> Account:
169
    """
170
    Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there
171
    is no account at the address.
172
173
    Use `get_account_optional()` if you care about the difference between a
174
    non-existent account and `EMPTY_ACCOUNT`.
175
176
    Parameters
177
    ----------
178
    state: `State`
179
        The state
180
    address : `Address`
181
        Address to lookup.
182
183
    Returns
184
    -------
185
    account : `Account`
186
        Account at address.
187
188
    """
189
    account = get_account_optional(state, address)
190
    if isinstance(account, Account):
191
        return account
192
    else:
193
        return EMPTY_ACCOUNT

get_account_optional

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

Parameters

state: State The state address : Address Address to lookup.

Returns

account : Account Account at address.

def get_account_optional(state: State, ​​address: Address) -> Optional[Account]:
197
    """
198
    Get the `Account` object at an address. Returns `None` (rather than
199
    `EMPTY_ACCOUNT`) if there is no account at the address.
200
201
    Parameters
202
    ----------
203
    state: `State`
204
        The state
205
    address : `Address`
206
        Address to lookup.
207
208
    Returns
209
    -------
210
    account : `Account`
211
        Account at address.
212
213
    """
214
    account = trie_get(state._main_trie, address)
215
    return account

get_code

Get the bytecode for a given code hash.

Return b"" for EMPTY_CODE_HASH.

def get_code(state: State, ​​code_hash: Hash32) -> Bytes:
219
    """
220
    Get the bytecode for a given code hash.
221
222
    Return ``b""`` for ``EMPTY_CODE_HASH``.
223
    """
224
    if code_hash == EMPTY_CODE_HASH:
225
        return b""
226
    return state._code_store[code_hash]

store_code

Store bytecode in State and return its hash.

def store_code(state: State, ​​code: Bytes) -> Hash32:
230
    """
231
    Store bytecode in ``State`` and return its hash.
232
    """
233
    code_hash = keccak256(code)
234
    if code_hash != EMPTY_CODE_HASH:
235
        state._code_store[code_hash] = code
236
    return code_hash

set_account

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

Parameters

state: State The state address : Address Address to set. account : Account Account to set at address.

def set_account(state: State, ​​address: Address, ​​account: Optional[Account]) -> None:
242
    """
243
    Set the `Account` object at an address. Setting to `None` deletes
244
    the account (but not its storage, see `destroy_account()`).
245
246
    Parameters
247
    ----------
248
    state: `State`
249
        The state
250
    address : `Address`
251
        Address to set.
252
    account : `Account`
253
        Account to set at address.
254
255
    """
256
    trie_set(state._main_trie, address, account)

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.

Parameters

state: State The state address : Address Address of account to destroy.

def destroy_account(state: State, ​​address: Address) -> None:
260
    """
261
    Completely remove the account at `address` and all of its storage.
262
263
    This function is made available exclusively for the `SELFDESTRUCT`
264
    opcode. It is expected that `SELFDESTRUCT` will be disabled in a future
265
    hardfork and this function will be removed.
266
267
    Parameters
268
    ----------
269
    state: `State`
270
        The state
271
    address : `Address`
272
        Address of account to destroy.
273
274
    """
275
    destroy_storage(state, address)
276
    set_account(state, address, None)

destroy_storage

Completely remove the storage at address.

Parameters

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

def destroy_storage(state: State, ​​address: Address) -> None:
280
    """
281
    Completely remove the storage at `address`.
282
283
    Parameters
284
    ----------
285
    state: `State`
286
        The state
287
    address : `Address`
288
        Address of account whose storage is to be deleted.
289
290
    """
291
    if address in state._storage_tries:
292
        del state._storage_tries[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

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

def mark_account_created(state: State, ​​address: Address) -> None:
296
    """
297
    Mark an account as having been created in the current transaction.
298
    This information is used by `get_storage_original()` to handle an obscure
299
    edgecase, and to respect the constraints added to SELFDESTRUCT by
300
    EIP-6780.
301
302
    The marker is not removed even if the account creation reverts. Since the
303
    account cannot have had code prior to its creation and can't call
304
    `get_storage_original()`, this is harmless.
305
306
    Parameters
307
    ----------
308
    state: `State`
309
        The state
310
    address : `Address`
311
        Address of the account that has been created.
312
313
    """
314
    state.created_accounts.add(address)

get_storage

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

Parameters

state: State The state address : Address Address of the account. key : Bytes Key to lookup.

Returns

value : U256 Value at the key.

def get_storage(state: State, ​​address: Address, ​​key: Bytes32) -> U256:
318
    """
319
    Get a value at a storage key on an account. Returns `U256(0)` if the
320
    storage key has not been set previously.
321
322
    Parameters
323
    ----------
324
    state: `State`
325
        The state
326
    address : `Address`
327
        Address of the account.
328
    key : `Bytes`
329
        Key to lookup.
330
331
    Returns
332
    -------
333
    value : `U256`
334
        Value at the key.
335
336
    """
337
    trie = state._storage_tries.get(address)
338
    if trie is None:
339
        return U256(0)
340
341
    value = trie_get(trie, key)
342
343
    assert isinstance(value, U256)
344
    return value

set_storage

Set a value at a storage key on an account. Setting to U256(0) deletes the key.

Parameters

state: State The state address : Address Address of the account. key : Bytes Key to set. value : U256 Value to set at the key.

def set_storage(state: State, ​​address: Address, ​​key: Bytes32, ​​value: U256) -> None:
350
    """
351
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
352
    the key.
353
354
    Parameters
355
    ----------
356
    state: `State`
357
        The state
358
    address : `Address`
359
        Address of the account.
360
    key : `Bytes`
361
        Key to set.
362
    value : `U256`
363
        Value to set at the key.
364
365
    """
366
    assert trie_get(state._main_trie, address) is not None
367
368
    trie = state._storage_tries.get(address)
369
    if trie is None:
370
        trie = Trie(secured=True, default=U256(0))
371
        state._storage_tries[address] = trie
372
    trie_set(trie, key, value)
373
    if trie._data == {}:
374
        del state._storage_tries[address]

storage_root

Calculate the storage root of an account.

Parameters

state: The state address : Address of the account.

Returns

root : Root Storage root of the account.

def storage_root(state: State, ​​address: Address) -> Root:
378
    """
379
    Calculate the storage root of an account.
380
381
    Parameters
382
    ----------
383
    state:
384
        The state
385
    address :
386
        Address of the account.
387
388
    Returns
389
    -------
390
    root : `Root`
391
        Storage root of the account.
392
393
    """
394
    assert not state._snapshots
395
    if address in state._storage_tries:
396
        return root(state._storage_tries[address])
397
    else:
398
        return EMPTY_TRIE_ROOT

state_root

Calculate the state root.

Parameters

state: The current state.

Returns

root : Root The state root.

def state_root(state: State) -> Root:
402
    """
403
    Calculate the state root.
404
405
    Parameters
406
    ----------
407
    state:
408
        The current state.
409
410
    Returns
411
    -------
412
    root : `Root`
413
        The state root.
414
415
    """
416
    assert not state._snapshots
417
418
    def get_storage_root(address: Address) -> Root:
419
        return storage_root(state, address)
420
421
    return root(state._main_trie, get_storage_root=get_storage_root)

account_exists

Checks if an account exists in the state trie.

Parameters

state: The 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(state: State, ​​address: Address) -> bool:
425
    """
426
    Checks if an account exists in the state trie.
427
428
    Parameters
429
    ----------
430
    state:
431
        The state
432
    address:
433
        Address of the account that needs to be checked.
434
435
    Returns
436
    -------
437
    account_exists : `bool`
438
        True if account exists in the state trie, False otherwise
439
440
    """
441
    return get_account_optional(state, address) is not None

account_has_code_or_nonce

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

Parameters

state: The 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(state: State, ​​address: Address) -> bool:
445
    """
446
    Checks if an account has non-zero nonce or non-empty code.
447
448
    Parameters
449
    ----------
450
    state:
451
        The state
452
    address:
453
        Address of the account that needs to be checked.
454
455
    Returns
456
    -------
457
    has_code_or_nonce : `bool`
458
        True if the account has non-zero nonce or non-empty code,
459
        False otherwise.
460
461
    """
462
    account = get_account(state, address)
463
    return account.nonce != Uint(0) or account.code_hash != EMPTY_CODE_HASH

account_has_storage

Checks if an account has storage.

Parameters

state: The 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(state: State, ​​address: Address) -> bool:
467
    """
468
    Checks if an account has storage.
469
470
    Parameters
471
    ----------
472
    state:
473
        The state
474
    address:
475
        Address of the account that needs to be checked.
476
477
    Returns
478
    -------
479
    has_storage : `bool`
480
        True if the account has storage, False otherwise.
481
482
    """
483
    return address in state._storage_tries

is_account_alive

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

Parameters

state: The 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(state: State, ​​address: Address) -> bool:
487
    """
488
    Check whether an account is both in the state and non-empty.
489
490
    Parameters
491
    ----------
492
    state:
493
        The state
494
    address:
495
        Address of the account that needs to be checked.
496
497
    Returns
498
    -------
499
    is_alive : `bool`
500
        True if the account is alive.
501
502
    """
503
    account = get_account_optional(state, address)
504
    return account is not None and account != EMPTY_ACCOUNT

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(state: State, ​​address: Address, ​​f: Callable[[Account], None]) -> None:
510
    """
511
    Modify an `Account` in the `State`. If, after modification, the account
512
    exists and has zero nonce, empty code, and zero balance, it is destroyed.
513
    """
514
    set_account(state, address, modify(get_account(state, address), f))
515
516
    account = get_account_optional(state, address)
517
    account_exists_and_is_empty = (
518
        account is not None
519
        and account.nonce == Uint(0)
520
        and account.code_hash == EMPTY_CODE_HASH
521
        and account.balance == 0
522
    )
523
524
    if account_exists_and_is_empty:
525
        destroy_account(state, address)

move_ether

Move funds between accounts.

def move_ether(state: State, ​​sender_address: Address, ​​recipient_address: Address, ​​amount: U256) -> None:
534
    """
535
    Move funds between accounts.
536
    """
537
538
    def reduce_sender_balance(sender: Account) -> None:
539
        if sender.balance < amount:
540
            raise AssertionError
541
        sender.balance -= amount
542
543
    def increase_recipient_balance(recipient: Account) -> None:
544
        recipient.balance += amount
545
546
    modify_state(state, sender_address, reduce_sender_balance)
547
    modify_state(state, recipient_address, increase_recipient_balance)

set_account_balance

Sets the balance of an account.

Parameters

state: The current state.

address: Address of the account whose nonce needs to be incremented.

amount: The amount that needs to be set in the balance.

def set_account_balance(state: State, ​​address: Address, ​​amount: U256) -> None:
551
    """
552
    Sets the balance of an account.
553
554
    Parameters
555
    ----------
556
    state:
557
        The current state.
558
559
    address:
560
        Address of the account whose nonce needs to be incremented.
561
562
    amount:
563
        The amount that needs to be set in the balance.
564
565
    """
566
567
    def set_balance(account: Account) -> None:
568
        account.balance = amount
569
570
    modify_state(state, address, set_balance)

increment_nonce

Increments the nonce of an account.

Parameters

state: The current state.

address: Address of the account whose nonce needs to be incremented.

def increment_nonce(state: State, ​​address: Address) -> None:
574
    """
575
    Increments the nonce of an account.
576
577
    Parameters
578
    ----------
579
    state:
580
        The current state.
581
582
    address:
583
        Address of the account whose nonce needs to be incremented.
584
585
    """
586
587
    def increase_nonce(sender: Account) -> None:
588
        sender.nonce += Uint(1)
589
590
    modify_state(state, address, increase_nonce)

set_code

Sets Account code.

Parameters

state: The current state.

address: Address of the account whose code needs to be updated.

code: The bytecode that needs to be set.

def set_code(state: State, ​​address: Address, ​​code: Bytes) -> None:
594
    """
595
    Sets Account code.
596
597
    Parameters
598
    ----------
599
    state:
600
        The current state.
601
602
    address:
603
        Address of the account whose code needs to be updated.
604
605
    code:
606
        The bytecode that needs to be set.
607
608
    """
609
    code_hash = keccak256(code)
610
    if code_hash != EMPTY_CODE_HASH:
611
        state._code_store[code_hash] = code
612
613
    def write_code(sender: Account) -> None:
614
        sender.code_hash = code_hash
615
616
    modify_state(state, address, write_code)

get_storage_original

Get the original value in a storage slot i.e. the value before the current transaction began. This function reads the value from the snapshots taken before executing the transaction.

Parameters

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

def get_storage_original(state: State, ​​address: Address, ​​key: Bytes32) -> U256:
620
    """
621
    Get the original value in a storage slot i.e. the value before the current
622
    transaction began. This function reads the value from the snapshots taken
623
    before executing the transaction.
624
625
    Parameters
626
    ----------
627
    state:
628
        The current state.
629
    address:
630
        Address of the account to read the value from.
631
    key:
632
        Key of the storage slot.
633
634
    """
635
    # In the transaction where an account is created, its preexisting storage
636
    # is ignored.
637
    if address in state.created_accounts:
638
        return U256(0)
639
640
    _, original_trie = state._snapshots[0]
641
    original_account_trie = original_trie.get(address)
642
643
    if original_account_trie is None:
644
        original_value = U256(0)
645
    else:
646
        original_value = trie_get(original_account_trie, key)
647
648
    assert isinstance(original_value, U256)
649
650
    return original_value

get_transient_storage

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

Parameters

transient_storage: TransientStorage The transient storage address : Address Address of the account. key : Bytes Key to lookup.

Returns

value : U256 Value at the key.

def get_transient_storage(transient_storage: TransientStorage, ​​address: Address, ​​key: Bytes32) -> U256:
656
    """
657
    Get a value at a storage key on an account from transient storage.
658
    Returns `U256(0)` if the storage key has not been set previously.
659
660
    Parameters
661
    ----------
662
    transient_storage: `TransientStorage`
663
        The transient storage
664
    address : `Address`
665
        Address of the account.
666
    key : `Bytes`
667
        Key to lookup.
668
669
    Returns
670
    -------
671
    value : `U256`
672
        Value at the key.
673
674
    """
675
    trie = transient_storage._tries.get(address)
676
    if trie is None:
677
        return U256(0)
678
679
    value = trie_get(trie, key)
680
681
    assert isinstance(value, U256)
682
    return value

set_transient_storage

Set a value at a storage key on an account. Setting to U256(0) deletes the key.

Parameters

transient_storage: TransientStorage The transient storage address : Address Address of the account. key : Bytes Key to set. value : U256 Value to set at the key.

def set_transient_storage(transient_storage: TransientStorage, ​​address: Address, ​​key: Bytes32, ​​value: U256) -> None:
691
    """
692
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
693
    the key.
694
695
    Parameters
696
    ----------
697
    transient_storage: `TransientStorage`
698
        The transient storage
699
    address : `Address`
700
        Address of the account.
701
    key : `Bytes`
702
        Key to set.
703
    value : `U256`
704
        Value to set at the key.
705
706
    """
707
    trie = transient_storage._tries.get(address)
708
    if trie is None:
709
        trie = Trie(secured=True, default=U256(0))
710
        transient_storage._tries[address] = trie
711
    trie_set(trie, key, value)
712
    if trie._data == {}:
713
        del transient_storage._tries[address]