State

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.

Module Contents

Classes

State

Contains all information that is preserved between transactions.

Functions

close_state

Free resources held by the state. Used by optimized implementations to

begin_transaction

Start a state transaction.

commit_transaction

Commit a state transaction.

rollback_transaction

Rollback a state transaction, resetting the state to the point when the

get_account

Get the Account object at an address. Returns EMPTY_ACCOUNT if there

get_account_optional

Get the Account object at an address. Returns None (rather than

set_account

Set the Account object at an address. Setting to None deletes

destroy_account

Completely remove the account at address and all of its storage.

destroy_storage

Completely remove the storage at address.

mark_account_created

Mark an account as having been created in the current transaction.

get_storage

Get a value at a storage key on an account. Returns U256(0) if the

set_storage

Set a value at a storage key on an account. Setting to U256(0) deletes

storage_root

Calculate the storage root of an account.

state_root

Calculate the state root.

account_exists

Checks if an account exists in the state trie

account_has_code_or_nonce

Checks if an account has non zero nonce or non empty code

is_account_empty

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

account_exists_and_is_empty

Checks if an account exists and has zero nonce, empty code and zero

is_account_alive

Check whether is an account is both in the state and non empty.

modify_state

Modify an Account in the State.

move_ether

Move funds between accounts.

set_account_balance

Sets the balance of an account.

touch_account

Initializes an account to state.

increment_nonce

Increments the nonce of an account.

set_code

Sets Account code.

create_ether

Add newly created ether to an account.

get_storage_original

Get the original value in a storage slot i.e. the value before the current

Module Details

State

Contains all information that is preserved between transactions.

class State
_main_trie :ethereum.constantinople.trie.Trie[ethereum.constantinople.fork_types.Address, Optional[ethereum.constantinople.fork_types.Account]]:ethereum.istanbul.trie.Trie[ethereum.istanbul.fork_types.Address, Optional[ethereum.istanbul.fork_types.Account]]
_storage_tries :Dict[ethereum.constantinople.fork_types.Address, ethereum.constantinople.trie.Trie[ethereum.base_types.Bytes,:Dict[ethereum.istanbul.fork_types.Address, ethereum.istanbul.trie.Trie[ethereum.base_types.Bytes, ethereum.base_types.U256]]
_snapshots :List[Tuple[ethereum.constantinople.trie.Trie[ethereum.constantinople.fork_types.Address, Optional[ethereum.constantinople.fork_types.Account]], Dict[ethereum.constantinople.fork_types.Address, ethereum.constantinople.trie.Trie[ethereum.base_types.Bytes,:List[Tuple[ethereum.istanbul.trie.Trie[ethereum.istanbul.fork_types.Address, Optional[ethereum.istanbul.fork_types.Account]], Dict[ethereum.istanbul.fork_types.Address, ethereum.istanbul.trie.Trie[ethereum.base_types.Bytes, ethereum.base_types.U256]]]]
_created_accounts :Set[ethereum.istanbul.fork_types.Address]

close_state

close_state(state)

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

def close_state(state: State) -> None:
    del state._main_trie
    del state._storage_tries
    del state._snapshots
del state._created_accounts

begin_transaction

begin_transaction(state)

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:
    state._snapshots.append(
        (
            copy_trie(state._main_trie),
            {k: copy_trie(t) for (k, t) in state._storage_tries.items()},
        )
    )

commit_transaction

commit_transaction(state)

Commit a state transaction.

Parameters

state (State) – The state.

def commit_transaction(state: State) -> None:
    state._snapshots.pop()
if not state._snapshots:
        state._created_accounts.clear()

rollback_transaction

rollback_transaction(state)

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:
    state._main_trie, state._storage_tries = state._snapshots.pop()
if not state._snapshots:
        state._created_accounts.clear()

get_account

get_account(state, address)

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 at address.

Return type

Account

def get_account(state: State, address: Address) -> Account:
    account = get_account_optional(state, address)
    if isinstance(account, Account):
        return account
    else:
        return EMPTY_ACCOUNT

get_account_optional

get_account_optional(state, address)

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 at address.

Return type

Account

def get_account_optional(state: State, address: Address) -> Optional[Account]:
    account = trie_get(state._main_trie, address)
    return account

set_account

set_account(state, address, 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:
    trie_set(state._main_trie, address, account)

destroy_account

destroy_account(state, address)

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:
    destroy_storage(state, address)
    set_account(state, address, None)

destroy_storage

destroy_storage(state, address)

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:
    if address in state._storage_tries:
        del state._storage_tries[address]

mark_account_created

mark_account_created(state, address)

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:
    state._created_accounts.add(address)

get_storage

get_storage(state, address, key)

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 – Value at the key.

Return type

U256

def get_storage(state: State, address: Address, key: Bytes) -> U256:
    trie = state._storage_tries.get(address)
    if trie is None:
        return U256(0)

    value = trie_get(trie, key)

    assert isinstance(value, U256)
    return value

set_storage

set_storage(state, address, key, value)

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: Bytes, value: U256
) -> None:
    assert trie_get(state._main_trie, address) is not None

    trie = state._storage_tries.get(address)
    if trie is None:
        trie = Trie(secured=True, default=U256(0))
        state._storage_tries[address] = trie
    trie_set(trie, key, value)
    if trie._data == {}:
        del state._storage_tries[address]

storage_root

storage_root(state, address)

Calculate the storage root of an account.

Parameters
  • state – The state

  • address – Address of the account.

Returns

root – Storage root of the account.

Return type

Root

def storage_root(state: State, address: Address) -> Root:
    assert not state._snapshots
    if address in state._storage_tries:
        return root(state._storage_tries[address])
    else:
        return EMPTY_TRIE_ROOT

state_root

state_root(state)

Calculate the state root.

Parameters

state – The current state.

Returns

root – The state root.

Return type

Root

def state_root(state: State) -> Root:
    assert not state._snapshots

    def get_storage_root(address: Address) -> Root:
        return storage_root(state, address)

    return root(state._main_trie, get_storage_root=get_storage_root)

account_exists

account_exists(state, address)

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 – True if account exists in the state trie, False otherwise

Return type

bool

def account_exists(state: State, address: Address) -> bool:
    return get_account_optional(state, address) is not None

account_has_code_or_nonce

account_has_code_or_nonce(state, address)

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 – True if if an account has non zero nonce or non empty code, False otherwise.

Return type

bool

def account_has_code_or_nonce(state: State, address: Address) -> bool:
    account = get_account(state, address)
    return account.nonce != Uint(0) or account.code != b""

is_account_empty

is_account_empty(state, address)

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 – True if if an account has zero nonce, empty code and zero balance, False otherwise.

Return type

bool

def is_account_empty(state: State, address: Address) -> bool:
    account = get_account(state, address)
    return (
        account.nonce == Uint(0)
        and account.code == b""
        and account.balance == 0
    )

account_exists_and_is_empty

account_exists_and_is_empty(state, address)

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 – True if an account exists and has zero nonce, empty code and zero balance, False otherwise.

Return type

bool

def account_exists_and_is_empty(state: State, address: Address) -> bool:
    account = get_account_optional(state, address)
    return (
        account is not None
        and account.nonce == Uint(0)
        and account.code == b""
        and account.balance == 0
    )

is_account_alive

is_account_alive(state, address)

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 – True if the account is alive.

Return type

bool

def is_account_alive(state: State, address: Address) -> bool:
    account = get_account_optional(state, address)
    if account is None:
        return False
    else:
        return not (
            account.nonce == Uint(0)
            and account.code == b""
            and account.balance == 0
        )

modify_state

modify_state(state, address, f)

Modify an Account in the State.

def modify_state(
    state: State, address: Address, f: Callable[[Account], None]
) -> None:
    set_account(state, address, modify(get_account(state, address), f))

move_ether

move_ether(state, sender_address, recipient_address, amount)

Move funds between accounts.

def move_ether(
    state: State,
    sender_address: Address,
    recipient_address: Address,
    amount: U256,
) -> None:

    def reduce_sender_balance(sender: Account) -> None:
        ensure(sender.balance >= amount, AssertionError)
        sender.balance -= amount

    def increase_recipient_balance(recipient: Account) -> None:
        recipient.balance += amount

    modify_state(state, sender_address, reduce_sender_balance)
    modify_state(state, recipient_address, increase_recipient_balance)

set_account_balance

set_account_balance(state, address, amount)

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:

    def set_balance(account: Account) -> None:
        account.balance = amount

    modify_state(state, address, set_balance)

touch_account

touch_account(state, address)

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:
    if not account_exists(state, address):
        set_account(state, address, EMPTY_ACCOUNT)

increment_nonce

increment_nonce(state, address)

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:

    def increase_nonce(sender: Account) -> None:
        sender.nonce += 1

    modify_state(state, address, increase_nonce)

set_code

set_code(state, address, 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:

    def write_code(sender: Account) -> None:
        sender.code = code

    modify_state(state, address, write_code)

create_ether

create_ether(state, address, amount)

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:

    def increase_balance(account: Account) -> None:
        account.balance += amount

    modify_state(state, address, increase_balance)

get_storage_original

get_storage_original(state, address, key)

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: Bytes) -> U256:
    # In the transaction where an account is created, its preexisting storage
    # is ignored.
    if address in state._created_accounts:
        return U256(0)

    _, original_trie = state._snapshots[0]
    original_account_trie = original_trie.get(address)

    if original_account_trie is None:
        original_value = U256(0)
    else:
        original_value = trie_get(original_account_trie, key)

    assert isinstance(original_value, U256)

    return original_value