ethereum.forks.spurious_dragon.stateethereum.forks.byzantium.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)

close_state

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

def close_state(state: State) -> None:
51
    """
52
    Free resources held by the state. Used by optimized implementations to
53
    release file descriptors.
54
    """
55
    del state._main_trie
56
    del state._storage_tries
57
    del state._snapshots

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

commit_transaction

Commit a state transaction.

Parameters

state : State The state.

def commit_transaction(state: State) -> None:
82
    """
83
    Commit a state transaction.
84
85
    Parameters
86
    ----------
87
    state : State
88
        The state.
89
90
    """
91
    state._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.

def rollback_transaction(state: State) -> None:
95
    """
96
    Rollback a state transaction, resetting the state to the point when the
97
    corresponding `begin_transaction()` call was made.
98
99
    Parameters
100
    ----------
101
    state : State
102
        The state.
103
104
    """
105
    state._main_trie, state._storage_tries = state._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:
109
    """
110
    Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there
111
    is no account at the address.
112
113
    Use `get_account_optional()` if you care about the difference between a
114
    non-existent account and `EMPTY_ACCOUNT`.
115
116
    Parameters
117
    ----------
118
    state: `State`
119
        The state
120
    address : `Address`
121
        Address to lookup.
122
123
    Returns
124
    -------
125
    account : `Account`
126
        Account at address.
127
128
    """
129
    account = get_account_optional(state, address)
130
    if isinstance(account, Account):
131
        return account
132
    else:
133
        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]:
137
    """
138
    Get the `Account` object at an address. Returns `None` (rather than
139
    `EMPTY_ACCOUNT`) if there is no account at the address.
140
141
    Parameters
142
    ----------
143
    state: `State`
144
        The state
145
    address : `Address`
146
        Address to lookup.
147
148
    Returns
149
    -------
150
    account : `Account`
151
        Account at address.
152
153
    """
154
    account = trie_get(state._main_trie, address)
155
    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:
161
    """
162
    Set the `Account` object at an address. Setting to `None` deletes
163
    the account (but not its storage, see `destroy_account()`).
164
165
    Parameters
166
    ----------
167
    state: `State`
168
        The state
169
    address : `Address`
170
        Address to set.
171
    account : `Account`
172
        Account to set at address.
173
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
    """
194
    destroy_storage(state, address)
195
    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:
199
    """
200
    Completely remove the storage at `address`.
201
202
    Parameters
203
    ----------
204
    state: `State`
205
        The state
206
    address : `Address`
207
        Address of account whose storage is to be deleted.
208
209
    """
210
    if address in state._storage_tries:
