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

30
@dataclass
class State:

_main_trie

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

_storage_tries

39
    _storage_tries: Dict[Address, Trie[Bytes32, U256]] = field(
40
        default_factory=dict
41
    )

_snapshots

42
    _snapshots: List[
43
        Tuple[
44
            Trie[Address, Optional[Account]],
45
            Dict[Address, Trie[Bytes32, U256]],
46
        ]
47
    ] = field(default_factory=list)

created_accounts

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

TransientStorage

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

51
@dataclass
class TransientStorage:

_tries

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

_snapshots

59
    _snapshots: List[Dict[Address, Trie[Bytes32, U256]]] = field(
60
        default_factory=list
61
    )

close_state

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

def close_state(state: State) -> None:
65
    """
66
    Free resources held by the state. Used by optimized implementations to
67
    release file descriptors.
68
    """
69
    del state._main_trie
70
    del state._storage_tries
71
    del state._snapshots
72
    del state.created_accounts

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:
78
    """
79
    Start a state transaction.
80
81
    Transactions are entirely implicit and can be nested. It is not possible to
82
    calculate the state root during a transaction.
83
84
    Parameters
85
    ----------
86
    state : State
87
        The state.
88
    transient_storage : TransientStorage
89
        The transient storage of the transaction.
90
91
    """
92
    state._snapshots.append(
93
        (
94
            copy_trie(state._main_trie),
95
            {k: copy_trie(t) for (k, t) in state._storage_tries.items()},
96
        )
97
    )
98
    transient_storage._snapshots.append(
99
        {k: copy_trie(t) for (k, t) in transient_storage._tries.items()}
100
    )

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:
106
    """
107
    Commit a state transaction.
108
109
    Parameters
110
    ----------
111
    state : State
112
        The state.
113
    transient_storage : TransientStorage
114
        The transient storage of the transaction.
115
116
    """
117
    state._snapshots.pop()
118
    if not state._snapshots:
119
        state.created_accounts.clear()
120
121
    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:
127
    """
128
    Rollback a state transaction, resetting the state to the point when the
129
    corresponding `begin_transaction()` call was made.
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._main_trie, state._storage_tries = state._snapshots.pop()
140
    if not state._snapshots:
141
        state.created_accounts.clear()
142
143
    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:
147
    """
148
    Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there
149
    is no account at the address.
150
151
    Use `get_account_optional()` if you care about the difference between a
152
    non-existent account and `EMPTY_ACCOUNT`.
153
154
    Parameters
155
    ----------
156
    state: `State`
157
        The state
158
    address : `Address`
159
        Address to lookup.
160
161
    Returns
162
    -------
163
    account : `Account`
164
        Account at address.
165
166
    """
167
    account = get_account_optional(state, address)
168
    if isinstance(account, Account):
169
        return account
170
    else:
171
        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]:
175
    """
176
    Get the `Account` object at an address. Returns `None` (rather than
177
    `EMPTY_ACCOUNT`) if there is no account at the address.
178
179
    Parameters
180
    ----------
181
    state: `State`
182
        The state
183
    address : `Address`
184
        Address to lookup.
185
186
    Returns
187
    -------
188
    account : `Account`
189
        Account at address.
190
191
    """
192
    account = trie_get(state._main_trie, address)
193
    return account

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:
199
    """
200
    Set the `Account` object at an address. Setting to `None` deletes
201
    the account (but not its storage, see `destroy_account()`).
202
203
    Parameters
204
    ----------
205
    state: `State`
206
        The state
207
    address : `Address`
208
        Address to set.
209
    account : `Account`
210
        Account to set at address.
211
212
    """
213
    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:
217
    """
218
    Completely remove the account at `address` and all of its storage.
219
220
    This function is made available exclusively for the `SELFDESTRUCT`
221
    opcode. It is expected that `SELFDESTRUCT` will be disabled in a future
222
    hardfork and this function will be removed.
223
224
    Parameters
225
    ----------
226
    state: `State`
227
        The state
228
    address : `Address`
229
        Address of account to destroy.
230
231
    """
232
    destroy_storage(state, address)
233
    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:
237
    """
238
    Completely remove the storage at `address`.
239
240
    Parameters
241
    ----------
242
    state: `State`
243
        The state
244
    address : `Address`
245
        Address of account whose storage is to be deleted.
