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.

32
@dataclass
class State:

_main_trie

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

_storage_tries

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

_snapshots

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

_code_store

50
    _code_store: Dict[Hash32, Bytes] = field(
51
        default_factory=dict, compare=False
52
    )

close_state

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

def close_state(state: State) -> None:
56
    """
57
    Free resources held by the state. Used by optimized implementations to
58
    release file descriptors.
59
    """
60
    del state._main_trie
61
    del state._storage_tries
62
    del state._snapshots
63
    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:
67
    """
68
    Start a state transaction.
69
70
    Transactions are entirely implicit and can be nested. It is not possible to
71
    calculate the state root during a transaction.
72
73
    Parameters
74
    ----------
75
    state : State
76
        The state.
77
78
    """
79
    state._snapshots.append(
80
        (
81
            copy_trie(state._main_trie),
82
            {k: copy_trie(t) for (k, t) in state._storage_tries.items()},
83
        )
84
    )

commit_transaction

Commit a state transaction.

Parameters

state : State The state.

def commit_transaction(state: State) -> None:
88
    """
89
    Commit a state transaction.
90
91
    Parameters
92
    ----------
93
    state : State
94
        The state.
95
96
    """
97
    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:
101
    """
102
    Rollback a state transaction, resetting the state to the point when the
103
    corresponding `begin_transaction()` call was made.
104
105
    Parameters
106
    ----------
107
    state : State
108
        The state.
109
110
    """
111
    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:
115
    """
116
    Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there
117
    is no account at the address.
118
119
    Use `get_account_optional()` if you care about the difference between a
120
    non-existent account and `EMPTY_ACCOUNT`.
121
122
    Parameters
123
    ----------
124
    state: `State`
125
        The state
126
    address : `Address`
127
        Address to lookup.
128
129
    Returns
130
    -------
131
    account : `Account`
132
        Account at address.
133
134
    """
135
    account = get_account_optional(state, address)
136
    if isinstance(account, Account):
137
        return account
138
    else:
139
        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]:
143
    """
144
    Get the `Account` object at an address. Returns `None` (rather than
145
    `EMPTY_ACCOUNT`) if there is no account at the address.
146
147
    Parameters
148
    ----------
149
    state: `State`
150
        The state
151
    address : `Address`
152
        Address to lookup.
153
154
    Returns
155
    -------
156
    account : `Account`
157
        Account at address.
158
159
    """
160
    account = trie_get(state._main_trie, address)
161
    return account

get_code

Get the bytecode for a given code hash.

def get_code(state: State, ​​code_hash: Hash32) -> Bytes:
165
    """
166
    Get the bytecode for a given code hash.
167
    """
168
    if code_hash == EMPTY_CODE_HASH:
169
        return b""
170
    return state._code_store[code_hash]

store_code

Store bytecode in State.

def store_code(state: State, ​​code: Bytes) -> Hash32:
174
    """
175
    Store bytecode in ``State``.
176
    """
177
    code_hash = keccak256(code)
178
    if code_hash != EMPTY_CODE_HASH:
179
        state._code_store[code_hash] = code
180
    return code_hash

set_account

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

Parameters

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

def set_account(state: State, ​​address: Address, ​​account: Optional[Account]) -> None:
186
    """
187
    Set the `Account` object at an address. Setting to `None` deletes
188
    the account (but not its storage, see `destroy_account()`).
189
190
    Parameters
191
    ----------
192
    state: `State`
193
        The state
194
    address : `Address`
195
        Address to set.
196
    account : `Account`
197
        Account to set at address.
198
199
    """
200
    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:
204
    """
205
    Completely remove the account at `address` and all of its storage.
206
207
    This function is made available exclusively for the `SELFDESTRUCT`
208
    opcode. It is expected that `SELFDESTRUCT` will be disabled in a future
209
    hardfork and this function will be removed.
210
211
    Parameters
212
    ----------
213
    state: `State`
214
        The state
215
    address : `Address`
216
        Address of account to destroy.
217
218
    """
