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.

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.arrow_glacier.trie.Trie[ethereum.arrow_glacier.fork_types.Address, Optional[ethereum.arrow_glacier.fork_types.Account]]
_storage_tries :Dict[ethereum.arrow_glacier.fork_types.Address, ethereum.arrow_glacier.trie.Trie[ethereum.base_types.Bytes, ethereum.base_types.U256]]
_snapshots :List[Tuple[ethereum.arrow_glacier.trie.Trie[ethereum.arrow_glacier.fork_types.Address, Optional[ethereum.arrow_glacier.fork_types.Account]], Dict[ethereum.arrow_glacier.fork_types.Address, ethereum.arrow_glacier.trie.Trie[ethereum.base_types.Bytes, ethereum.base_types.U256]]]]

close_state

close_state(state: State)None

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

begin_transaction

begin_transaction(state: State)None

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: State)None

Commit a state transaction.

Parameters

state (State) – The state.

def commit_transaction(state: State) -> None:
    state._snapshots.pop()

rollback_transaction

rollback_transaction(state: State)None

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()

get_account

get_account(state: State, address: ethereum.arrow_glacier.fork_types.Address)ethereum.arrow_glacier.fork_types.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 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: State, address: ethereum.arrow_glacier.fork_types.Address)Optional[ethereum.arrow_glacier.fork_types.Account]

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: State, address: ethereum.arrow_glacier.fork_types.Address, account: Optional[ethereum.arrow_glacier.fork_types.Account])None

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: State, address: ethereum.arrow_glacier.fork_types.Address)None

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: State, address: ethereum.arrow_glacier.fork_types.Address)None

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]

get_storage

get_storage(state: State, address: ethereum.arrow_glacier.fork_types.Address, key: ethereum.base_types.Bytes)ethereum.base_types.U256

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: State, address: ethereum.arrow_glacier.fork_types.Address, key: ethereum.base_types.Bytes, value: ethereum.base_types.U256)None

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: State, address: ethereum.arrow_glacier.fork_types.Address)ethereum.arrow_glacier.fork_types.Root

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 state._snapshots == []
    if address in state._storage_tries:
        return root(state._storage_tries[address])
    else:
        return EMPTY_TRIE_ROOT

state_root

state_root(state: State)ethereum.arrow_glacier.fork_types.Root

Calculate the state root.

Parameters

state – The current state.

Returns

root – The state root.

Return type

Root

def state_root(state: State) -> Root:
    assert 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: State, address: ethereum.arrow_glacier.fork_types.Address)bool

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: State, address: ethereum.arrow_glacier.fork_types.Address)bool

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: State, address: ethereum.arrow_glacier.fork_types.Address)bool

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: State, address: ethereum.arrow_glacier.fork_types.Address)bool

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: State, address: ethereum.arrow_glacier.fork_types.Address)bool

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: State, address: ethereum.arrow_glacier.fork_types.Address, f: Callable[[ethereum.arrow_glacier.fork_types.Account], None])None

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: State, sender_address: ethereum.arrow_glacier.fork_types.Address, recipient_address: ethereum.arrow_glacier.fork_types.Address, amount: ethereum.base_types.U256)None

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: State, address: ethereum.arrow_glacier.fork_types.Address, amount: ethereum.base_types.U256)None

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: State, address: ethereum.arrow_glacier.fork_types.Address)None

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: State, address: ethereum.arrow_glacier.fork_types.Address)None

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: State, address: ethereum.arrow_glacier.fork_types.Address, code: ethereum.base_types.Bytes)None

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: State, address: ethereum.arrow_glacier.fork_types.Address, amount: ethereum.base_types.U256)None

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: State, address: ethereum.arrow_glacier.fork_types.Address, key: ethereum.base_types.Bytes)ethereum.base_types.U256

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:
    _, 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