246
247
    """
248
    if address in state._storage_tries:
249
        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:
253
    """
254
    Mark an account as having been created in the current transaction.
255
    This information is used by `get_storage_original()` to handle an obscure
256
    edgecase, and to respect the constraints added to SELFDESTRUCT by
257
    EIP-6780.
258
259
    The marker is not removed even if the account creation reverts. Since the
260
    account cannot have had code prior to its creation and can't call
261
    `get_storage_original()`, this is harmless.
262
263
    Parameters
264
    ----------
265
    state: `State`
266
        The state
267
    address : `Address`
268
        Address of the account that has been created.
269
270
    """
271
    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:
275
    """
276
    Get a value at a storage key on an account. Returns `U256(0)` if the
277
    storage key has not been set previously.
278
279
    Parameters
280
    ----------
281
    state: `State`
282
        The state
283
    address : `Address`
284
        Address of the account.
285
    key : `Bytes`
286
        Key to lookup.
287
288
    Returns
289
    -------
290
    value : `U256`
291
        Value at the key.
292
293
    """
294
    trie = state._storage_tries.get(address)
295
    if trie is None:
296
        return U256(0)
297
298
    value = trie_get(trie, key)
299
300
    assert isinstance(value, U256)
301
    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:
307
    """
308
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
309
    the key.
310
311
    Parameters
312
    ----------
313
    state: `State`
314
        The state
315
    address : `Address`
316
        Address of the account.
317
    key : `Bytes`
318
        Key to set.
319
    value : `U256`
320
        Value to set at the key.
321
322
    """
323
    assert trie_get(state._main_trie, address) is not None
324
325
    trie = state._storage_tries.get(address)
326
    if trie is None:
327
        trie = Trie(secured=True, default=U256(0))
328
        state._storage_tries[address] = trie
329
    trie_set(trie, key, value)
330
    if trie._data == {}:
331
        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:
335
    """
336
    Calculate the storage root of an account.
337
338
    Parameters
339
    ----------
340
    state:
341
        The state
342
    address :
343
        Address of the account.
344
345
    Returns
346
    -------
347
    root : `Root`
348
        Storage root of the account.
349
350
    """
351
    assert not state._snapshots
352
    if address in state._storage_tries:
353
        return root(state._storage_tries[address])
354
    else:
355
        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:
359
    """
360
    Calculate the state root.
361
362
    Parameters
363
    ----------
364
    state:
365
        The current state.
366
367
    Returns
368
    -------
369
    root : `Root`
370
        The state root.
371
372
    """
373
    assert not state._snapshots
374
375
    def get_storage_root(address: Address) -> Root:
376
        return storage_root(state, address)
377
378
    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:
382
    """
383
    Checks if an account exists in the state trie.
384
385
    Parameters
386
    ----------
387
    state:
388
        The state
389
    address:
390
        Address of the account that needs to be checked.
391
392
    Returns
393
    -------
394
    account_exists : `bool`
395
        True if account exists in the state trie, False otherwise
396
397
    """
398
    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:
402
    """
403
    Checks if an account has non zero nonce or non empty code.
404
405
    Parameters
406
    ----------
407
    state:
408
        The state
409
    address:
410
        Address of the account that needs to be checked.
411
412
    Returns
413
    -------
414
    has_code_or_nonce : `bool`
415
        True if the account has non zero nonce or non empty code,
416
        False otherwise.
417
418
    """
419
    account = get_account(state, address)
420
    return account.nonce != Uint(0) or account.code != b""

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:
424
    """
425
    Checks if an account has storage.
426
427
    Parameters
428
    ----------
429
    state:
430
        The state
431
    address:
432
        Address of the account that needs to be checked.
433
434
    Returns
435
    -------
436
    has_storage : `bool`
437
        True if the account has storage, False otherwise.
438
439
    """
440
    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:
444
    """
445
    Check whether an account is both in the state and non-empty.
446
447
    Parameters
448
    ----------
449
    state:
450
        The state
451
    address:
452
        Address of the account that needs to be checked.
453
454
    Returns
455
    -------
456
    is_alive : `bool`
457
        True if the account is alive.
458
459
    """
460
    account = get_account_optional(state, address)
461
    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:
467
    """
468
    Modify an `Account` in the `State`. If, after modification, the account
469
    exists and has zero nonce, empty code, and zero balance, it is destroyed.