219
    destroy_storage(state, address)
220
    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:
224
    """
225
    Completely remove the storage at `address`.
226
227
    Parameters
228
    ----------
229
    state: `State`
230
        The state
231
    address : `Address`
232
        Address of account whose storage is to be deleted.
233
234
    """
235
    if address in state._storage_tries:
236
        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:
240
    """
241
    Get a value at a storage key on an account. Returns `U256(0)` if the
242
    storage key has not been set previously.
243
244
    Parameters
245
    ----------
246
    state: `State`
247
        The state
248
    address : `Address`
249
        Address of the account.
250
    key : `Bytes`
251
        Key to lookup.
252
253
    Returns
254
    -------
255
    value : `U256`
256
        Value at the key.
257
258
    """
259
    trie = state._storage_tries.get(address)
260
    if trie is None:
261
        return U256(0)
262
263
    value = trie_get(trie, key)
264
265
    assert isinstance(value, U256)
266
    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:
272
    """
273
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
274
    the key.
275
276
    Parameters
277
    ----------
278
    state: `State`
279
        The state
280
    address : `Address`
281
        Address of the account.
282
    key : `Bytes`
283
        Key to set.
284
    value : `U256`
285
        Value to set at the key.
286
287
    """
288
    assert trie_get(state._main_trie, address) is not None
289
290
    trie = state._storage_tries.get(address)
291
    if trie is None:
292
        trie = Trie(secured=True, default=U256(0))
293
        state._storage_tries[address] = trie
294
    trie_set(trie, key, value)
295
    if trie._data == {}:
296
        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:
300
    """
301
    Calculate the storage root of an account.
302
303
    Parameters
304
    ----------
305
    state:
306
        The state
307
    address :
308
        Address of the account.
309
310
    Returns
311
    -------
312
    root : `Root`
313
        Storage root of the account.
314
315
    """
316
    assert not state._snapshots
317
    if address in state._storage_tries:
318
        return root(state._storage_tries[address])
319
    else:
320
        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:
324
    """
325
    Calculate the state root.
326
327
    Parameters
328
    ----------
329
    state:
330
        The current state.
331
332
    Returns
333
    -------
334
    root : `Root`
335
        The state root.
336
337
    """
338
    assert not state._snapshots
339
340
    def get_storage_root(address: Address) -> Root:
341
        return storage_root(state, address)
342
343
    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:
347
    """
348
    Checks if an account exists in the state trie.
349
350
    Parameters
351
    ----------
352
    state:
353
        The state
354
    address:
355
        Address of the account that needs to be checked.
356
357
    Returns
358
    -------
359
    account_exists : `bool`
360
        True if account exists in the state trie, False otherwise
361
362
    """
363
    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:
367
    """
368
    Checks if an account has non-zero nonce or non-empty code.
369
370
    Parameters
371
    ----------
372
    state:
373
        The state
374
    address:
375
        Address of the account that needs to be checked.
376
377
    Returns
378
    -------
379
    has_code_or_nonce : `bool`
380
        True if the account has non-zero nonce or non-empty code,
381
        False otherwise.
382
383
    """
384
    account = get_account(state, address)
385
    return account.nonce != Uint(0) or account.code_hash != EMPTY_CODE_HASH

account_has_storage

Checks if an account has storage.

Parameters

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

Returns

has_storage : bool True if the account has storage, False otherwise.

def account_has_storage(state: State, ​​address: Address) -> bool:
389
    """
390
    Checks if an account has storage.
391
392
    Parameters
393
    ----------
394
    state:
395
        The state
396
    address:
397
        Address of the account that needs to be checked.
398
399
    Returns
400
    -------
401
    has_storage : `bool`
402
        True if the account has storage, False otherwise.
403
404
    """
405
    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:
