ethereum.spurious_dragon.stateethereum.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
    state._snapshots.append(
73
        (
74
            copy_trie(state._main_trie),
75
            {k: copy_trie(t) for (k, t) in state._storage_tries.items()},
76
        )
77
    )

commit_transaction

Commit a state transaction.

Parameters

state : State The state.

def commit_transaction(state: State) -> None:
81
    """
82
    Commit a state transaction.
83
84
    Parameters
85
    ----------
86
    state : State
87
        The state.
88
    """
89
    state._snapshots.pop()

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:
93
    """
94
    Rollback a state transaction, resetting the state to the point when the
95
    corresponding `start_transaction()` call was made.
96
97
    Parameters
98
    ----------
99
    state : State
100
        The state.
101
    """
102
    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:
106
    """
107
    Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there
108
    is no account at the address.
109
110
    Use `get_account_optional()` if you care about the difference between a
111
    non-existent account and `EMPTY_ACCOUNT`.
112
113
    Parameters
114
    ----------
115
    state: `State`
116
        The state
117
    address : `Address`
118
        Address to lookup.
119
120
    Returns
121
    -------
122
    account : `Account`
123
        Account at address.
124
    """
125
    account = get_account_optional(state, address)
126
    if isinstance(account, Account):
127
        return account
128
    else:
129
        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]:
133
    """
134
    Get the `Account` object at an address. Returns `None` (rather than
135
    `EMPTY_ACCOUNT`) if there is no account at the address.
136
137
    Parameters
138
    ----------
139
    state: `State`
140
        The state
141
    address : `Address`
142
        Address to lookup.
143
144
    Returns
145
    -------
146
    account : `Account`
147
        Account at address.
148
    """
149
    account = trie_get(state._main_trie, address)
150
    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:
156
    """
157
    Set the `Account` object at an address. Setting to `None` deletes
158
    the account (but not its storage, see `destroy_account()`).
159
160
    Parameters
161
    ----------
162
    state: `State`
163
        The state
164
    address : `Address`
165
        Address to set.
166
    account : `Account`
167
        Account to set at address.
168
    """
169
    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:
173
    """
174
    Completely remove the account at `address` and all of its storage.
175
176
    This function is made available exclusively for the `SELFDESTRUCT`
177
    opcode. It is expected that `SELFDESTRUCT` will be disabled in a future
178
    hardfork and this function will be removed.
179
180
    Parameters
181
    ----------
182
    state: `State`
183
        The state
184
    address : `Address`
185
        Address of account to destroy.
186
    """
187
    destroy_storage(state, address)
188
    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:
192
    """
193
    Completely remove the storage at `address`.
194
195
    Parameters
196
    ----------
197
    state: `State`
198
        The state
199
    address : `Address`
200
        Address of account whose storage is to be deleted.
201
    """
202
    if address in state._storage_tries:
203
        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:
207
    """
208
    Get a value at a storage key on an account. Returns `U256(0)` if the
209
    storage key has not been set previously.
210
211
    Parameters
212
    ----------
213
    state: `State`
214
        The state
215
    address : `Address`
216
        Address of the account.
217
    key : `Bytes`
218
        Key to lookup.
219
220
    Returns
221
    -------
222
    value : `U256`
223
        Value at the key.
224
    """
225
    trie = state._storage_tries.get(address)
226
    if trie is None:
227
        return U256(0)
228
229
    value = trie_get(trie, key)
230
231
    assert isinstance(value, U256)
232
    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:
238
    """
239
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
240
    the key.
241
242
    Parameters
243
    ----------
244
    state: `State`
245
        The state
246
    address : `Address`
247
        Address of the account.
248
    key : `Bytes`
249
        Key to set.
250
    value : `U256`
251
        Value to set at the key.
252
    """
253
    assert trie_get(state._main_trie, address) is not None
254
255
    trie = state._storage_tries.get(address)
256
    if trie is None:
257
        trie = Trie(secured=True, default=U256(0))
258
        state._storage_tries[address] = trie
259
    trie_set(trie, key, value)
260
    if trie._data == {}:
261
        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:
265
    """
266
    Calculate the storage root of an account.
267
268
    Parameters
269
    ----------
270
    state:
271
        The state
272
    address :
273
        Address of the account.
274
275
    Returns
276
    -------
277
    root : `Root`
278
        Storage root of the account.
279
    """
280
    assert not state._snapshots
281
    if address in state._storage_tries:
282
        return root(state._storage_tries[address])
283
    else:
284
        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:
288
    """
289
    Calculate the state root.
290
291
    Parameters
292
    ----------
293
    state:
294
        The current state.
295
296
    Returns
297
    -------
298
    root : `Root`
299
        The state root.
300
    """
301
    assert not state._snapshots
302
303
    def get_storage_root(address: Address) -> Root:
304
        return storage_root(state, address)
