ethereum.muir_glacier.stateethereum.berlin.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)

close_state

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

def close_state(state: State) -> None:
52
    """
53
    Free resources held by the state. Used by optimized implementations to
54
    release file descriptors.
55
    """
56
    del state._main_trie
57
    del state._storage_tries
58
    del state._snapshots
59
    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.

def begin_transaction(state: State) -> None:
63
    """
64
    Start a state transaction.
65
66
    Transactions are entirely implicit and can be nested. It is not possible to
67
    calculate the state root during a transaction.
68
69
    Parameters
70
    ----------
71
    state : State
72
        The state.
73
    """
74
    state._snapshots.append(
75
        (
76
            copy_trie(state._main_trie),
77
            {k: copy_trie(t) for (k, t) in state._storage_tries.items()},
78
        )
79
    )

commit_transaction

Commit a state transaction.

Parameters

state : State The state.

def commit_transaction(state: State) -> None:
83
    """
84
    Commit a state transaction.
85
86
    Parameters
87
    ----------
88
    state : State
89
        The state.
90
    """
91
    state._snapshots.pop()
92
    if not state._snapshots:
93
        state.created_accounts.clear()

rollback_transaction

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

Parameters

state : State The state.

def rollback_transaction(state: State) -> None:
97
    """
98
    Rollback a state transaction, resetting the state to the point when the
99
    corresponding `start_transaction()` call was made.
100
101
    Parameters
102
    ----------
103
    state : State
104
        The state.
105
    """
106
    state._main_trie, state._storage_tries = state._snapshots.pop()
107
    if not state._snapshots:
108
        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: Address) -> Account:
112
    """
113
    Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there
114
    is no account at the address.
115
116
    Use `get_account_optional()` if you care about the difference between a
117
    non-existent account and `EMPTY_ACCOUNT`.
118
119
    Parameters
120
    ----------
121
    state: `State`
122
        The state
123
    address : `Address`
124
        Address to lookup.
125
126
    Returns
127
    -------
128
    account : `Account`
129
        Account at address.
130
    """
131
    account = get_account_optional(state, address)
132
    if isinstance(account, Account):
133
        return account
134
    else:
135
        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]:
139
    """
140
    Get the `Account` object at an address. Returns `None` (rather than
141
    `EMPTY_ACCOUNT`) if there is no account at the address.
142
143
    Parameters
144
    ----------
145
    state: `State`
146
        The state
147
    address : `Address`
148
        Address to lookup.
149
150
    Returns
151
    -------
152
    account : `Account`
153
        Account at address.
154
    """
155
    account = trie_get(state._main_trie, address)
156
    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:
162
    """
163
    Set the `Account` object at an address. Setting to `None` deletes
164
    the account (but not its storage, see `destroy_account()`).
165
166
    Parameters
167
    ----------
168
    state: `State`
169
        The state
170
    address : `Address`
171
        Address to set.
172
    account : `Account`
173
        Account to set at address.
174
    """
175
    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:
179
    """
180
    Completely remove the account at `address` and all of its storage.
181
182
    This function is made available exclusively for the `SELFDESTRUCT`
183
    opcode. It is expected that `SELFDESTRUCT` will be disabled in a future
184
    hardfork and this function will be removed.
185
186
    Parameters
187
    ----------
188
    state: `State`
189
        The state
190
    address : `Address`
191
        Address of account to destroy.
192
    """
193
    destroy_storage(state, address)
194
    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:
198
    """
199
    Completely remove the storage at `address`.
200
201
    Parameters
202
    ----------
203
    state: `State`
204
        The state
205
    address : `Address`
206
        Address of account whose storage is to be deleted.
207
    """
208
    if address in state._storage_tries:
209
        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: Address) -> None:
213
    """
214
    Mark an account as having been created in the current transaction.
215
    This information is used by `get_storage_original()` to handle an obscure
216
    edgecase.
217
218
    The marker is not removed even if the account creation reverts. Since the
219
    account cannot have had code prior to its creation and can't call
220
    `get_storage_original()`, this is harmless.
221
222
    Parameters
223
    ----------
224
    state: `State`
225
        The state
226
    address : `Address`
227
        Address of the account that has been created.
228
    """
229
    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:
