|
6 | 6 | This is mainly done as a first pass to make the diff small.
|
7 | 7 | """
|
8 | 8 |
|
9 |
| -from typing import Any, Optional |
| 9 | +from typing import Any, Callable, Optional |
10 | 10 |
|
11 | 11 | from ethereum_types.bytes import Bytes20, Bytes32
|
| 12 | +from ethereum_types.numeric import U256 |
12 | 13 |
|
13 | 14 | # TODO: This file is current Osaka specific -- we could move state.py
|
14 | 15 | # into here to mitigate this.
|
15 | 16 |
|
16 | 17 | # Use generic types for compatibility across forks
|
17 | 18 | Account = Any
|
18 | 19 | Address = Bytes20
|
| 20 | +State = Any |
19 | 21 |
|
20 | 22 |
|
21 | 23 | class MemoryMerkleOracle:
|
22 | 24 | """
|
23 | 25 | Merkle oracle implementation that wraps existing execution-specs state.
|
24 | 26 | """
|
25 | 27 |
|
26 |
| - def __init__(self, state): |
| 28 | + def __init__(self, state: State) -> None: |
27 | 29 | """
|
28 | 30 | Initialize oracle with existing state.
|
29 | 31 |
|
@@ -67,101 +69,111 @@ def state_root(self) -> Bytes32:
|
67 | 69 |
|
68 | 70 | return state_root(self._state)
|
69 | 71 |
|
70 |
| - def get_storage_original(self, address, key): |
| 72 | + def get_storage_original(self, address: Address, key: Bytes32) -> Bytes32: |
71 | 73 | """Get original storage value (before transaction started)."""
|
72 | 74 | from ethereum.osaka.state import get_storage_original
|
73 | 75 |
|
74 | 76 | storage_value = get_storage_original(self._state, address, key)
|
75 | 77 | return storage_value.to_be_bytes32()
|
76 | 78 |
|
77 |
| - def set_storage_value(self, address, key, value): |
| 79 | + def set_storage_value( |
| 80 | + self, address: Address, key: Bytes32, value: Bytes32 |
| 81 | + ) -> None: |
78 | 82 | """Set a single storage value."""
|
79 | 83 | from ethereum_types.numeric import U256
|
80 | 84 |
|
81 | 85 | from ethereum.osaka.state import set_storage
|
82 | 86 |
|
83 |
| - if isinstance(value, bytes): |
84 |
| - storage_value = U256.from_be_bytes(value) |
85 |
| - else: |
86 |
| - storage_value = value |
| 87 | + # Convert Bytes32 to U256 for storage |
| 88 | + storage_value = U256.from_be_bytes(value) |
87 | 89 | set_storage(self._state, address, key, storage_value)
|
88 | 90 |
|
89 |
| - def account_has_code_or_nonce(self, address): |
| 91 | + def account_has_code_or_nonce(self, address: Address) -> bool: |
90 | 92 | """Check if account has non-zero code or nonce."""
|
91 | 93 | from ethereum.osaka.state import account_has_code_or_nonce
|
92 | 94 |
|
93 | 95 | return account_has_code_or_nonce(self._state, address)
|
94 | 96 |
|
95 |
| - def account_has_storage(self, address): |
| 97 | + def account_has_storage(self, address: Address) -> bool: |
96 | 98 | """Check if account has any storage slots."""
|
97 | 99 | from ethereum.osaka.state import account_has_storage
|
98 | 100 |
|
99 | 101 | return account_has_storage(self._state, address)
|
100 | 102 |
|
101 |
| - def is_account_alive(self, address): |
| 103 | + def is_account_alive(self, address: Address) -> bool: |
102 | 104 | """Check if account is alive (exists and not marked for deletion)."""
|
103 | 105 | from ethereum.osaka.state import is_account_alive
|
104 | 106 |
|
105 | 107 | return is_account_alive(self._state, address)
|
106 | 108 |
|
107 |
| - def account_exists(self, address): |
| 109 | + def account_exists(self, address: Address) -> bool: |
108 | 110 | """Check if account exists in the state."""
|
109 | 111 | from ethereum.osaka.state import account_exists
|
110 | 112 |
|
111 | 113 | return account_exists(self._state, address)
|
112 | 114 |
|
113 |
| - def increment_nonce(self, address): |
| 115 | + def increment_nonce(self, address: Address) -> None: |
114 | 116 | """Increment account nonce."""
|
115 | 117 | from ethereum.osaka.state import increment_nonce
|
116 | 118 |
|
117 | 119 | increment_nonce(self._state, address)
|
118 | 120 |
|
119 |
| - def set_code(self, address, code): |
| 121 | + def set_code(self, address: Address, code: Any) -> None: |
120 | 122 | """Set account code."""
|
121 | 123 | from ethereum.osaka.state import set_code
|
122 | 124 |
|
123 | 125 | set_code(self._state, address, code)
|
124 | 126 |
|
125 |
| - def set_account_balance(self, address, balance): |
| 127 | + def set_account_balance(self, address: Address, balance: U256) -> None: |
126 | 128 | """Set account balance."""
|
127 | 129 | from ethereum.osaka.state import set_account_balance
|
128 | 130 |
|
129 | 131 | set_account_balance(self._state, address, balance)
|
130 | 132 |
|
131 |
| - def move_ether(self, sender, recipient, amount): |
| 133 | + def move_ether( |
| 134 | + self, sender: Address, recipient: Address, amount: U256 |
| 135 | + ) -> None: |
132 | 136 | """Transfer ether between accounts."""
|
133 | 137 | from ethereum.osaka.state import move_ether
|
134 | 138 |
|
135 | 139 | move_ether(self._state, sender, recipient, amount)
|
136 | 140 |
|
137 |
| - def add_created_account(self, address): |
| 141 | + def add_created_account(self, address: Address) -> None: |
138 | 142 | """Mark account as created in current transaction."""
|
139 | 143 | # Add to the created_accounts set in state
|
140 | 144 | self._state.created_accounts.add(address)
|
141 | 145 |
|
142 |
| - def is_created_account(self, address): |
| 146 | + def is_created_account(self, address: Address) -> bool: |
143 | 147 | """Check if account was created in current transaction."""
|
144 | 148 | return address in self._state.created_accounts
|
145 | 149 |
|
146 |
| - def account_exists_and_is_empty(self, address): |
| 150 | + def account_exists_and_is_empty(self, address: Address) -> bool: |
147 | 151 | """Check if account exists and is empty."""
|
148 | 152 | from ethereum.osaka.state import account_exists_and_is_empty
|
149 | 153 |
|
150 | 154 | return account_exists_and_is_empty(self._state, address)
|
151 | 155 |
|
152 |
| - def destroy_account(self, address): |
| 156 | + def destroy_account(self, address: Address) -> None: |
153 | 157 | """Mark account for destruction."""
|
154 | 158 | from ethereum.osaka.state import destroy_account
|
155 | 159 |
|
156 | 160 | destroy_account(self._state, address)
|
157 | 161 |
|
158 |
| - def modify_state(self, address, modifier_function): |
| 162 | + def destroy_storage(self, address: Address) -> None: |
| 163 | + """Completely remove the storage at address.""" |
| 164 | + from ethereum.osaka.state import destroy_storage |
| 165 | + |
| 166 | + destroy_storage(self._state, address) |
| 167 | + |
| 168 | + def modify_state( |
| 169 | + self, address: Address, modifier_function: Callable[[Account], None] |
| 170 | + ) -> None: |
159 | 171 | """Modify an account using a modifier function."""
|
160 | 172 | from ethereum.osaka.state import modify_state
|
161 | 173 |
|
162 | 174 | modify_state(self._state, address, modifier_function)
|
163 | 175 |
|
164 | 176 | @property
|
165 |
| - def state(self): |
| 177 | + def state(self) -> State: |
166 | 178 | """Access to underlying state for compatibility."""
|
167 | 179 | return self._state
|
0 commit comments