305
306
    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:
310
    """
311
    Checks if an account exists in the state trie
312
313
    Parameters
314
    ----------
315
    state:
316
        The state
317
    address:
318
        Address of the account that needs to be checked.
319
320
    Returns
321
    -------
322
    account_exists : `bool`
323
        True if account exists in the state trie, False otherwise
324
    """
325
    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:
329
    """
330
    Checks if an account has non zero nonce or non empty code
331
332
    Parameters
333
    ----------
334
    state:
335
        The state
336
    address:
337
        Address of the account that needs to be checked.
338
339
    Returns
340
    -------
341
    has_code_or_nonce : `bool`
342
        True if the account has non zero nonce or non empty code,
343
        False otherwise.
344
    """
345
    account = get_account(state, address)
346
    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:
350
    """
351
    Checks if an account has storage.
352
353
    Parameters
354
    ----------
355
    state:
356
        The state
357
    address:
358
        Address of the account that needs to be checked.
359
360
    Returns
361
    -------
362
    has_storage : `bool`
363
        True if the account has storage, False otherwise.
364
    """
365
    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:
369
    """
370
    Checks if an account has zero nonce, empty code and zero balance.
371
372
    Parameters
373
    ----------
374
    state:
375
        The state
376
    address:
377
        Address of the account that needs to be checked.
378
379
    Returns
380
    -------
381
    is_empty : `bool`
382
        True if an account has zero nonce, empty code and zero balance,
383
        False otherwise.
384
    """
385
    account = get_account(state, address)
386
    return (
387
        account.nonce == Uint(0)
388
        and account.code == b""
389
        and account.balance == 0
390
    )

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:
394
    """
395
    Checks if an account exists and has zero nonce, empty code and zero
396
    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
    exists_and_is_empty : `bool`
408
        True if an account exists and has zero nonce, empty code and zero
409
        balance, False otherwise.
410
    """
411
    account = get_account_optional(state, address)
412
    return (
413
        account is not None
414
        and account.nonce == Uint(0)
415
        and account.code == b""
416
        and account.balance == 0
417
    )

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:
421
    """
422
    Check whether is an account is both in the state and non empty.
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
    is_alive : `bool`
434
        True if the account is alive.
435
    """
436
    account = get_account_optional(state, address)
437
    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:
443
    """
444
    Modify an `Account` in the `State`.
445
    """
446
    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:
455
    """
456
    Move funds between accounts.
457
    """
458
459
    def reduce_sender_balance(sender: Account) -> None:
460
        if sender.balance < amount:
461
            raise AssertionError
462
        sender.balance -= amount
463
464
    def increase_recipient_balance(recipient: Account) -> None:
465
        recipient.balance += amount
466
467
    modify_state(state, sender_address, reduce_sender_balance)
468
    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:
472
    """
473
    Sets the balance of an account.
474
475
    Parameters
476
    ----------
477
    state:
478
        The current state.
479
480
    address:
481
        Address of the account whose nonce needs to be incremented.
482
483
    amount:
484
        The amount that needs to set in balance.
485
    """
486
487
    def set_balance(account: Account) -> None:
488
        account.balance = amount
489
490
    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:
494
    """
495
    Initializes an account to state.
496
497
    Parameters
498
    ----------
499
    state:
500
        The current state.
501
502
    address:
503
        The address of the account that need to initialised.
504
    """
505
    if not account_exists(state, address):
506
        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:
510
    """
511
    Increments the nonce of an account.
512
513
    Parameters
514
    ----------
515
    state:
516
        The current state.
517
518
    address:
519
        Address of the account whose nonce needs to be incremented.
520
    """
521
522
    def increase_nonce(sender: Account) -> None:
523
        sender.nonce += Uint(1)
524
525
    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:
529
    """
530
    Sets Account code.
531
532
    Parameters
533
    ----------
534
    state:
535
        The current state.
536
537
    address:
538
        Address of the account whose code needs to be update.
539
540
    code:
541
        The bytecode that needs to be set.
542
    """
543
544
    def write_code(sender: Account) -> None:
545
        sender.code = code
546
547
    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:
551
    """
552
    Add newly created ether to an account.
553
554
    Parameters
555
    ----------
556
    state:
557
        The current state.
558
    address:
559
        Address of the account to which ether is added.
560
    amount:
561
        The amount of ether to be added to the account of interest.
562
    """
563
564
    def increase_balance(account: Account) -> None:
565
        account.balance += amount
566
567
    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:
573
    """
574
    Destroy all touched accounts that are empty.
575
    Parameters
576
    ----------
577
    state: `State`
578
        The current state.
579
    touched_accounts: `Iterable[Address]`
580
        All the accounts that have been touched in the current transaction.
581
    """
582
    for address in touched_accounts:
583
        if account_exists_and_is_empty(state, address):
584
            destroy_account(state, address)