State
Table of Contents
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
Contains all information that is preserved between transactions. |
Functions
Free resources held by the state. Used by optimized implementations to |
|
Start a state transaction. |
|
Commit a state transaction. |
|
Rollback a state transaction, resetting the state to the point when the |
|
Get the Account object at an address. Returns EMPTY_ACCOUNT if there |
|
Get the Account object at an address. Returns None (rather than |
|
Set the Account object at an address. Setting to None deletes |
|
Completely remove the account at address and all of its storage. |
|
Completely remove the storage at address. |
|
Get a value at a storage key on an account. Returns U256(0) if the |
|
Set a value at a storage key on an account. Setting to U256(0) deletes |
|
Calculate the storage root of an account. |
|
Calculate the state root. |
|
Checks if an account exists in the state trie |
|
Checks if an account has non zero nonce or non empty code |
|
Checks if an account has zero nonce, empty code and zero balance. |
|
Checks if an account exists and has zero nonce, empty code and zero |
|
Check whether is an account is both in the state and non empty. |
|
Modify an Account in the State. |
|
Move funds between accounts. |
|
Sets the balance of an account. |
|
Initializes an account to state. |
|
Increments the nonce of an account. |
|
Sets Account code. |
|
Add newly created ether to an account. |
|
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.istanbul.trie.Trie[ethereum.istanbul.fork_types.Address, Optional[ethereum.istanbul.fork_types.Account]]
- _storage_tries :Dict[ethereum.istanbul.fork_types.Address, ethereum.istanbul.trie.Trie[ethereum.base_types.Bytes, ethereum.base_types.U256]]
- _snapshots :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]]]]
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.istanbul.fork_types.Address) → ethereum.istanbul.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.istanbul.fork_types.Address) → Optional[ethereum.istanbul.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.istanbul.fork_types.Address, account: Optional[ethereum.istanbul.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.istanbul.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.istanbul.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.istanbul.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.istanbul.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.istanbul.fork_types.Address) → ethereum.istanbul.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.istanbul.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.istanbul.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.istanbul.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.istanbul.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.istanbul.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.istanbul.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.istanbul.fork_types.Address, f: Callable[[ethereum.istanbul.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.istanbul.fork_types.Address, recipient_address: ethereum.istanbul.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.istanbul.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.istanbul.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.istanbul.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.istanbul.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.istanbul.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.istanbul.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