211
        del state._storage_tries[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:
215
    """
216
    Get a value at a storage key on an account. Returns `U256(0)` if the
217
    storage key has not been set previously.
218
219
    Parameters
220
    ----------
221
    state: `State`
222
        The state
223
    address : `Address`
224
        Address of the account.
225
    key : `Bytes`
226
        Key to lookup.
227
228
    Returns
229
    -------
230
    value : `U256`
231
        Value at the key.
232
233
    """
234
    trie = state._storage_tries.get(address)
235
    if trie is None:
236
        return U256(0)
237
238
    value = trie_get(trie, key)
239
240
    assert isinstance(value, U256)
241
    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:
247
    """
248
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
249
    the key.
250
251
    Parameters
252
    ----------
253
    state: `State`
254
        The state
255
    address : `Address`
256
        Address of the account.
257
    key : `Bytes`
258
        Key to set.
259
    value : `U256`
260
        Value to set at the key.
261
262
    """
263
    assert trie_get(state._main_trie, address) is not None
264
265
    trie = state._storage_tries.get(address)
266
    if trie is None:
267
        trie = Trie(secured=True, default=U256(0))
268
        state._storage_tries[address] = trie
269
    trie_set(trie, key, value)
270
    if trie._data == {}:
271
        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:
275
    """
276
    Calculate the storage root of an account.
277
278
    Parameters
279
    ----------
280
    state:
281
        The state
282
    address :
283
        Address of the account.
284
285
    Returns
286
    -------
287
    root : `Root`
288
        Storage root of the account.
289
290
    """
291
    assert not state._snapshots
292
    if address in state._storage_tries:
293
        return root(state._storage_tries[address])
294
    else:
295
        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:
299
    """
300
    Calculate the state root.
301
302
    Parameters
303
    ----------
304
    state:
305
        The current state.
306
307
    Returns
308
    -------
309
    root : `Root`
310
        The state root.
311
312
    """
313
    assert not state._snapshots
314
315
    def get_storage_root(address: Address) -> Root:
316
        return storage_root(state, address)
317
318
    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:
322
    """
323
    Checks if an account exists in the state trie.
324
325
    Parameters
326
    ----------
327
    state:
328
        The state
329
    address:
330
        Address of the account that needs to be checked.
331
332
    Returns
333
    -------
334
    account_exists : `bool`
335
        True if account exists in the state trie, False otherwise
336
337
    """
338
    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:
342
    """
343
    Checks if an account has non zero nonce or non empty code.
344
345
    Parameters
346
    ----------
347
    state:
348
        The state
349
    address:
350
        Address of the account that needs to be checked.
351
352
    Returns
353
    -------
354
    has_code_or_nonce : `bool`
355
        True if the account has non zero nonce or non empty code,
356
        False otherwise.
357
358
    """
359
    account = get_account(state, address)
360
    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:
364
    """
365
    Checks if an account has storage.
366
367
    Parameters
368
    ----------
369
    state:
370
        The state
371
    address:
372
        Address of the account that needs to be checked.
373
374
    Returns
375
    -------
376
    has_storage : `bool`
377
        True if the account has storage, False otherwise.
378
379
    """
380
    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:
384
    """
385
    Checks if an account exists and has zero nonce, empty code and zero
386
    balance.
387
388
    Parameters
389
    ----------
390
    state:
391
        The state
392
    address:
393
        Address of the account that needs to be checked.
394
395
    Returns
396
    -------
397
    exists_and_is_empty : `bool`
398
        True if an account exists and has zero nonce, empty code and zero
399
        balance, False otherwise.
400
401
    """
402
    account = get_account_optional(state, address)
403
    return (
404
        account is not None
405
        and account.nonce == Uint(0)
406
        and account.code == b""
407
        and account.balance == 0
408
    )

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:
412
    """
413
    Check whether an account is both in the state and non-empty.
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
    is_alive : `bool`
425
        True if the account is alive.
426
427
    """
428
    account = get_account_optional(state, address)
429
    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:
435
    """
436
    Modify an `Account` in the `State`.
437
    """
438
    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:
447
    """
448
    Move funds between accounts.
449
    """
450
451
    def reduce_sender_balance(sender: Account) -> None:
452
        if sender.balance < amount:
453
            raise AssertionError
454
        sender.balance -= amount
455
456
    def increase_recipient_balance(recipient: Account) -> None:
457
        recipient.balance += amount
458
459
    modify_state(state, sender_address, reduce_sender_balance)
460
    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:
464
    """
465
    Sets the balance of an account.
466
467
    Parameters
468
    ----------
469
    state:
470
        The current state.
471
472
    address:
473
        Address of the account whose nonce needs to be incremented.
474
475
    amount:
476
        The amount that needs to set in balance.
477
478
    """
479
480
    def set_balance(account: Account) -> None:
481
        account.balance = amount
482
483
    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:
487
    """
488
    Initializes an account to state.
489
490
    Parameters
491
    ----------
492
    state:
493
        The current state.
494
495
    address:
496
        The address of the account that need to initialised.
497
498
    """
499
    if not account_exists(state, address):
500
        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:
504
    """
505
    Increments the nonce of an account.
506
507
    Parameters
508
    ----------
509
    state:
510
        The current state.
511
512
    address:
513
        Address of the account whose nonce needs to be incremented.
514
515
    """
516
517
    def increase_nonce(sender: Account) -> None:
518
        sender.nonce += Uint(1)
519
520
    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:
524
    """
525
    Sets Account code.
526
527
    Parameters
528
    ----------
529
    state:
530
        The current state.
531
532
    address:
533
        Address of the account whose code needs to be update.
534
535
    code:
536
        The bytecode that needs to be set.
537
538
    """
539
540
    def write_code(sender: Account) -> None:
541
        sender.code = code
542
543
    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:
547
    """
548
    Add newly created ether to an account.
549
550
    Parameters
551
    ----------
552
    state:
553
        The current state.
554
    address:
555
        Address of the account to which ether is added.
556
    amount:
557
        The amount of ether to be added to the account of interest.
558
559
    """
560
561
    def increase_balance(account: Account) -> None:
562
        account.balance += amount
563
564
    modify_state(state, address, increase_balance)

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:
570
    """
571
    Destroy all touched accounts that are empty.
572
573
    Parameters
574
    ----------
575
    state: `State`
576
        The current state.
577
    touched_accounts: `Iterable[Address]`
578
        All the accounts that have been touched in the current transaction.
579
580
    """
581
    for address in touched_accounts:
582
        if account_exists_and_is_empty(state, address):
583
            destroy_account(state, address)