ethereum.forks.gray_glacier.stateethereum.forks.paris.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

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

_storage_tries

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

_snapshots

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

created_accounts

50
    created_accounts: Set[Address] = field(default_factory=set)
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

Return the bytecode for a given code hash.

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

close_state

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

def close_state(state: State) -> None:
71
    """
72
    Free resources held by the state. Used by optimized implementations to
73
    release file descriptors.
74
    """
75
    del state._main_trie
76
    del state._storage_tries
77
    del state._snapshots
78
    del state.created_accounts
79
    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.

def begin_transaction(state: State) -> None:
83
    """
84
    Start a state transaction.
85
86
    Transactions are entirely implicit and can be nested. It is not possible to
87
    calculate the state root during a transaction.
88
89
    Parameters
90
    ----------
91
    state : State
92
        The state.
93
94
    """
95
    state._snapshots.append(
96
        (
97
            copy_trie(state._main_trie),
98
            {k: copy_trie(t) for (k, t) in state._storage_tries.items()},
99
        )
100
    )

commit_transaction

Commit a state transaction.

Parameters

state : State The state.

def commit_transaction(state: State) -> None:
104
    """
105
    Commit a state transaction.
106
107
    Parameters
108
    ----------
109
    state : State
110
        The state.
111
112
    """
113
    state._snapshots.pop()
114
    if not state._snapshots:
115
        state.created_accounts.clear()

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.

def rollback_transaction(state: State) -> None:
119
    """
120
    Rollback a state transaction, resetting the state to the point when the
121
    corresponding `begin_transaction()` call was made.
122
123
    Parameters
124
    ----------
125
    state : State
126
        The state.
127
128
    """
129
    state._main_trie, state._storage_tries = state._snapshots.pop()
130
    if not state._snapshots:
131
        state.created_accounts.clear()

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: AddressAddress) -> AccountAccount:
135
    """
136
    Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there
137
    is no account at the address.
138
139
    Use `get_account_optional()` if you care about the difference between a
140
    non-existent account and `EMPTY_ACCOUNT`.
141
142
    Parameters
143
    ----------
144
    state: `State`
145
        The state
146
    address : `Address`
147
        Address to lookup.
148
149
    Returns
150
    -------
151
    account : `Account`
152
        Account at address.
153
154
    """
155
    account = get_account_optional(state, address)
142
    if isinstance(account, Account):
156
    if isinstance(account, Account):
157
        return account
158
    else:
145
        return EMPTY_ACCOUNT
159
        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: AddressAddress) -> Optional[AccountAccount]:
163
    """
164
    Get the `Account` object at an address. Returns `None` (rather than
165
    `EMPTY_ACCOUNT`) if there is no account at the address.
166
167
    Parameters
168
    ----------
169
    state: `State`
170
        The state
171
    address : `Address`
172
        Address to lookup.
173
174
    Returns
175
    -------
176
    account : `Account`
177
        Account at address.
178
179
    """
180
    account = trie_get(state._main_trie, address)
181
    return account

get_code

Get the bytecode for a given code hash.Return the bytecode for a given code hash.

Parameters

state: The current state. code_hash: The hash of the code to retrieve.

Returns

code : Bytes The bytecode for the given hash.

def get_code(state: State, ​​code_hash: Hash32) -> Bytes:
185
    """
172
    Get the bytecode for a given code hash.
186
    Return the bytecode for a given code hash.
187
188
    Parameters
189
    ----------
190
    state:
191
        The current state.
192
    code_hash:
193
        The hash of the code to retrieve.
194
195
    Returns
196
    -------
197
    code : `Bytes`
198
        The bytecode for the given hash.
199
200
    """
174
    if code_hash == EMPTY_CODE_HASH:
175
        return b""
176
    return state._code_store[code_hash]
201
    return state.get_code(code_hash)

store_code

Store bytecode in State.Store bytecode in the code store and return its hash.

Parameters

state: The current state. code: The bytecode to store.

Returns

code_hash : Hash32 The keccak256 hash of the stored bytecode.

def store_code(state: State, ​​code: Bytes) -> Hash32:
205
    """
181
    Store bytecode in ``State``.
206
    Store bytecode in the code store and return its hash.
207
208
    Parameters
209
    ----------
210
    state:
211
        The current state.
212
    code:
213
        The bytecode to store.
214
215
    Returns
216
    -------
217
    code_hash : `Hash32`
218
        The keccak256 hash of the stored bytecode.
219
220
    """