470
    """
471
    set_account(state, address, modify(get_account(state, address), f))
472
473
    account = get_account_optional(state, address)
474
    account_exists_and_is_empty = (
475
        account is not None
476
        and account.nonce == Uint(0)
477
        and account.code == b""
478
        and account.balance == 0
479
    )
480
481
    if account_exists_and_is_empty:
482
        destroy_account(state, address)

move_ether

Move funds between accounts.

def move_ether(state: State, ​​sender_address: Address, ​​recipient_address: Address, ​​amount: U256) -> None:
491
    """
492
    Move funds between accounts.
493
    """
494
495
    def reduce_sender_balance(sender: Account) -> None:
496
        if sender.balance < amount:
497
            raise AssertionError
498
        sender.balance -= amount
499
500
    def increase_recipient_balance(recipient: Account) -> None:
501
        recipient.balance += amount
502
503
    modify_state(state, sender_address, reduce_sender_balance)
504
    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 set in balance.

def set_account_balance(state: State, ​​address: Address, ​​amount: U256) -> None:
508
    """
509
    Sets the balance of an account.
510
511
    Parameters
512
    ----------
513
    state:
514
        The current state.
515
516
    address:
517
        Address of the account whose nonce needs to be incremented.
518
519
    amount:
520
        The amount that needs to set in balance.
521
522
    """
523
524
    def set_balance(account: Account) -> None:
525
        account.balance = amount
526
527
    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:
531
    """
532
    Increments the nonce of an account.
533
534
    Parameters
535
    ----------
536
    state:
537
        The current state.
538
539
    address:
540
        Address of the account whose nonce needs to be incremented.
541
542
    """
543
544
    def increase_nonce(sender: Account) -> None:
545
        sender.nonce += Uint(1)
546
547
    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 update.

code: The bytecode that needs to be set.

def set_code(state: State, ​​address: Address, ​​code: Bytes) -> None:
551
    """
552
    Sets Account code.
553
554
    Parameters
555
    ----------
556
    state:
557
        The current state.
558
559
    address:
560
        Address of the account whose code needs to be update.
561
562
    code:
563
        The bytecode that needs to be set.
564
565
    """
566
567
    def write_code(sender: Account) -> None:
568
        sender.code = code
569
570
    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:
574
    """
575
    Get the original value in a storage slot i.e. the value before the current
576
    transaction began. This function reads the value from the snapshots taken
577
    before executing the transaction.
578
579
    Parameters
580
    ----------
581
    state:
582
        The current state.
583
    address:
584
        Address of the account to read the value from.
585
    key:
586
        Key of the storage slot.
587
588
    """
589
    # In the transaction where an account is created, its preexisting storage
590
    # is ignored.
591
    if address in state.created_accounts:
592
        return U256(0)
593
594
    _, original_trie = state._snapshots[0]
595
    original_account_trie = original_trie.get(address)
596
597
    if original_account_trie is None:
598
        original_value = U256(0)
599
    else:
600
        original_value = trie_get(original_account_trie, key)
601
602
    assert isinstance(original_value, U256)
603
604
    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:
610
    """
611
    Get a value at a storage key on an account from transient storage.
612
    Returns `U256(0)` if the storage key has not been set previously.
613
614
    Parameters
615
    ----------
616
    transient_storage: `TransientStorage`
617
        The transient storage
618
    address : `Address`
619
        Address of the account.
620
    key : `Bytes`
621
        Key to lookup.
622
623
    Returns
624
    -------
625
    value : `U256`
626
        Value at the key.
627
628
    """
629
    trie = transient_storage._tries.get(address)
630
    if trie is None:
631
        return U256(0)
632
633
    value = trie_get(trie, key)
634
635
    assert isinstance(value, U256)
636
    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:
645
    """
646
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
647
    the key.
648
649
    Parameters
650
    ----------
651
    transient_storage: `TransientStorage`
652
        The transient storage
653
    address : `Address`
654
        Address of the account.
655
    key : `Bytes`
656
        Key to set.
657
    value : `U256`
658
        Value to set at the key.
659
660
    """
661
    trie = transient_storage._tries.get(address)
662
    if trie is None:
663
        trie = Trie(secured=True, default=U256(0))
664
        transient_storage._tries[address] = trie
665
    trie_set(trie, key, value)
666
    if trie._data == {}:
667
        del transient_storage._tries[address]