409
    """
410
    Checks if an account exists and has zero nonce, empty code and zero
411
    balance.
412
413
    Parameters
414
    ----------
415
    state:
416
        The state
417
    address:
418
        Address of the account that needs to be checked.
419
420
    Returns
421
    -------
422
    exists_and_is_empty : `bool`
423
        True if an account exists and has zero nonce, empty code and zero
424
        balance, False otherwise.
425
426
    """
427
    account = get_account_optional(state, address)
428
    return (
429
        account is not None
430
        and account.nonce == Uint(0)
431
        and account.code_hash == EMPTY_CODE_HASH
432
        and account.balance == 0
433
    )

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:
437
    """
438
    Check whether an account is both in the state and non-empty.
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
    is_alive : `bool`
450
        True if the account is alive.
451
452
    """
453
    account = get_account_optional(state, address)
454
    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:
460
    """
461
    Modify an `Account` in the `State`.
462
    """
463
    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:
472
    """
473
    Move funds between accounts.
474
    """
475
476
    def reduce_sender_balance(sender: Account) -> None:
477
        if sender.balance < amount:
478
            raise AssertionError
479
        sender.balance -= amount
480
481
    def increase_recipient_balance(recipient: Account) -> None:
482
        recipient.balance += amount
483
484
    modify_state(state, sender_address, reduce_sender_balance)
485
    modify_state(state, recipient_address, increase_recipient_balance)

set_account_balance

Sets the balance of an account.

Parameters

state: The current state.

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

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

def set_account_balance(state: State, ​​address: Address, ​​amount: U256) -> None:
489
    """
490
    Sets the balance of an account.
491
492
    Parameters
493
    ----------
494
    state:
495
        The current state.
496
497
    address:
498
        Address of the account whose nonce needs to be incremented.
499
500
    amount:
501
        The amount that needs to be set in the balance.
502
503
    """
504
505
    def set_balance(account: Account) -> None:
506
        account.balance = amount
507
508
    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:
512
    """
513
    Initializes an account to state.
514
515
    Parameters
516
    ----------
517
    state:
518
        The current state.
519
520
    address:
521
        The address of the account that needs to be initialized.
522
523
    """
524
    if not account_exists(state, address):
525
        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:
529
    """
530
    Increments the nonce of an account.
531
532
    Parameters
533
    ----------
534
    state:
535
        The current state.
536
537
    address:
538
        Address of the account whose nonce needs to be incremented.
539
540
    """
541
542
    def increase_nonce(sender: Account) -> None:
543
        sender.nonce += Uint(1)
544
545
    modify_state(state, address, increase_nonce)

set_code

Sets Account code.

Parameters

state: The current state.

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

code: The bytecode that needs to be set.

def set_code(state: State, ​​address: Address, ​​code: Bytes) -> None:
549
    """
550
    Sets Account code.
551
552
    Parameters
553
    ----------
554
    state:
555
        The current state.
556
557
    address:
558
        Address of the account whose code needs to be updated.
559
560
    code:
561
        The bytecode that needs to be set.
562
563
    """
564
    code_hash = keccak256(code)
565
    if code_hash != EMPTY_CODE_HASH:
566
        state._code_store[code_hash] = code
567
568
    def write_code(sender: Account) -> None:
569
        sender.code_hash = code_hash
570
571
    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:
575
    """
576
    Add newly created ether to an account.
577
578
    Parameters
579
    ----------
580
    state:
581
        The current state.
582
    address:
583
        Address of the account to which ether is added.
584
    amount:
585
        The amount of ether to be added to the account of interest.
586
587
    """
588
589
    def increase_balance(account: Account) -> None:
590
        account.balance += amount
591
592
    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:
598
    """
599
    Destroy all touched accounts that are empty.
600
601
    Parameters
602
    ----------
603
    state: `State`
604
        The current state.
605
    touched_accounts: `Iterable[Address]`
606
        All the accounts that have been touched in the current transaction.
607
608
    """
609
    for address in touched_accounts:
610
        if account_exists_and_is_empty(state, address):
611
            destroy_account(state, address)