ethereum.state

Shared state types and the PreState protocol used by the state transition function.

The PreState protocol specifies the operations that any pre-execution state provider must support, allowing multiple backing implementations (in-memory dict, on-disk database, witness, etc.).

The State class is the in-memory implementation of PreState. 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.

Address

34
Address = Bytes20

Root

35
Root = Hash32

EMPTY_CODE_HASH

37
EMPTY_CODE_HASH = keccak256(b"")

Account

State associated with an address.

40
@slotted_freezable
41
@dataclass
class Account:

nonce

47
    nonce: Uint

balance

48
    balance: U256

code_hash

49
    code_hash: Hash32

EMPTY_ACCOUNT

52
EMPTY_ACCOUNT = Account(
53
    nonce=Uint(0),
54
    balance=U256(0),
55
    code_hash=EMPTY_CODE_HASH,
56
)

BlockDiff

State changes produced by executing a block.

59
@dataclass
class BlockDiff:

account_changes

Per-address account diffs produced by execution.

65
    account_changes: Dict[Address, Optional[Account]]

storage_changes

Per-address storage diffs produced by execution.

68
    storage_changes: Dict[Address, Dict[Bytes32, U256]]

code_changes

New bytecodes (keyed by code hash) introduced by execution.

71
    code_changes: Dict[Hash32, Bytes]

storage_clears

Addresses whose pre-existing storage was wiped during block execution (via a pre-EIP-6780 SELFDESTRUCT). Their storage tries are dropped before storage_changes is applied, so any post-wipe writes begin from empty storage.

74
    storage_clears: Set[Address] = field(default_factory=set)

PreState

Protocol for providing pre-execution state.

Specify the operations that any pre-state provider (dict, database, witness, etc.) must support for the EELS state transition.

class PreState:

get_account_optional

Get the account at an address.

Return None if there is no account at the address.

def get_account_optional(self, ​​address: Address) -> Optional[Account]:
94
        """
95
        Get the account at an address.
96
97
        Return ``None`` if there is no account at the address.
98
        """
99
        ...

get_storage

Get a storage value.

Return U256(0) if the key has not been set.

def get_storage(self, ​​address: Address, ​​key: Bytes32) -> U256:
102
        """
103
        Get a storage value.
104
105
        Return ``U256(0)`` if the key has not been set.
106
        """
107
        ...

get_code

Get the bytecode for a given code hash.

Return b"" for EMPTY_CODE_HASH.

def get_code(self, ​​code_hash: Hash32) -> Bytes:
110
        """
111
        Get the bytecode for a given code hash.
112
113
        Return ``b""`` for ``EMPTY_CODE_HASH``.
114
        """
115
        ...

account_has_storage

Check whether an account has any storage.

Only needed for EIP-7610.

def account_has_storage(self, ​​address: Address) -> bool:
118
        """
119
        Check whether an account has any storage.
120
121
        Only needed for EIP-7610.
122
        """
123
        ...

compute_state_root_and_trie_changes

Compute the state root after applying changes to the pre-state.

storage_clears lists addresses whose pre-existing storage tries must be dropped before storage_changes is applied, so any post-wipe writes begin from empty storage.

Return the new state root together with the internal trie nodes that were created or modified.

def compute_state_root_and_trie_changes(self, ​​account_changes: Dict[Address, Optional[Account]], ​​storage_changes: Dict[Address, Dict[Bytes32, U256]], ​​storage_clears: AbstractSet[Address]) -> Tuple[Root, List["InternalNode"]]:
131
        """
132
        Compute the state root after applying changes to the pre-state.
133
134
        ``storage_clears`` lists addresses whose pre-existing storage
135
        tries must be dropped before ``storage_changes`` is applied, so
136
        any post-wipe writes begin from empty storage.
137
138
        Return the new state root together with the internal trie nodes
139
        that were created or modified.
140
        """
141
        ...

State

Contains all information that is preserved between transactions.

144
@dataclass
class State:

_main_trie

150
    _main_trie: Trie[Address, Optional[Account]] = field(
151
        default_factory=lambda: Trie(secured=True, default=None)
152
    )

_storage_tries

153
    _storage_tries: Dict[Address, Trie[Bytes32, U256]] = field(
154
        default_factory=dict
155
    )

_code_store

156
    _code_store: Dict[Hash32, Bytes] = field(
157
        default_factory=dict, compare=False
158
    )

get_code

Get the bytecode for a given code hash.

Return b"" for EMPTY_CODE_HASH.

def get_code(self, ​​code_hash: Hash32) -> Bytes:
161
        """
162
        Get the bytecode for a given code hash.
163
164
        Return ``b""`` for ``EMPTY_CODE_HASH``.
165
        """
166
        if code_hash == EMPTY_CODE_HASH:
167
            return b""
168
        return self._code_store[code_hash]

get_account_optional

Get the account at an address.

Return None if there is no account at the address.

def get_account_optional(self, ​​address: Address) -> Optional[Account]:
171
        """
172
        Get the account at an address.
173
174
        Return ``None`` if there is no account at the address.
175
        """
176
        return trie_get(self._main_trie, address)

get_storage

Get a storage value.

Return U256(0) if the key has not been set.

def get_storage(self, ​​address: Address, ​​key: Bytes32) -> U256:
179
        """
180
        Get a storage value.
181
182
        Return ``U256(0)`` if the key has not been set.
183
        """
