ethereum.dao_fork.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
.
1""" 2State 3^^^^^ 4 5.. contents:: Table of Contents 6 :backlinks: none 7 :local: 8 9Introduction 10------------ 11 12The state contains all information that is preserved between transactions. 13 14It consists of a main account trie and storage tries for each contract. 15 16There is a distinction between an account that does not exist and 17`EMPTY_ACCOUNT`. 18""" 19from dataclasses import dataclass, field 20from typing import Callable, Dict, List, Optional, Tuple 21 22from ethereum.base_types import U256, Bytes, Uint, modify 23from ethereum.utils.ensure import ensure 24 25from .fork_types import EMPTY_ACCOUNT, Account, Address, Root 26from .trie import EMPTY_TRIE_ROOT, Trie, copy_trie, root, trie_get, trie_set 27 28 29@dataclass 30class State: 31 """ 32 Contains all information that is preserved between transactions. 33 """ 34 35 _main_trie: Trie[Address, Optional[Account]] = field( 36 default_factory=lambda: Trie(secured=True, default=None) 37 ) 38 _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( 39 default_factory=dict 40 ) 41 _snapshots: List[ 42 Tuple[ 43 Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] 44 ] 45 ] = field(default_factory=list) 46 47 48def close_state(state: State) -> None: 49 """ 50 Free resources held by the state. Used by optimized implementations to 51 release file descriptors. 52 """ 53 del state._main_trie 54 del state._storage_tries 55 del state._snapshots 56 57 58def begin_transaction(state: State) -> None: 59 """ 60 Start a state transaction. 61 62 Transactions are entirely implicit and can be nested. It is not possible to 63 calculate the state root during a transaction. 64 65 Parameters 66 ---------- 67 state : State 68 The state. 69 """ 70 state._snapshots.append( 71 ( 72 copy_trie(state._main_trie), 73 {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, 74 ) 75 ) 76 77 78def commit_transaction(state: State) -> None: 79 """ 80 Commit a state transaction. 81 82 Parameters 83 ---------- 84 state : State 85 The state. 86 """ 87 state._snapshots.pop() 88 89 90def rollback_transaction(state: State) -> None: 91 """ 92 Rollback a state transaction, resetting the state to the point when the 93 corresponding `start_transaction()` call was made. 94 95 Parameters 96 ---------- 97 state : State 98 The state. 99 """ 100 state._main_trie, state._storage_tries = state._snapshots.pop() 101 102 103def get_account(state: State, address: Address) -> Account: 104 """ 105 Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there 106 is no account at the address. 107 108 Use `get_account_optional()` if you care about the difference between a 109 non-existent account and `EMPTY_ACCOUNT`. 110 111 Parameters 112 ---------- 113 state: `State` 114 The state 115 address : `Address` 116 Address to lookup. 117 118 Returns 119 ------- 120 account : `Account` 121 Account at address. 122 """ 123 account = get_account_optional(state, address) 124 if isinstance(account, Account): 125 return account 126 else: 127 return EMPTY_ACCOUNT 128 129 130def get_account_optional(state: State, address: Address) -> Optional[Account]: 131 """ 132 Get the `Account` object at an address. Returns `None` (rather than 133 `EMPTY_ACCOUNT`) if there is no account at the address. 134 135 Parameters 136 ---------- 137 state: `State` 138 The state 139 address : `Address` 140 Address to lookup. 141 142 Returns 143 ------- 144 account : `Account` 145 Account at address. 146 """ 147 account = trie_get(state._main_trie, address) 148 return account 149 150 151def set_account( 152 state: State, address: Address, account: Optional[Account] 153) -> None: 154 """ 155 Set the `Account` object at an address. Setting to `None` deletes 156 the account (but not its storage, see `destroy_account()`). 157 158 Parameters 159 ---------- 160 state: `State` 161 The state 162 address : `Address` 163 Address to set. 164 account : `Account` 165 Account to set at address. 166 """ 167 trie_set(state._main_trie, address, account) 168 169 170def destroy_account(state: State, address: Address) -> None: 171 """ 172 Completely remove the account at `address` and all of its storage. 173 174 This function is made available exclusively for the `SELFDESTRUCT` 175 opcode. It is expected that `SELFDESTRUCT` will be disabled in a future 176 hardfork and this function will be removed. 177 178 Parameters 179 ---------- 180 state: `State` 181 The state 182 address : `Address` 183 Address of account to destroy. 184 """ 185 destroy_storage(state, address) 186 set_account(state, address, None) 187 188 189def destroy_storage(state: State, address: Address) -> None: 190 """ 191 Completely remove the storage at `address`. 192 193 Parameters 194 ---------- 195 state: `State` 196 The state 197 address : `Address` 198 Address of account whose storage is to be deleted. 199 """ 200 if address in state._storage_tries: 201 del state._storage_tries[address] 202 203 204def get_storage(state: State, address: Address, key: Bytes) -> U256: 205 """ 206 Get a value at a storage key on an account. Returns `U256(0)` if the 207 storage key has not been set previously. 208 209 Parameters 210 ---------- 211 state: `State` 212 The state 213 address : `Address` 214 Address of the account. 215 key : `Bytes` 216 Key to lookup. 217 218 Returns 219 ------- 220 value : `U256` 221 Value at the key. 222 """ 223 trie = state._storage_tries.get(address) 224 if trie is None: 225 return U256(0) 226 227 value = trie_get(trie, key) 228 229 assert isinstance(value, U256) 230 return value 231 232 233def set_storage( 234 state: State, address: Address, key: Bytes, value: U256 235) -> None: 236 """ 237 Set a value at a storage key on an account. Setting to `U256(0)` deletes 238 the key. 239 240 Parameters 241 ---------- 242 state: `State` 243 The state 244 address : `Address` 245 Address of the account. 246 key : `Bytes` 247 Key to set. 248 value : `U256` 249 Value to set at the key. 250 """ 251 assert trie_get(state._main_trie, address) is not None 252 253 trie = state._storage_tries.get(address) 254 if trie is None: 255 trie = Trie(secured=True, default=U256(0)) 256 state._storage_tries[address] = trie 257 trie_set(trie, key, value) 258 if trie._data == {}: 259 del state._storage_tries[address] 260 261 262def storage_root(state: State, address: Address) -> Root: 263 """ 264 Calculate the storage root of an account. 265 266 Parameters 267 ---------- 268 state: 269 The state 270 address : 271 Address of the account. 272 273 Returns 274 ------- 275 root : `Root` 276 Storage root of the account. 277 """ 278 assert not state._snapshots 279 if address in state._storage_tries: 280 return root(state._storage_tries[address]) 281 else: 282 return EMPTY_TRIE_ROOT 283 284 285def state_root(state: State) -> Root: 286 """ 287 Calculate the state root. 288 289 Parameters 290 ---------- 291 state: 292 The current state. 293 294 Returns 295 ------- 296 root : `Root` 297 The state root. 298 """ 299 assert not state._snapshots 300 301 def get_storage_root(address: Address) -> Root: 302 return storage_root(state, address) 303 304 return root(state._main_trie, get_storage_root=get_storage_root) 305 306 307def account_exists(state: State, address: Address) -> bool: 308 """ 309 Checks if an account exists in the state trie 310 311 Parameters 312 ---------- 313 state: 314 The state 315 address: 316 Address of the account that needs to be checked. 317 318 Returns 319 ------- 320 account_exists : `bool` 321 True if account exists in the state trie, False otherwise 322 """ 323 return get_account_optional(state, address) is not None 324 325 326def account_has_code_or_nonce(state: State, address: Address) -> bool: 327 """ 328 Checks if an account has non zero nonce or non empty code 329 330 Parameters 331 ---------- 332 state: 333 The state 334 address: 335 Address of the account that needs to be checked. 336 337 Returns 338 ------- 339 has_code_or_nonce : `bool` 340 True if if an account has non zero nonce or non empty code, 341 False otherwise. 342 """ 343 account = get_account(state, address) 344 return account.nonce != Uint(0) or account.code != b"" 345 346 347def modify_state( 348 state: State, address: Address, f: Callable[[Account], None] 349) -> None: 350 """ 351 Modify an `Account` in the `State`. 352 """ 353 set_account(state, address, modify(get_account(state, address), f)) 354 355 356def move_ether( 357 state: State, 358 sender_address: Address, 359 recipient_address: Address, 360 amount: U256, 361) -> None: 362 """ 363 Move funds between accounts. 364 """ 365 366 def reduce_sender_balance(sender: Account) -> None: 367 ensure(sender.balance >= amount, AssertionError) 368 sender.balance -= amount 369 370 def increase_recipient_balance(recipient: Account) -> None: 371 recipient.balance += amount 372 373 modify_state(state, sender_address, reduce_sender_balance) 374 modify_state(state, recipient_address, increase_recipient_balance) 375 376 377def set_account_balance(state: State, address: Address, amount: U256) -> None: 378 """ 379 Sets the balance of an account. 380 381 Parameters 382 ---------- 383 state: 384 The current state. 385 386 address: 387 Address of the account whose nonce needs to be incremented. 388 389 amount: 390 The amount that needs to set in balance. 391 """ 392 393 def set_balance(account: Account) -> None: 394 account.balance = amount 395 396 modify_state(state, address, set_balance) 397 398 399def touch_account(state: State, address: Address) -> None: 400 """ 401 Initializes an account to state. 402 403 Parameters 404 ---------- 405 state: 406 The current state. 407 408 address: 409 The address of the account that need to initialised. 410 """ 411 if not account_exists(state, address): 412 set_account(state, address, EMPTY_ACCOUNT) 413 414 415def increment_nonce(state: State, address: Address) -> None: 416 """ 417 Increments the nonce of an account. 418 419 Parameters 420 ---------- 421 state: 422 The current state. 423 424 address: 425 Address of the account whose nonce needs to be incremented. 426 """ 427 428 def increase_nonce(sender: Account) -> None: 429 sender.nonce += 1 430 431 modify_state(state, address, increase_nonce) 432 433 434def set_code(state: State, address: Address, code: Bytes) -> None: 435 """ 436 Sets Account code. 437 438 Parameters 439 ---------- 440 state: 441 The current state. 442 443 address: 444 Address of the account whose code needs to be update. 445 446 code: 447 The bytecode that needs to be set. 448 """ 449 450 def write_code(sender: Account) -> None: 451 sender.code = code 452 453 modify_state(state, address, write_code) 454 455 456def create_ether(state: State, address: Address, amount: U256) -> None: 457 """ 458 Add newly created ether to an account. 459 460 Parameters 461 ---------- 462 state: 463 The current state. 464 address: 465 Address of the account to which ether is added. 466 amount: 467 The amount of ether to be added to the account of interest. 468 """ 469 470 def increase_balance(account: Account) -> None: 471 account.balance += amount 472 473 modify_state(state, address, increase_balance)
30@dataclass 31class State: 32 """ 33 Contains all information that is preserved between transactions. 34 """ 35 36 _main_trie: Trie[Address, Optional[Account]] = field( 37 default_factory=lambda: Trie(secured=True, default=None) 38 ) 39 _storage_tries: Dict[Address, Trie[Bytes, U256]] = field( 40 default_factory=dict 41 ) 42 _snapshots: List[ 43 Tuple[ 44 Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]] 45 ] 46 ] = field(default_factory=list)
Contains all information that is preserved between transactions.
49def close_state(state: State) -> None: 50 """ 51 Free resources held by the state. Used by optimized implementations to 52 release file descriptors. 53 """ 54 del state._main_trie 55 del state._storage_tries 56 del state._snapshots
Free resources held by the state. Used by optimized implementations to release file descriptors.
59def begin_transaction(state: State) -> None: 60 """ 61 Start a state transaction. 62 63 Transactions are entirely implicit and can be nested. It is not possible to 64 calculate the state root during a transaction. 65 66 Parameters 67 ---------- 68 state : State 69 The state. 70 """ 71 state._snapshots.append( 72 ( 73 copy_trie(state._main_trie), 74 {k: copy_trie(t) for (k, t) in state._storage_tries.items()}, 75 ) 76 )
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.
79def commit_transaction(state: State) -> None: 80 """ 81 Commit a state transaction. 82 83 Parameters 84 ---------- 85 state : State 86 The state. 87 """ 88 state._snapshots.pop()
Commit a state transaction.
Parameters
state : State The state.
91def rollback_transaction(state: State) -> None: 92 """ 93 Rollback a state transaction, resetting the state to the point when the 94 corresponding `start_transaction()` call was made. 95 96 Parameters 97 ---------- 98 state : State 99 The state. 100 """ 101 state._main_trie, state._storage_tries = state._snapshots.pop()
Rollback a state transaction, resetting the state to the point when the
corresponding start_transaction()
call was made.
Parameters
state : State The state.
104def get_account(state: State, address: Address) -> Account: 105 """ 106 Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there 107 is no account at the address. 108 109 Use `get_account_optional()` if you care about the difference between a 110 non-existent account and `EMPTY_ACCOUNT`. 111 112 Parameters 113 ---------- 114 state: `State` 115 The state 116 address : `Address` 117 Address to lookup. 118 119 Returns 120 ------- 121 account : `Account` 122 Account at address. 123 """ 124 account = get_account_optional(state, address) 125 if isinstance(account, Account): 126 return account 127 else: 128 return EMPTY_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.
131def get_account_optional(state: State, address: Address) -> Optional[Account]: 132 """ 133 Get the `Account` object at an address. Returns `None` (rather than 134 `EMPTY_ACCOUNT`) if there is no account at the address. 135 136 Parameters 137 ---------- 138 state: `State` 139 The state 140 address : `Address` 141 Address to lookup. 142 143 Returns 144 ------- 145 account : `Account` 146 Account at address. 147 """ 148 account = trie_get(state._main_trie, address) 149 return 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
Account at address.
152def set_account( 153 state: State, address: Address, account: Optional[Account] 154) -> None: 155 """ 156 Set the `Account` object at an address. Setting to `None` deletes 157 the account (but not its storage, see `destroy_account()`). 158 159 Parameters 160 ---------- 161 state: `State` 162 The state 163 address : `Address` 164 Address to set. 165 account : `Account` 166 Account to set at address. 167 """ 168 trie_set(state._main_trie, 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.
171def destroy_account(state: State, address: Address) -> None: 172 """ 173 Completely remove the account at `address` and all of its storage. 174 175 This function is made available exclusively for the `SELFDESTRUCT` 176 opcode. It is expected that `SELFDESTRUCT` will be disabled in a future 177 hardfork and this function will be removed. 178 179 Parameters 180 ---------- 181 state: `State` 182 The state 183 address : `Address` 184 Address of account to destroy. 185 """ 186 destroy_storage(state, address) 187 set_account(state, 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.
190def destroy_storage(state: State, address: Address) -> None: 191 """ 192 Completely remove the storage at `address`. 193 194 Parameters 195 ---------- 196 state: `State` 197 The state 198 address : `Address` 199 Address of account whose storage is to be deleted. 200 """ 201 if address in state._storage_tries: 202 del state._storage_tries[address]
Completely remove the storage at address
.
Parameters
state: State
The state
address : Address
Address of account whose storage is to be deleted.
205def get_storage(state: State, address: Address, key: Bytes) -> U256: 206 """ 207 Get a value at a storage key on an account. Returns `U256(0)` if the 208 storage key has not been set previously. 209 210 Parameters 211 ---------- 212 state: `State` 213 The state 214 address : `Address` 215 Address of the account. 216 key : `Bytes` 217 Key to lookup. 218 219 Returns 220 ------- 221 value : `U256` 222 Value at the key. 223 """ 224 trie = state._storage_tries.get(address) 225 if trie is None: 226 return U256(0) 227 228 value = trie_get(trie, key) 229 230 assert isinstance(value, U256) 231 return value
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.
234def set_storage( 235 state: State, address: Address, key: Bytes, value: U256 236) -> None: 237 """ 238 Set a value at a storage key on an account. Setting to `U256(0)` deletes 239 the key. 240 241 Parameters 242 ---------- 243 state: `State` 244 The state 245 address : `Address` 246 Address of the account. 247 key : `Bytes` 248 Key to set. 249 value : `U256` 250 Value to set at the key. 251 """ 252 assert trie_get(state._main_trie, address) is not None 253 254 trie = state._storage_tries.get(address) 255 if trie is None: 256 trie = Trie(secured=True, default=U256(0)) 257 state._storage_tries[address] = trie 258 trie_set(trie, key, value) 259 if trie._data == {}: 260 del state._storage_tries[address]
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.
263def storage_root(state: State, address: Address) -> Root: 264 """ 265 Calculate the storage root of an account. 266 267 Parameters 268 ---------- 269 state: 270 The state 271 address : 272 Address of the account. 273 274 Returns 275 ------- 276 root : `Root` 277 Storage root of the account. 278 """ 279 assert not state._snapshots 280 if address in state._storage_tries: 281 return root(state._storage_tries[address]) 282 else: 283 return EMPTY_TRIE_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.
286def state_root(state: State) -> Root: 287 """ 288 Calculate the state root. 289 290 Parameters 291 ---------- 292 state: 293 The current state. 294 295 Returns 296 ------- 297 root : `Root` 298 The state root. 299 """ 300 assert not state._snapshots 301 302 def get_storage_root(address: Address) -> Root: 303 return storage_root(state, address) 304 305 return root(state._main_trie, get_storage_root=get_storage_root)
Calculate the state root.
Parameters
state: The current state.
Returns
root : Root
The state root.
308def account_exists(state: State, address: Address) -> bool: 309 """ 310 Checks if an account exists in the state trie 311 312 Parameters 313 ---------- 314 state: 315 The state 316 address: 317 Address of the account that needs to be checked. 318 319 Returns 320 ------- 321 account_exists : `bool` 322 True if account exists in the state trie, False otherwise 323 """ 324 return get_account_optional(state, address) is not None
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
327def account_has_code_or_nonce(state: State, address: Address) -> bool: 328 """ 329 Checks if an account has non zero nonce or non empty code 330 331 Parameters 332 ---------- 333 state: 334 The state 335 address: 336 Address of the account that needs to be checked. 337 338 Returns 339 ------- 340 has_code_or_nonce : `bool` 341 True if if an account has non zero nonce or non empty code, 342 False otherwise. 343 """ 344 account = get_account(state, address) 345 return account.nonce != Uint(0) or account.code != b""
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 if an account has non zero nonce or non empty code,
False otherwise.
348def modify_state( 349 state: State, address: Address, f: Callable[[Account], None] 350) -> None: 351 """ 352 Modify an `Account` in the `State`. 353 """ 354 set_account(state, address, modify(get_account(state, address), f))
Modify an Account
in the State
.
357def move_ether( 358 state: State, 359 sender_address: Address, 360 recipient_address: Address, 361 amount: U256, 362) -> None: 363 """ 364 Move funds between accounts. 365 """ 366 367 def reduce_sender_balance(sender: Account) -> None: 368 ensure(sender.balance >= amount, AssertionError) 369 sender.balance -= amount 370 371 def increase_recipient_balance(recipient: Account) -> None: 372 recipient.balance += amount 373 374 modify_state(state, sender_address, reduce_sender_balance) 375 modify_state(state, recipient_address, increase_recipient_balance)
Move funds between accounts.
378def set_account_balance(state: State, address: Address, amount: U256) -> None: 379 """ 380 Sets the balance of an account. 381 382 Parameters 383 ---------- 384 state: 385 The current state. 386 387 address: 388 Address of the account whose nonce needs to be incremented. 389 390 amount: 391 The amount that needs to set in balance. 392 """ 393 394 def set_balance(account: Account) -> None: 395 account.balance = amount 396 397 modify_state(state, address, set_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.
400def touch_account(state: State, address: Address) -> None: 401 """ 402 Initializes an account to state. 403 404 Parameters 405 ---------- 406 state: 407 The current state. 408 409 address: 410 The address of the account that need to initialised. 411 """ 412 if not account_exists(state, address): 413 set_account(state, address, EMPTY_ACCOUNT)
Initializes an account to state.
Parameters
state: The current state.
address: The address of the account that need to initialised.
416def increment_nonce(state: State, address: Address) -> None: 417 """ 418 Increments the nonce of an account. 419 420 Parameters 421 ---------- 422 state: 423 The current state. 424 425 address: 426 Address of the account whose nonce needs to be incremented. 427 """ 428 429 def increase_nonce(sender: Account) -> None: 430 sender.nonce += 1 431 432 modify_state(state, address, increase_nonce)
Increments the nonce of an account.
Parameters
state: The current state.
address: Address of the account whose nonce needs to be incremented.
435def set_code(state: State, address: Address, code: Bytes) -> None: 436 """ 437 Sets Account code. 438 439 Parameters 440 ---------- 441 state: 442 The current state. 443 444 address: 445 Address of the account whose code needs to be update. 446 447 code: 448 The bytecode that needs to be set. 449 """ 450 451 def write_code(sender: Account) -> None: 452 sender.code = code 453 454 modify_state(state, address, write_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.
457def create_ether(state: State, address: Address, amount: U256) -> None: 458 """ 459 Add newly created ether to an account. 460 461 Parameters 462 ---------- 463 state: 464 The current state. 465 address: 466 Address of the account to which ether is added. 467 amount: 468 The amount of ether to be added to the account of interest. 469 """ 470 471 def increase_balance(account: Account) -> None: 472 account.balance += amount 473 474 modify_state(state, address, increase_balance)
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.