233
    """
234
    Get a value at a storage key on an account. Returns `U256(0)` if the
235
    storage key has not been set previously.
236
237
    Parameters
238
    ----------
239
    state: `State`
240
        The state
241
    address : `Address`
242
        Address of the account.
243
    key : `Bytes`
244
        Key to lookup.
245
246
    Returns
247
    -------
248
    value : `U256`
249
        Value at the key.
250
    """
251
    trie = state._storage_tries.get(address)
252
    if trie is None:
253
        return U256(0)
254
255
    value = trie_get(trie, key)
256
257
    assert isinstance(value, U256)
258
    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:
264
    """
265
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
266
    the key.
267
268
    Parameters
269
    ----------
270
    state: `State`
271
        The state
272
    address : `Address`
273
        Address of the account.
274
    key : `Bytes`
275
        Key to set.
276
    value : `U256`
277
        Value to set at the key.
278
    """
279
    assert trie_get(state._main_trie, address) is not None
280
281
    trie = state._storage_tries.get(address)
282
    if trie is None:
283
        trie = Trie(secured=True, default=U256(0))
284
        state._storage_tries[address] = trie
285
    trie_set(trie, key, value)
286
    if trie._data == {}:
287
        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:
291
    """
292
    Calculate the storage root of an account.
293
294
    Parameters
295
    ----------
296
    state:
297
        The state
298
    address :
299
        Address of the account.
300
301
    Returns
302
    -------
303
    root : `Root`
304
        Storage root of the account.
305
    """
306
    assert not state._snapshots
307
    if address in state._storage_tries:
308
        return root(state._storage_tries[address])
309
    else:
310
        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:
314
    """
315
    Calculate the state root.
316
317
    Parameters
318
    ----------
319
    state:
320
        The current state.
321
322
    Returns
323
    -------
324
    root : `Root`
325
        The state root.
326
    """
327
    assert not state._snapshots
328
329
    def get_storage_root(address: Address) -> Root:
330
        return storage_root(state, address)
331
332
    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:
336
    """
337
    Checks if an account exists in the state trie
338
339
    Parameters
340
    ----------
341
    state:
342
        The state
343
    address:
344
        Address of the account that needs to be checked.
345
346
    Returns
347
    -------
348
    account_exists : `bool`
349
        True if account exists in the state trie, False otherwise
350
    """
351
    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:
355
    """
356
    Checks if an account has non zero nonce or non empty code
357
358
    Parameters
359
    ----------
360
    state:
361
        The state
362
    address:
363
        Address of the account that needs to be checked.
364
365
    Returns
366
    -------
367
    has_code_or_nonce : `bool`
368
        True if the account has non zero nonce or non empty code,
369
        False otherwise.
370
    """
371
    account = get_account(state, address)
372
    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:
376
    """
377
    Checks if an account has storage.
378
379
    Parameters
380
    ----------
381
    state:
382
        The state
383
    address:
384
        Address of the account that needs to be checked.
385
386
    Returns
387
    -------
388
    has_storage : `bool`
389
        True if the account has storage, False otherwise.
390
    """
391
    return address in state._storage_tries

is_account_empty

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

Parameters

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

Returns

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

def is_account_empty(state: State, ​​address: Address) -> bool:
395
    """
396
    Checks if an account has zero nonce, empty code and zero balance.
397
398
    Parameters
399
    ----------
400
    state:
401
        The state
402
    address:
403
        Address of the account that needs to be checked.
404
405
    Returns
406
    -------
407
    is_empty : `bool`
408
        True if an account has zero nonce, empty code and zero balance,
409
        False otherwise.
410
    """
411
    account = get_account(state, address)
412
    return (
413
        account.nonce == Uint(0)
414
        and account.code == b""
415
        and account.balance == 0
416
    )

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:
420
    """
421
    Checks if an account exists and has zero nonce, empty code and zero
422
    balance.
423
424
    Parameters
425
    ----------
426
    state:
427
        The state
428
    address:
429
        Address of the account that needs to be checked.
430
431
    Returns
432
    -------
433
    exists_and_is_empty : `bool`
434
        True if an account exists and has zero nonce, empty code and zero
435
        balance, False otherwise.
436
    """
437
    account = get_account_optional(state, address)
438
    return (
439
        account is not None
440
        and account.nonce == Uint(0)
441
        and account.code == b""
442
        and account.balance == 0
443
    )

is_account_alive