184
        trie = self._storage_tries.get(address)
185
        if trie is None:
186
            return U256(0)
187
188
        value = trie_get(trie, key)
189
190
        assert isinstance(value, U256)
191
        return value

account_has_storage

Check whether an account has any storage.

Only needed for EIP-7610.

def account_has_storage(self, ​​address: Address) -> bool:
194
        """
195
        Check whether an account has any storage.
196
197
        Only needed for EIP-7610.
198
        """
199
        return address in self._storage_tries

compute_state_root_and_trie_changes

Compute the state root after applying changes to the pre-state.

storage_clears lists addresses whose pre-existing storage tries are dropped before storage_changes is applied, so any post-wipe writes begin from empty storage.

Return the new state root together with the internal trie nodes that were created or modified.

def compute_state_root_and_trie_changes(self, ​​account_changes: Dict[Address, Optional[Account]], ​​storage_changes: Dict[Address, Dict[Bytes32, U256]], ​​storage_clears: AbstractSet[Address]) -> Tuple[Root, List["InternalNode"]]:
207
        """
208
        Compute the state root after applying changes to the pre-state.
209
210
        ``storage_clears`` lists addresses whose pre-existing storage
211
        tries are dropped before ``storage_changes`` is applied, so any
212
        post-wipe writes begin from empty storage.
213
214
        Return the new state root together with the internal trie nodes
215
        that were created or modified.
216
        """
217
        main_trie = copy_trie(self._main_trie)
218
        storage_tries = {
219
            k: copy_trie(v)
220
            for k, v in self._storage_tries.items()
221
            if k not in storage_clears
222
        }
223
224
        for address, account in account_changes.items():
225
            trie_set(main_trie, address, account)
226
227
        for address, slots in storage_changes.items():
228
            trie = storage_tries.get(address)
229
            if trie is None:
230
                trie = Trie(secured=True, default=U256(0))
231
                storage_tries[address] = trie
232
            for key, value in slots.items():
233
                trie_set(trie, key, value)
234
            if trie._data == {}:
235
                del storage_tries[address]
236
237
        def get_storage_root(addr: Address) -> Root:
238
            if addr in storage_tries:
239
                return root(storage_tries[addr])
240
            return EMPTY_TRIE_ROOT
241
242
        state_root_value = root(main_trie, get_storage_root=get_storage_root)
243
244
        return state_root_value, []

close_state

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

def close_state(state: State) -> None:
248
    """
249
    Free resources held by the state. Used by optimized implementations to
250
    release file descriptors.
251
    """
252
    del state._main_trie
253
    del state._storage_tries
254
    del state._code_store

apply_changes_to_state

Apply block-level diff to the State for the next block.

Parameters

state : The state to update. diff : Account, storage, and code changes to apply.

def apply_changes_to_state(state: State, ​​diff: BlockDiff) -> None:
258
    """
259
    Apply block-level diff to the ``State`` for the next block.
260
261
    Parameters
262
    ----------
263
    state :
264
        The state to update.
265
    diff :
266
        Account, storage, and code changes to apply.
267
268
    """
269
    for address in diff.storage_clears:
270
        state._storage_tries.pop(address, None)
271
272
    for address, account in diff.account_changes.items():
273
        trie_set(state._main_trie, address, account)
274
275
    for address, slots in diff.storage_changes.items():
276
        trie = state._storage_tries.get(address)
277
        if trie is None:
278
            trie = Trie(secured=True, default=U256(0))
279
            state._storage_tries[address] = trie
280
        for key, value in slots.items():
281
            trie_set(trie, key, value)
282
        if trie._data == {}:
283
            del state._storage_tries[address]
284
285
    state._code_store.update(diff.code_changes)

store_code

Store bytecode in State.

def store_code(state: State, ​​code: Bytes) -> Hash32:
289
    """
290
    Store bytecode in ``State``.
291
    """
292
    code_hash = keccak256(code)
293
    if code_hash != EMPTY_CODE_HASH:
294
        state._code_store[code_hash] = code
295
    return code_hash

set_account

Set an account in a State.

Setting to None deletes the account.

def set_account(state: State, ​​address: Address, ​​account: Optional[Account]) -> None:
303
    """
304
    Set an account in a ``State``.
305
306
    Setting to ``None`` deletes the account.
307
    """
308
    trie_set(state._main_trie, address, account)

set_storage

Set a storage value in a State.

Setting to U256(0) deletes the key.

def set_storage(state: State, ​​address: Address, ​​key: Bytes32, ​​value: U256) -> None:
317
    """
318
    Set a storage value in a ``State``.
319
320
    Setting to ``U256(0)`` deletes the key.
321
    """
322
    assert trie_get(state._main_trie, address) is not None
323
324
    trie = state._storage_tries.get(address)
325
    if trie is None:
326
        trie = Trie(secured=True, default=U256(0))
327
        state._storage_tries[address] = trie
328
    trie_set(trie, key, value)
329
    if trie._data == {}:
330
        del state._storage_tries[address]

state_root

Compute the state root of the current state.

def state_root(state: State) -> Root:
334
    """
335
    Compute the state root of the current state.
336
    """
337
    root_value, _ = state.compute_state_root_and_trie_changes({}, {})
338
    return root_value