@@ -14,30 +14,30 @@ import
14
14
chronicles,
15
15
stint,
16
16
results,
17
- eth/ common/ [base, hashes, addresses, accounts, headers, transactions],
17
+ eth/ common/ [base, addresses, accounts, headers, transactions],
18
18
../../ execution_chain/ db/ [ledger, access_list],
19
19
../../ execution_chain/ common/ common,
20
20
../../ execution_chain/ transaction/ call_evm,
21
- ../../ execution_chain/ evm/ [types, state, evm_errors]
21
+ ../../ execution_chain/ evm/ [types, state, evm_errors],
22
+ ./ async_evm_backend
22
23
23
- from web3/ eth_api_types import TransactionArgs
24
- from web3/ eth_api_types import Quantity
24
+ from web3/ eth_api_types import TransactionArgs, Quantity
25
25
26
26
export
27
- results, chronos, hashes, addresses, accounts , headers, TransactionArgs, CallResult,
27
+ async_evm_backend, results, chronos , headers, TransactionArgs, CallResult,
28
28
transactions.AccessList, GasInt
29
29
30
30
logScope:
31
31
topics = " async_evm"
32
32
33
- # The Portal EVM uses the Nimbus in-memory EVM to execute transactions using the
34
- # portal state network state data. Currently only call is supported .
33
+ # The Async EVM uses the Nimbus in-memory EVM to execute transactions using state
34
+ # data fetched asyncronously from a supplied state backend .
35
35
#
36
- # Rather than wire in the portal state lookups into the EVM directly, the approach
36
+ # Rather than wire in the async state lookups into the EVM directly, the approach
37
37
# taken here is to optimistically execute the transaction multiple times with the
38
38
# goal of building the correct access list so that we can then lookup the accessed
39
- # state from the portal network , store the state in the in-memory EVM and then
40
- # finally execute the transaction using the correct state. The Portal EVM makes
39
+ # state from the async state backend , store the state in the in-memory EVM and then
40
+ # finally execute the transaction using the correct state. The Async EVM makes
41
41
# use of data in memory during the call and therefore each piece of state is never
42
42
# fetched more than once. We know we have found the correct access list if it
43
43
# doesn't change after another execution of the transaction.
@@ -48,9 +48,8 @@ logScope:
48
48
# call given that we gain the ability to fetch the state concurrently.
49
49
#
50
50
# There are multiple reasons for choosing this approach:
51
- # - Firstly updating the existing Nimbus EVM to support using a different state
52
- # backend (portal state in this case) is difficult and would require making
53
- # non-trivial changes to the EVM.
51
+ # - Firstly updating the existing Nimbus EVM to support using different state
52
+ # backends is difficult and would require making non-trivial changes to the EVM.
54
53
# - This new approach allows us to look up the state concurrently in the event that
55
54
# multiple new state keys are discovered after executing the transaction. This
56
55
# should in theory result in improved performance for certain scenarios. The
82
81
address: Address
83
82
codeFut: Future[Opt[seq [byte ]]]
84
83
85
- GetAccountProc* = proc (stateRoot: Hash32, address: Address): Future[Opt[Account]] {.
86
- async: (raises: [CancelledError])
87
- .}
88
-
89
- GetStorageProc* = proc (
90
- stateRoot: Hash32, address: Address, slotKey: UInt256
91
- ): Future[Opt[UInt256]] {.async: (raises: [CancelledError]) .}
92
-
93
- GetCodeProc* = proc (stateRoot: Hash32, address: Address): Future[Opt[seq [byte ]]] {.
94
- async: (raises: [CancelledError])
95
- .}
96
-
97
- AsyncEvmStateBackend* = object
98
- getAccount: GetAccountProc
99
- getStorage: GetStorageProc
100
- getCode: GetCodeProc
101
-
102
84
AsyncEvm* = ref object
103
85
com: CommonRef
104
86
backend: AsyncEvmStateBackend
@@ -114,14 +96,6 @@ func init(
114
96
func init(T: type CodeQuery, adr: Address, fut: Future[Opt[seq [byte ]]]): T =
115
97
T(address: adr, codeFut: fut)
116
98
117
- proc init* (
118
- T: type AsyncEvmStateBackend,
119
- accProc: GetAccountProc,
120
- storageProc: GetStorageProc,
121
- codeProc: GetCodeProc,
122
- ): T =
123
- AsyncEvmStateBackend(getAccount: accProc, getStorage: storageProc, getCode: codeProc)
124
-
125
99
proc init* (
126
100
T: type AsyncEvm, backend: AsyncEvmStateBackend, networkId: NetworkId = MainNet
127
101
): T =
@@ -165,7 +139,7 @@ proc callFetchingState(
165
139
fetchedCode = initHashSet[Address]()
166
140
167
141
# Set code of the 'to' address in the EVM so that we can execute the transaction
168
- let code = (await evm.backend.getCode(header.stateRoot , to)).valueOr:
142
+ let code = (await evm.backend.getCode(header, to)).valueOr:
169
143
return err("Unable to get code")
170
144
vmState.ledger.setCode(to, code)
171
145
fetchedCode.incl(to)
@@ -215,8 +189,7 @@ proc callFetchingState(
215
189
let slotIdx = (adr, v.storageSlot)
216
190
if slotIdx notin fetchedStorage:
217
191
debug "Fetching storage slot", address = adr, slotKey = v.storageSlot
218
- let storageFut =
219
- evm.backend.getStorage(header.stateRoot, adr, v.storageSlot)
192
+ let storageFut = evm.backend.getStorage(header, adr, v.storageSlot)
220
193
if not stateFetchDone:
221
194
storageQueries.add(StorageQuery.init(adr, v.storageSlot, storageFut))
222
195
if not optimisticStateFetch:
@@ -226,15 +199,15 @@ proc callFetchingState(
226
199
227
200
if adr notin fetchedAccounts:
228
201
debug "Fetching account", address = adr
229
- let accFut = evm.backend.getAccount(header.stateRoot , adr)
202
+ let accFut = evm.backend.getAccount(header, adr)
230
203
if not stateFetchDone:
231
204
accountQueries.add(AccountQuery.init(adr, accFut))
232
205
if not optimisticStateFetch:
233
206
stateFetchDone = true
234
207
235
208
if v.codeTouched and adr notin fetchedCode:
236
209
debug "Fetching code", address = adr
237
- let codeFut = evm.backend.getCode(header.stateRoot , adr)
210
+ let codeFut = evm.backend.getCode(header, adr)
238
211
if not stateFetchDone:
239
212
codeQueries.add(CodeQuery.init(adr, codeFut))
240
213
if not optimisticStateFetch:
0 commit comments