221
    code_hash = keccak256(code)
184
    if code_hash != EMPTY_CODE_HASH:
222
    if code_hash != EMPTY_CODE_HASH:
223
        state._code_store[code_hash] = code
224
    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: AddressAddress, ​​account: Optional[AccountAccount]) -> None:
230
    """
231
    Set the `Account` object at an address. Setting to `None` deletes
232
    the account (but not its storage, see `destroy_account()`).
233
234
    Parameters
235
    ----------
236
    state: `State`
237
        The state
238
    address : `Address`
239
        Address to set.
240
    account : `Account`
241
        Account to set at address.
242
243
    """
244
    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: AddressAddress) -> None:
248
    """
249
    Completely remove the account at `address` and all of its storage.
250
251
    This function is made available exclusively for the `SELFDESTRUCT`
252
    opcode. It is expected that `SELFDESTRUCT` will be disabled in a future
253
    hardfork and this function will be removed.
254
255
    Parameters
256
    ----------
257
    state: `State`
258
        The state
259
    address : `Address`
260
        Address of account to destroy.
261
262
    """
263
    destroy_storage(state, address)
264
    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: AddressAddress) -> None:
268
    """
269
    Completely remove the storage at `address`.
270
271
    Parameters
272
    ----------
273
    state: `State`
274
        The state
275
    address : `Address`
276
        Address of account whose storage is to be deleted.
277
278
    """
279
    if address in state._storage_tries:
280
        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.

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: AddressAddress) -> None:
284
    """
285
    Mark an account as having been created in the current transaction.
286
    This information is used by `get_storage_original()` to handle an obscure
287
    edgecase.
288
289
    The marker is not removed even if the account creation reverts. Since the
290
    account cannot have had code prior to its creation and can't call
291
    `get_storage_original()`, this is harmless.
292
293
    Parameters
294
    ----------
295
    state: `State`
296
        The state
297
    address : `Address`
298
        Address of the account that has been created.
299
300
    """
301
    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: AddressAddress, ​​key: Bytes32) -> U256:
305
    """
306
    Get a value at a storage key on an account. Returns `U256(0)` if the
307
    storage key has not been set previously.
308
309
    Parameters
310
    ----------
311
    state: `State`
312
        The state
313
    address : `Address`
314
        Address of the account.
315
    key : `Bytes`
316
        Key to lookup.
317
318
    Returns
319
    -------
320
    value : `U256`
321
        Value at the key.
322
323
    """
324
    trie = state._storage_tries.get(address)
325
    if trie is None:
326
        return U256(0)
327
328
    value = trie_get(trie, key)
329
330
    assert isinstance(value, U256)
331
    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: AddressAddress, ​​key: Bytes32, ​​value: U256) -> None:
337
    """
338
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
339
    the key.
340
341
    Parameters
342
    ----------
343
    state: `State`
344
        The state
345
    address : `Address`
346
        Address of the account.
347
    key : `Bytes`
348
        Key to set.
349
    value : `U256`
350
        Value to set at the key.
351
352
    """
353
    assert trie_get(state._main_trie, address) is not None
354
355
    trie = state._storage_tries.get(address)
356
    if trie is None:
357
        trie = Trie(secured=True, default=U256(0))
358
        state._storage_tries[address] = trie
359
    trie_set(trie, key, value)
360
    if trie._data == {}:
361
        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: AddressAddress) -> RootRoot:
365
    """
366
    Calculate the storage root of an account.
367
368
    Parameters
369
    ----------
370
    state:
371
        The state
372
    address :
373
        Address of the account.
374
375
    Returns
376
    -------
377
    root : `Root`
378
        Storage root of the account.
379
380
    """
381
    assert not state._snapshots
382
    if address in state._storage_tries:
383
        return root(state._storage_tries[address])
384
    else:
385
        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) -> RootRoot:
389
    """
390
    Calculate the state root.
391
392
    Parameters
393
    ----------
394
    state:
395
        The current state.
396
397
    Returns
398
    -------
399
    root : `Root`
400
        The state root.
401
402
    """