Check whether is 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:
447
    """
448
    Check whether is an account is both in the state and non empty.
449
450
    Parameters
451
    ----------
452
    state:
453
        The state
454
    address:
455
        Address of the account that needs to be checked.
456
457
    Returns
458
    -------
459
    is_alive : `bool`
460
        True if the account is alive.
461
    """
462
    account = get_account_optional(state, address)
463
    return account is not None and account != EMPTY_ACCOUNT

modify_state

Modify an Account in the State.

def modify_state(state: State, ​​address: Address, ​​f: Callable[[Account], None]) -> None:
469
    """
470
    Modify an `Account` in the `State`.
471
    """
472
    set_account(state, address, modify(get_account(state, address), f))

move_ether

Move funds between accounts.

def move_ether(state: State, ​​sender_address: Address, ​​recipient_address: Address, ​​amount: U256) -> None:
481
    """
482
    Move funds between accounts.
483
    """
484
485
    def reduce_sender_balance(sender: Account) -> None:
486
        if sender.balance < amount:
487
            raise AssertionError
488
        sender.balance -= amount
489
490
    def increase_recipient_balance(recipient: Account) -> None:
491
        recipient.balance += amount
492
493
    modify_state(state, sender_address, reduce_sender_balance)
494
    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:
498
    """
499
    Sets the balance of an account.
500
501
    Parameters
502
    ----------
503
    state:
504
        The current state.
505
506
    address:
507
        Address of the account whose nonce needs to be incremented.
508
509
    amount:
510
        The amount that needs to set in balance.
511
    """
512
513
    def set_balance(account: Account) -> None:
514
        account.balance = amount
515
516
    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 need to initialised.

def touch_account(state: State, ​​address: Address) -> None:
520
    """
521
    Initializes an account to state.
522
523
    Parameters
524
    ----------
525
    state:
526
        The current state.
527
528
    address:
529
        The address of the account that need to initialised.
530
    """
531
    if not account_exists(state, address):
532
        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: Address) -> None:
536
    """
537
    Increments the nonce of an account.
538
539
    Parameters
540
    ----------
541
    state:
542
        The current state.
543
544
    address:
545
        Address of the account whose nonce needs to be incremented.
546
    """
547
548
    def increase_nonce(sender: Account) -> None:
549
        sender.nonce += Uint(1)
550
551
    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:
555
    """
556
    Sets Account code.
557
558
    Parameters
559
    ----------
560
    state:
561
        The current state.
562
563
    address:
564
        Address of the account whose code needs to be update.
565
566
    code:
567
        The bytecode that needs to be set.
568
    """
569
570
    def write_code(sender: Account) -> None:
571
        sender.code = code
572
573
    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:
577
    """
578
    Add newly created ether to an account.
579
580
    Parameters
581
    ----------
582
    state:
583
        The current state.
584
    address:
585
        Address of the account to which ether is added.
586
    amount:
587
        The amount of ether to be added to the account of interest.
588
    """
589
590
    def increase_balance(account: Account) -> None:
591
        account.balance += amount
592
593
    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: Address, ​​key: Bytes32) -> U256:
597
    """
598
    Get the original value in a storage slot i.e. the value before the current
599
    transaction began. This function reads the value from the snapshots taken
600
    before executing the transaction.
601
602
    Parameters
603
    ----------
604
    state:
605
        The current state.
606
    address:
607
        Address of the account to read the value from.
608
    key:
609
        Key of the storage slot.
610
    """
611
    # In the transaction where an account is created, its preexisting storage
612
    # is ignored.
613
    if address in state.created_accounts:
614
        return U256(0)
615
616
    _, original_trie = state._snapshots[0]
617
    original_account_trie = original_trie.get(address)
618
619
    if original_account_trie is None:
620
        original_value = U256(0)
621
    else:
622
        original_value = trie_get(original_account_trie, key)
623
624
    assert isinstance(original_value, U256)
625
626
    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:
632
    """
633
    Destroy all touched accounts that are empty.
634
    Parameters
635
    ----------
636
    state: `State`
637
        The current state.
638
    touched_accounts: `Iterable[Address]`
639
        All the accounts that have been touched in the current transaction.
640
    """
641
    for address in touched_accounts:
642
        if account_exists_and_is_empty(state, address):
643
            destroy_account(state, address)