33use crate :: {
44 evm_types:: { Gas , GasCost , OpcodeId , ProgramCounter } ,
55 EthBlock , GethCallTrace , GethExecError , GethExecStep , GethExecTrace , GethPrestateTrace , Hash ,
6- ToBigEndian , Transaction , Word , H256 ,
6+ ToBigEndian , Transaction , H256 ,
77} ;
88use ethers_core:: types:: {
99 transaction:: eip2930:: { AccessList , AccessListItem } ,
1010 Address , Bytes , U256 , U64 ,
1111} ;
12+ use itertools:: Itertools ;
1213use serde:: { Deserialize , Serialize } ;
1314use std:: collections:: HashMap ;
15+ use trace:: collect_codes;
16+
17+ /// Trace related helpers
18+ pub mod trace;
1419
1520#[ cfg( feature = "enable-memory" ) ]
1621use crate :: evm_types:: Memory ;
@@ -19,9 +24,64 @@ use crate::evm_types::Stack;
1924#[ cfg( feature = "enable-storage" ) ]
2025use crate :: evm_types:: Storage ;
2126
27+ /// l2 block full trace
28+ #[ derive( Deserialize , Serialize , Default , Debug , Clone ) ]
29+ pub struct BlockTraceV2 {
30+ /// chain id
31+ #[ serde( rename = "chainID" , default ) ]
32+ pub chain_id : u64 ,
33+ /// coinbase's status AFTER execution
34+ pub coinbase : AccountProofWrapper ,
35+ /// block
36+ pub header : EthBlock ,
37+ /// txs
38+ pub transactions : Vec < TransactionTrace > ,
39+ /// Accessed bytecodes with hashes
40+ pub codes : Vec < BytecodeTrace > ,
41+ /// storage trace BEFORE execution
42+ #[ serde( rename = "storageTrace" ) ]
43+ pub storage_trace : StorageTrace ,
44+ /// l1 tx queue
45+ #[ serde( rename = "startL1QueueIndex" , default ) ]
46+ pub start_l1_queue_index : u64 ,
47+ }
48+
49+ impl From < BlockTrace > for BlockTraceV2 {
50+ fn from ( b : BlockTrace ) -> Self {
51+ let codes = collect_codes ( & b, None )
52+ . expect ( "collect codes should not fail" )
53+ . into_iter ( )
54+ . map ( |( hash, code) | BytecodeTrace {
55+ hash,
56+ code : code. into ( ) ,
57+ } )
58+ . collect_vec ( ) ;
59+ BlockTraceV2 {
60+ codes,
61+ chain_id : b. chain_id ,
62+ coinbase : b. coinbase ,
63+ header : b. header ,
64+ transactions : b. transactions ,
65+ storage_trace : b. storage_trace ,
66+ start_l1_queue_index : b. start_l1_queue_index ,
67+ }
68+ }
69+ }
70+
71+ /// Bytecode
72+ #[ derive( Deserialize , Serialize , Default , Debug , Clone ) ]
73+ pub struct BytecodeTrace {
74+ /// poseidon code hash
75+ pub hash : H256 ,
76+ /// bytecode
77+ pub code : Bytes ,
78+ }
79+
2280/// l2 block full trace
2381#[ derive( Deserialize , Serialize , Default , Debug , Clone ) ]
2482pub struct BlockTrace {
83+ /// Version string
84+ pub version : String ,
2585 /// chain id
2686 #[ serde( rename = "chainID" , default ) ]
2787 pub chain_id : u64 ,
@@ -34,6 +94,9 @@ pub struct BlockTrace {
3494 /// execution results
3595 #[ serde( rename = "executionResults" ) ]
3696 pub execution_results : Vec < ExecutionResult > ,
97+ /// Accessed bytecodes with hashes
98+ #[ serde( default ) ]
99+ pub codes : Vec < BytecodeTrace > ,
37100 /// storage trace BEFORE execution
38101 #[ serde( rename = "storageTrace" ) ]
39102 pub storage_trace : StorageTrace ,
@@ -87,6 +150,30 @@ impl From<&BlockTrace> for EthBlock {
87150 }
88151}
89152
153+ impl From < & BlockTraceV2 > for revm_primitives:: BlockEnv {
154+ fn from ( block : & BlockTraceV2 ) -> Self {
155+ revm_primitives:: BlockEnv {
156+ number : revm_primitives:: U256 :: from ( block. header . number . unwrap ( ) . as_u64 ( ) ) ,
157+ coinbase : block. coinbase . address . unwrap ( ) . 0 . into ( ) ,
158+ timestamp : revm_primitives:: U256 :: from_be_bytes ( block. header . timestamp . to_be_bytes ( ) ) ,
159+ gas_limit : revm_primitives:: U256 :: from_be_bytes ( block. header . gas_limit . to_be_bytes ( ) ) ,
160+ basefee : revm_primitives:: U256 :: from_be_bytes (
161+ block
162+ . header
163+ . base_fee_per_gas
164+ . unwrap_or_default ( )
165+ . to_be_bytes ( ) ,
166+ ) ,
167+ difficulty : revm_primitives:: U256 :: from_be_bytes ( block. header . difficulty . to_be_bytes ( ) ) ,
168+ prevrandao : block
169+ . header
170+ . mix_hash
171+ . map ( |h| revm_primitives:: B256 :: from ( h. to_fixed_bytes ( ) ) ) ,
172+ blob_excess_gas_and_price : None ,
173+ }
174+ }
175+ }
176+
90177impl From < & BlockTrace > for revm_primitives:: BlockEnv {
91178 fn from ( block : & BlockTrace ) -> Self {
92179 revm_primitives:: BlockEnv {
@@ -247,7 +334,7 @@ impl From<&TransactionTrace> for revm_primitives::TxEnv {
247334/// account trie proof in storage proof
248335pub type AccountTrieProofs = HashMap < Address , Vec < Bytes > > ;
249336/// storage trie proof in storage proof
250- pub type StorageTrieProofs = HashMap < Address , HashMap < Word , Vec < Bytes > > > ;
337+ pub type StorageTrieProofs = HashMap < Address , HashMap < H256 , Vec < Bytes > > > ;
251338
252339/// storage trace
253340#[ derive( Deserialize , Serialize , Default , Debug , Clone ) ]
@@ -337,11 +424,11 @@ pub struct ExecStep {
337424 pub depth : isize ,
338425 pub error : Option < GethExecError > ,
339426 #[ cfg( feature = "enable-stack" ) ]
340- pub stack : Option < Vec < Word > > ,
427+ pub stack : Option < Vec < crate :: Word > > ,
341428 #[ cfg( feature = "enable-memory" ) ]
342- pub memory : Option < Vec < Word > > ,
429+ pub memory : Option < Vec < crate :: Word > > ,
343430 #[ cfg( feature = "enable-storage" ) ]
344- pub storage : Option < HashMap < Word , Word > > ,
431+ pub storage : Option < HashMap < crate :: Word , crate :: Word > > ,
345432 #[ serde( rename = "extraData" ) ]
346433 pub extra_data : Option < ExtraData > ,
347434}
@@ -402,6 +489,8 @@ pub struct AccountProofWrapper {
402489 pub keccak_code_hash : Option < H256 > ,
403490 #[ serde( rename = "poseidonCodeHash" ) ]
404491 pub poseidon_code_hash : Option < H256 > ,
492+ #[ serde( rename = "codeSize" ) ]
493+ pub code_size : u64 ,
405494 pub storage : Option < StorageProofWrapper > ,
406495}
407496
@@ -412,3 +501,15 @@ pub struct StorageProofWrapper {
412501 pub key : Option < U256 > ,
413502 pub value : Option < U256 > ,
414503}
504+
505+ #[ ignore]
506+ #[ test]
507+ fn test_block_trace_convert ( ) {
508+ let trace_v1: BlockTrace =
509+ crate :: utils:: from_json_file ( "src/testdata/trace_v1_5224657.json" ) . expect ( "should load" ) ;
510+ let trace_v2: BlockTraceV2 = trace_v1. into ( ) ;
511+ let mut fd = std:: fs:: File :: create ( "src/testdata/trace_v2_5224657.json" ) . unwrap ( ) ;
512+ serde_json:: to_writer_pretty ( & mut fd, & trace_v2) . unwrap ( ) ;
513+ // then we can use this command to compare the traces:
514+ // vimdiff <(jq -S "del(.executionResults)|del(.txStorageTraces)" src/testdata/trace_v1_5224657.json) <(jq -S . src/testdata/trace_v2_5224657.json)
515+ }
0 commit comments