403
    assert not state._snapshots
404
367
    def get_storage_root(address: Address) -> Root:
405
    def get_storage_root(address: Address) -> Root:
406
        return storage_root(state, address)
407
408
    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: AddressAddress) -> bool:
412
    """
413
    Checks if an account exists in the state trie.
414
415
    Parameters
416
    ----------
417
    state:
418
        The state
419
    address:
420
        Address of the account that needs to be checked.
421
422
    Returns
423
    -------
424
    account_exists : `bool`
425
        True if account exists in the state trie, False otherwise
426
427
    """
428
    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: AddressAddress) -> bool:
432
    """
433
    Checks if an account has non-zero nonce or non-empty code.
434
435
    Parameters
436
    ----------
437
    state:
438
        The state
439
    address:
440
        Address of the account that needs to be checked.
441
442
    Returns
443
    -------
444
    has_code_or_nonce : `bool`
445
        True if the account has non-zero nonce or non-empty code,
446
        False otherwise.
447
448
    """
449
    account = get_account(state, address)
412
    return account.nonce != Uint(0) or account.code_hash != EMPTY_CODE_HASH
450
    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: AddressAddress) -> bool:
454
    """
455
    Checks if an account has storage.
456
457
    Parameters
458
    ----------
459
    state:
460
        The state
461
    address:
462
        Address of the account that needs to be checked.
463
464
    Returns
465
    -------
466
    has_storage : `bool`
467
        True if the account has storage, False otherwise.
468
469
    """
470
    return address in state._storage_tries

account_exists_and_is_empty

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

Parameters

state: The 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(state: State, ​​address: Address) -> bool:
436
    """
437
    Checks if an account exists and has zero nonce, empty code and zero
438
    balance.
439
440
    Parameters
441
    ----------
442
    state:
443
        The state
444
    address:
445
        Address of the account that needs to be checked.
446
447
    Returns
448
    -------
449
    exists_and_is_empty : `bool`
450
        True if an account exists and has zero nonce, empty code and zero
451
        balance, False otherwise.
452
453
    """
454
    account = get_account_optional(state, address)
455
    return (
456
        account is not None
457
        and account.nonce == Uint(0)
458
        and account.code_hash == EMPTY_CODE_HASH
459
        and account.balance == 0
460
    )

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: AddressAddress) -> bool:
474
    """
475
    Check whether an account is both in the state and non-empty.
476
477
    Parameters
478
    ----------
479
    state:
480
        The state
481
    address:
482
        Address of the account that needs to be checked.
483
484
    Returns
485
    -------
486
    is_alive : `bool`
487
        True if the account is alive.
488
489
    """
490
    account = get_account_optional(state, address)
481
    return account is not None and account != EMPTY_ACCOUNT
491
    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: AddressAddress, ​​f: Callable[[AccountAccount], None]) -> None:
497
    """
488
    Modify an `Account` in the `State`.
498
    Modify an `Account` in the `State`. If, after modification, the account
499
    exists and has zero nonce, empty code, and zero balance, it is destroyed.
500
    """
490
    set_account(state, address, modify(get_account(state, address), f))
501
    set_account(state, address, modify(get_account(state, address), f))
502
503
    account = get_account_optional(state, address)
504
    account_exists_and_is_empty = (
505
        account is not None
506
        and account.nonce == Uint(0)
507
        and account.code_hash == EMPTY_CODE_HASH
508
        and account.balance == 0
509
    )
510
511
    if account_exists_and_is_empty:
512
        destroy_account(state, address)

move_ether

Move funds between accounts.

def move_ether(state: State, ​​sender_address: AddressAddress, ​​recipient_address: AddressAddress, ​​amount: U256) -> None:
521
    """
522
    Move funds between accounts.
523
    """
524
503
    def reduce_sender_balance(sender: Account) -> None:
525
    def reduce_sender_balance(sender: Account) -> None:
526
        if sender.balance < amount:
527
            raise AssertionError
528
        sender.balance -= amount
529
508
    def increase_recipient_balance(recipient: Account) -> None:
530
    def increase_recipient_balance(recipient: Account) -> None:
531
        recipient.balance += amount
532
533
    modify_state(state, sender_address, reduce_sender_balance)
