1
- use crate :: { operation:: RW , Error } ;
2
- use eth_types:: {
3
- evm_types:: OpcodeId , Address , GethExecStep , GethExecTrace , GethPrestateTrace , ToAddress , Word ,
4
- } ;
5
- use ethers_core:: utils:: get_contract_address;
1
+ use crate :: operation:: RW ;
2
+ use eth_types:: { geth_types:: GethData , Address , GethExecStep , GethPrestateTrace , Word } ;
6
3
use std:: collections:: { hash_map:: Entry , HashMap , HashSet } ;
7
4
8
- use AccessValue :: { Account , Code , Storage } ;
9
- use RW :: { READ , WRITE } ;
10
-
11
5
/// State and Code Access with "keys/index" used in the access operation.
12
6
#[ derive( Debug , PartialEq , Eq ) ]
13
7
pub enum AccessValue {
@@ -119,6 +113,39 @@ impl AccessSet {
119
113
self . state . extend ( other. state . drain ( ) ) ;
120
114
self . code . extend ( other. code . drain ( ) ) ;
121
115
}
116
+
117
+ #[ cfg( not( feature = "scroll" ) ) ]
118
+ pub ( crate ) fn from_geth_data ( geth_data : & GethData ) -> Self {
119
+ let mut access_set = AccessSet :: default ( ) ;
120
+ access_set. add_account ( geth_data. eth_block . author . unwrap ( ) ) ;
121
+ for trace in geth_data. geth_traces . iter ( ) {
122
+ access_set. extend_from_traces ( trace. prestate . as_ref ( ) . unwrap ( ) ) ;
123
+ }
124
+ access_set
125
+ }
126
+
127
+ #[ cfg( feature = "scroll" ) ]
128
+ pub ( crate ) fn from_geth_data ( geth_data : & GethData ) -> Self {
129
+ let mut access_set = AccessSet :: default ( ) ;
130
+ access_set. add_account ( geth_data. eth_block . author . unwrap ( ) ) ;
131
+ for ( addr, storage) in geth_data. block_trace . storage_trace . storage_proofs . iter ( ) {
132
+ log:: info!( "add addr {:?} to access_set" , addr) ;
133
+ access_set. add_account ( * addr) ;
134
+ access_set. add_code ( * addr) ;
135
+ for key in storage. keys ( ) {
136
+ log:: info!( "add addr {:?} key {:?} to access_set" , addr, key) ;
137
+ access_set. add_storage ( * addr, * key) ;
138
+ }
139
+ }
140
+ if let Some ( ref proofs) = geth_data. block_trace . storage_trace . proofs {
141
+ for addr in proofs. keys ( ) {
142
+ log:: info!( "add addr {:?} to access_set" , addr) ;
143
+ access_set. add_account ( * addr) ;
144
+ access_set. add_code ( * addr) ;
145
+ }
146
+ }
147
+ access_set
148
+ }
122
149
}
123
150
124
151
impl From < Vec < Access > > for AccessSet {
@@ -145,168 +172,3 @@ impl Default for CodeSource {
145
172
Self :: Tx
146
173
}
147
174
}
148
-
149
- /// Generate the State Access trace from the given trace. All state read/write
150
- /// accesses are reported, without distinguishing those that happen in revert
151
- /// sections.
152
- pub fn gen_state_access_trace < TX > (
153
- _block : & eth_types:: Block < TX > ,
154
- tx : & eth_types:: Transaction ,
155
- geth_trace : & GethExecTrace ,
156
- ) -> Result < Vec < Access > , Error > {
157
- let mut call_stack: Vec < ( Address , CodeSource ) > = Vec :: new ( ) ;
158
- let mut accs = vec ! [ Access :: new( None , WRITE , Account { address: tx. from } ) ] ;
159
- if let Some ( to) = tx. to {
160
- call_stack. push ( ( to, CodeSource :: Address ( to) ) ) ;
161
- accs. push ( Access :: new ( None , WRITE , Account { address : to } ) ) ;
162
- // Code may be null if the account is not a contract
163
- accs. push ( Access :: new ( None , READ , Code { address : to } ) ) ;
164
- } else {
165
- let address = get_contract_address ( tx. from , tx. nonce ) ;
166
- call_stack. push ( ( address, CodeSource :: Tx ) ) ;
167
- accs. push ( Access :: new ( None , WRITE , Account { address } ) ) ;
168
- accs. push ( Access :: new ( None , WRITE , Code { address } ) ) ;
169
- }
170
-
171
- for ( index, step) in geth_trace. struct_logs . iter ( ) . enumerate ( ) {
172
- let next_step = geth_trace. struct_logs . get ( index + 1 ) ;
173
- let i = Some ( index) ;
174
- let ( contract_address, code_source) = & call_stack[ call_stack. len ( ) - 1 ] ;
175
- let ( contract_address, code_source) = ( * contract_address, * code_source) ;
176
-
177
- let ( mut push_call_stack, mut pop_call_stack) = ( false , false ) ;
178
- if let Some ( next_step) = next_step {
179
- push_call_stack = step. depth + 1 == next_step. depth ;
180
- pop_call_stack = step. depth - 1 == next_step. depth ;
181
- }
182
-
183
- let result: Result < ( ) , Error > = ( || {
184
- match step. op {
185
- OpcodeId :: SSTORE => {
186
- let address = contract_address;
187
- let key = step. stack . nth_last ( 0 ) ?;
188
- accs. push ( Access :: new ( i, WRITE , Storage { address, key } ) ) ;
189
- }
190
- OpcodeId :: SLOAD => {
191
- let address = contract_address;
192
- let key = step. stack . nth_last ( 0 ) ?;
193
- accs. push ( Access :: new ( i, READ , Storage { address, key } ) ) ;
194
- }
195
- OpcodeId :: SELFBALANCE => {
196
- let address = contract_address;
197
- accs. push ( Access :: new ( i, READ , Account { address } ) ) ;
198
- }
199
- OpcodeId :: CODESIZE => {
200
- if let CodeSource :: Address ( address) = code_source {
201
- accs. push ( Access :: new ( i, READ , Code { address } ) ) ;
202
- }
203
- }
204
- OpcodeId :: CODECOPY => {
205
- if let CodeSource :: Address ( address) = code_source {
206
- accs. push ( Access :: new ( i, READ , Code { address } ) ) ;
207
- }
208
- }
209
- OpcodeId :: BALANCE => {
210
- let address = step. stack . nth_last ( 0 ) ?. to_address ( ) ;
211
- accs. push ( Access :: new ( i, READ , Account { address } ) ) ;
212
- }
213
- OpcodeId :: EXTCODEHASH => {
214
- let address = step. stack . nth_last ( 0 ) ?. to_address ( ) ;
215
- accs. push ( Access :: new ( i, READ , Account { address } ) ) ;
216
- }
217
- OpcodeId :: EXTCODESIZE => {
218
- let address = step. stack . nth_last ( 0 ) ?. to_address ( ) ;
219
- accs. push ( Access :: new ( i, READ , Code { address } ) ) ;
220
- }
221
- OpcodeId :: EXTCODECOPY => {
222
- let address = step. stack . nth_last ( 0 ) ?. to_address ( ) ;
223
- accs. push ( Access :: new ( i, READ , Code { address } ) ) ;
224
- }
225
- OpcodeId :: SELFDESTRUCT => {
226
- let address = contract_address;
227
- accs. push ( Access :: new ( i, WRITE , Account { address } ) ) ;
228
- let address = step. stack . nth_last ( 0 ) ?. to_address ( ) ;
229
- accs. push ( Access :: new ( i, WRITE , Account { address } ) ) ;
230
- }
231
- OpcodeId :: CREATE => {
232
- if push_call_stack {
233
- // Find CREATE result
234
- let address = get_call_result ( & geth_trace. struct_logs [ index..] )
235
- . unwrap_or_else ( Word :: zero)
236
- . to_address ( ) ;
237
- if !address. is_zero ( ) {
238
- accs. push ( Access :: new ( i, WRITE , Account { address } ) ) ;
239
- accs. push ( Access :: new ( i, WRITE , Code { address } ) ) ;
240
- }
241
- call_stack. push ( ( address, CodeSource :: Address ( address) ) ) ;
242
- }
243
- }
244
- OpcodeId :: CREATE2 => {
245
- if push_call_stack {
246
- // Find CREATE2 result
247
- let address = get_call_result ( & geth_trace. struct_logs [ index..] )
248
- . unwrap_or_else ( Word :: zero)
249
- . to_address ( ) ;
250
- if !address. is_zero ( ) {
251
- accs. push ( Access :: new ( i, WRITE , Account { address } ) ) ;
252
- accs. push ( Access :: new ( i, WRITE , Code { address } ) ) ;
253
- }
254
- call_stack. push ( ( address, CodeSource :: Address ( address) ) ) ;
255
- }
256
- }
257
- OpcodeId :: CALL => {
258
- let address = contract_address;
259
- accs. push ( Access :: new ( i, WRITE , Account { address } ) ) ;
260
-
261
- let address = step. stack . nth_last ( 1 ) ?. to_address ( ) ;
262
- accs. push ( Access :: new ( i, WRITE , Account { address } ) ) ;
263
- accs. push ( Access :: new ( i, READ , Code { address } ) ) ;
264
- if push_call_stack {
265
- call_stack. push ( ( address, CodeSource :: Address ( address) ) ) ;
266
- }
267
- }
268
- OpcodeId :: CALLCODE => {
269
- let address = contract_address;
270
- accs. push ( Access :: new ( i, WRITE , Account { address } ) ) ;
271
-
272
- let address = step. stack . nth_last ( 1 ) ?. to_address ( ) ;
273
- accs. push ( Access :: new ( i, WRITE , Account { address } ) ) ;
274
- accs. push ( Access :: new ( i, READ , Code { address } ) ) ;
275
- if push_call_stack {
276
- call_stack. push ( ( address, CodeSource :: Address ( address) ) ) ;
277
- }
278
- }
279
- OpcodeId :: DELEGATECALL => {
280
- let address = step. stack . nth_last ( 1 ) ?. to_address ( ) ;
281
- accs. push ( Access :: new ( i, READ , Code { address } ) ) ;
282
- if push_call_stack {
283
- call_stack. push ( ( contract_address, CodeSource :: Address ( address) ) ) ;
284
- }
285
- }
286
- OpcodeId :: STATICCALL => {
287
- let address = step. stack . nth_last ( 1 ) ?. to_address ( ) ;
288
- accs. push ( Access :: new ( i, READ , Code { address } ) ) ;
289
- if push_call_stack {
290
- call_stack. push ( ( address, CodeSource :: Address ( address) ) ) ;
291
- }
292
- }
293
- _ => { }
294
- }
295
- Ok ( ( ) )
296
- } ) ( ) ;
297
- if let Err ( e) = result {
298
- log:: warn!( "err when parsing access: {:?}, step {:?}" , e, step) ;
299
- }
300
-
301
- if pop_call_stack {
302
- if call_stack. len ( ) == 1 {
303
- return Err ( Error :: InvalidGethExecStep (
304
- "gen_state_access_trace: call stack will be empty" ,
305
- Box :: new ( step. clone ( ) ) ,
306
- ) ) ;
307
- }
308
- call_stack. pop ( ) . expect ( "call stack is empty" ) ;
309
- }
310
- }
311
- Ok ( accs)
312
- }
0 commit comments