534
    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: AddressAddress, ​​amount: U256) -> None:
538
    """
539
    Sets the balance of an account.
540
541
    Parameters
542
    ----------
543
    state:
544
        The current state.
545
546
    address:
547
        Address of the account whose nonce needs to be incremented.
548
549
    amount:
550
        The amount that needs to be set in the balance.
551
552
    """
553
532
    def set_balance(account: Account) -> None:
554
    def set_balance(account: Account) -> None:
555
        account.balance = amount
556
557
    modify_state(state, address, set_balance)

touch_account

Initializes an account to state.

Parameters

state: The current state.

address: The address of the account that needs to be initialized.

def touch_account(state: State, ​​address: Address) -> None:
539
    """
540
    Initializes an account to state.
541
542
    Parameters
543
    ----------
544
    state:
545
        The current state.
546
547
    address:
548
        The address of the account that needs to be initialized.
549
550
    """
551
    if not account_exists(state, address):
552
        set_account(state, address, EMPTY_ACCOUNT)

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: AddressAddress) -> None:
561
    """
562
    Increments the nonce of an account.
563
564
    Parameters
565
    ----------
566
    state:
567
        The current state.
568
569
    address:
570
        Address of the account whose nonce needs to be incremented.
571
572
    """
573
569
    def increase_nonce(sender: Account) -> None:
574
    def increase_nonce(sender: Account) -> None:
575
        sender.nonce += Uint(1)
576
577
    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: AddressAddress, ​​code: Bytes) -> None:
581
    """
582
    Sets Account code.
583
584
    Parameters
585
    ----------
586
    state:
587
        The current state.
588
589
    address:
590
        Address of the account whose code needs to be updated.
591
592
    code:
593
        The bytecode that needs to be set.
594
595
    """
591
    code_hash = keccak256(code)
592
    if code_hash != EMPTY_CODE_HASH:
593
        state._code_store[code_hash] = code
596
    code_hash = store_code(state, code)
597
595
    def write_code(sender: Account) -> None:
598
    def write_code(sender: Account) -> None:
599
        sender.code_hash = code_hash
600
601
    modify_state(state, address, write_code)

create_ether

Add newly created ether to an account.

Parameters

state: The current 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(state: State, ​​address: Address, ​​amount: U256) -> None:
602
    """
603
    Add newly created ether to an account.
604
605
    Parameters
606
    ----------
607
    state:
608
        The current state.
609
    address:
610
        Address of the account to which ether is added.
611
    amount:
612
        The amount of ether to be added to the account of interest.
613
614
    """
615
616
    def increase_balance(account: Account) -> None:
617
        account.balance += amount
618
619
    modify_state(state, address, increase_balance)

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: AddressAddress, ​​key: Bytes32) -> U256:
605
    """
606
    Get the original value in a storage slot i.e. the value before the current
607
    transaction began. This function reads the value from the snapshots taken
608
    before executing the transaction.
609
610
    Parameters
611
    ----------
612
    state:
613
        The current state.
614
    address:
615
        Address of the account to read the value from.
616
    key:
617
        Key of the storage slot.
618
619
    """
620
    # In the transaction where an account is created, its preexisting storage
621
    # is ignored.
622
    if address in state.created_accounts:
623
        return U256(0)
624
625
    _, original_trie = state._snapshots[0]
626
    original_account_trie = original_trie.get(address)
627
628
    if original_account_trie is None:
629
        original_value = U256(0)
630
    else:
631
        original_value = trie_get(original_account_trie, key)
632
633
    assert isinstance(original_value, U256)
634
635
    return original_value

destroy_touched_empty_accounts

Destroy all touched accounts that are empty.

Parameters

state: State The current state. touched_accounts: Iterable[Address] All the accounts that have been touched in the current transaction.

def destroy_touched_empty_accounts(state: State, ​​touched_accounts: Iterable[Address]) -> None:
659
    """
660
    Destroy all touched accounts that are empty.
661
662
    Parameters
663
    ----------
664
    state: `State`
665
        The current state.
666
    touched_accounts: `Iterable[Address]`
667
        All the accounts that have been touched in the current transaction.
668
669
    """
670
    for address in touched_accounts:
671
        if account_exists_and_is_empty(state, address):
672
            destroy_account(state, address)