@@ -2,247 +2,16 @@ pub use super::block::{Block, BlockContext};
22use crate :: {
33 circuit_input_builder:: { self , BlockHead , CircuitInputBuilder , CircuitsParams } ,
44 error:: Error ,
5- precompile:: is_precompiled,
6- state_db:: { self , CodeDB , StateDB } ,
75} ;
86use eth_types:: {
97 self ,
10- evm_types :: OpcodeId ,
11- l2_types :: { BlockTrace , EthBlock , ExecStep , StorageTrace } ,
12- Address , ToWord , Word , H256 ,
8+ l2_types :: { BlockTrace , EthBlock , StorageTrace } ,
9+ state_db :: { self , CodeDB , StateDB } ,
10+ Address , ToWord , Word ,
1311} ;
1412use ethers_core:: types:: Bytes ;
15- use mpt_zktrie:: state:: { AccountData , ZktrieState } ;
16- use std:: collections:: hash_map:: { Entry , HashMap } ;
17-
18- impl From < & AccountData > for state_db:: Account {
19- fn from ( acc_data : & AccountData ) -> Self {
20- if acc_data. keccak_code_hash . is_zero ( ) {
21- state_db:: Account :: zero ( )
22- } else {
23- Self {
24- nonce : acc_data. nonce . into ( ) ,
25- balance : acc_data. balance ,
26- code_hash : acc_data. poseidon_code_hash ,
27- keccak_code_hash : acc_data. keccak_code_hash ,
28- code_size : acc_data. code_size . into ( ) ,
29- storage : Default :: default ( ) ,
30- }
31- }
32- }
33- }
34-
35- fn decode_bytecode ( bytecode : & str ) -> Result < Vec < u8 > , Error > {
36- let mut stripped = if let Some ( stripped) = bytecode. strip_prefix ( "0x" ) {
37- stripped. to_string ( )
38- } else {
39- bytecode. to_string ( )
40- } ;
41-
42- let bytecode_len = stripped. len ( ) as u64 ;
43- if ( bytecode_len & 1 ) != 0 {
44- stripped = format ! ( "0{stripped}" ) ;
45- }
46-
47- hex:: decode ( stripped) . map_err ( Error :: HexError )
48- }
49-
50- fn trace_code (
51- cdb : & mut CodeDB ,
52- code_hash : Option < H256 > ,
53- code : Bytes ,
54- step : & ExecStep ,
55- addr : Option < Address > ,
56- sdb : & StateDB ,
57- ) {
58- // first, try to read from sdb
59- // let stack = match step.stack.as_ref() {
60- // Some(stack) => stack,
61- // None => {
62- // log::error!("stack underflow, step {step:?}");
63- // return;
64- // }
65- // };
66- // if stack_pos >= stack.len() {
67- // log::error!("stack underflow, step {step:?}");
68- // return;
69- // }
70- // let addr = stack[stack.len() - stack_pos - 1].to_address(); //stack N-stack_pos
71- //
72- let code_hash = code_hash. or_else ( || {
73- addr. and_then ( |addr| {
74- let ( _existed, acc_data) = sdb. get_account ( & addr) ;
75- if acc_data. code_hash != CodeDB :: empty_code_hash ( ) && !code. is_empty ( ) {
76- // they must be same
77- Some ( acc_data. code_hash )
78- } else {
79- // let us re-calculate it
80- None
81- }
82- } )
83- } ) ;
84- let code_hash = match code_hash {
85- Some ( code_hash) => {
86- if code_hash. is_zero ( ) {
87- CodeDB :: hash ( & code)
88- } else {
89- if log:: log_enabled!( log:: Level :: Trace ) {
90- assert_eq ! (
91- code_hash,
92- CodeDB :: hash( & code) ,
93- "bytecode len {:?}, step {:?}" ,
94- code. len( ) ,
95- step
96- ) ;
97- }
98- code_hash
99- }
100- }
101- None => {
102- let hash = CodeDB :: hash ( & code) ;
103- log:: debug!(
104- "hash_code done: addr {addr:?}, size {}, hash {hash:?}" ,
105- & code. len( )
106- ) ;
107- hash
108- }
109- } ;
110-
111- cdb. 0 . entry ( code_hash) . or_insert_with ( || {
112- log:: trace!(
113- "trace code addr {:?}, size {} hash {:?}" ,
114- addr,
115- & code. len( ) ,
116- code_hash
117- ) ;
118- code. to_vec ( )
119- } ) ;
120- }
121-
122- fn update_codedb ( cdb : & mut CodeDB , sdb : & StateDB , block : & BlockTrace ) -> Result < ( ) , Error > {
123- log:: debug!( "build_codedb for block {:?}" , block. header. number) ;
124- for ( er_idx, execution_result) in block. execution_results . iter ( ) . enumerate ( ) {
125- if let Some ( bytecode) = & execution_result. byte_code {
126- let bytecode = decode_bytecode ( bytecode) ?. to_vec ( ) ;
127-
128- let code_hash = execution_result
129- . to
130- . as_ref ( )
131- . and_then ( |t| t. poseidon_code_hash )
132- . unwrap_or_else ( || CodeDB :: hash ( & bytecode) ) ;
133- let code_hash = if code_hash. is_zero ( ) {
134- CodeDB :: hash ( & bytecode)
135- } else {
136- code_hash
137- } ;
138- if let Entry :: Vacant ( e) = cdb. 0 . entry ( code_hash) {
139- e. insert ( bytecode) ;
140- //log::debug!("inserted tx bytecode {:?} {:?}", code_hash, hash);
141- }
142- if execution_result. account_created . is_none ( ) {
143- //assert_eq!(Some(hash), execution_result.code_hash);
144- }
145- }
146-
147- // filter all precompile calls, empty calls and create
148- let mut call_trace = execution_result
149- . call_trace
150- . flatten_trace ( & execution_result. prestate )
151- . into_iter ( )
152- . filter ( |call| {
153- let is_call_to_precompile = call. to . as_ref ( ) . map ( is_precompiled) . unwrap_or ( false ) ;
154- let is_call_to_empty = call. gas_used . is_zero ( )
155- && !call. call_type . is_create ( )
156- && call. is_callee_code_empty ;
157- !( is_call_to_precompile || is_call_to_empty || call. call_type . is_create ( ) )
158- } )
159- . collect :: < Vec < _ > > ( ) ;
160- log:: trace!( "call_trace: {call_trace:?}" ) ;
161-
162- for ( idx, step) in execution_result. exec_steps . iter ( ) . enumerate ( ) . rev ( ) {
163- if step. op . is_create ( ) {
164- continue ;
165- }
166- let call = if step. op . is_call_or_create ( ) {
167- // filter call to empty/precompile/!precheck_ok
168- if let Some ( next_step) = execution_result. exec_steps . get ( idx + 1 ) {
169- // the call doesn't have inner steps, it could be:
170- // - a call to a precompiled contract
171- // - a call to an empty account
172- // - a call that !is_precheck_ok
173- if next_step. depth != step. depth + 1 {
174- log:: trace!( "skip call step due to no inner step, curr: {step:?}, next: {next_step:?}" ) ;
175- continue ;
176- }
177- } else {
178- // this is the final step, no inner steps
179- log:: trace!( "skip call step due this is the final step: {step:?}" ) ;
180- continue ;
181- }
182- let call = call_trace. pop ( ) ;
183- log:: trace!( "call_trace pop: {call:?}, current step: {step:?}" ) ;
184- call
185- } else {
186- None
187- } ;
188-
189- if let Some ( data) = & step. extra_data {
190- match step. op {
191- OpcodeId :: CALL
192- | OpcodeId :: CALLCODE
193- | OpcodeId :: DELEGATECALL
194- | OpcodeId :: STATICCALL => {
195- let call = call. unwrap ( ) ;
196- assert_eq ! ( call. call_type, step. op, "{call:?}" ) ;
197- let code_idx = if block. transactions [ er_idx] . to . is_none ( ) {
198- 0
199- } else {
200- 1
201- } ;
202- let callee_code = data. get_code_at ( code_idx) ;
203- // TODO: make nil code ("0x") is not None and assert None case
204- // assert!(
205- // callee_code.is_none(),
206- // "invalid trace: cannot get code of call: {step:?}"
207- // );
208- let code_hash = match step. op {
209- OpcodeId :: CALL | OpcodeId :: CALLCODE => data. get_code_hash_at ( 1 ) ,
210- OpcodeId :: STATICCALL => data. get_code_hash_at ( 0 ) ,
211- _ => None ,
212- } ;
213- let addr = call. to . unwrap ( ) ;
214- trace_code (
215- cdb,
216- code_hash,
217- callee_code. unwrap_or_default ( ) ,
218- step,
219- Some ( addr) ,
220- sdb,
221- ) ;
222- }
223- OpcodeId :: CREATE | OpcodeId :: CREATE2 => {
224- // notice we do not need to insert code for CREATE,
225- // bustmapping do this job
226- unreachable ! ( )
227- }
228- OpcodeId :: EXTCODESIZE | OpcodeId :: EXTCODECOPY => {
229- let code = data. get_code_at ( 0 ) ;
230- if code. is_none ( ) {
231- log:: warn!( "unable to fetch code from step. {step:?}" ) ;
232- continue ;
233- }
234- trace_code ( cdb, None , code. unwrap ( ) , step, None , sdb) ;
235- }
236-
237- _ => { }
238- }
239- }
240- }
241- }
242-
243- log:: debug!( "updating codedb done" ) ;
244- Ok ( ( ) )
245- }
13+ use mpt_zktrie:: state:: ZktrieState ;
14+ use std:: collections:: hash_map:: HashMap ;
24615
24716fn dump_code_db ( cdb : & CodeDB ) {
24817 for ( k, v) in & cdb. 0 {
@@ -404,7 +173,7 @@ impl CircuitInputBuilder {
404173
405174 let mut code_db = CodeDB :: new ( ) ;
406175 code_db. insert ( Vec :: new ( ) ) ;
407- update_codedb ( & mut code_db , & sdb, & l2_trace) ?;
176+ code_db . update_codedb ( & sdb, & l2_trace) ?;
408177
409178 let mut builder_block = circuit_input_builder:: Block :: from_headers ( & [ ] , circuits_params) ;
410179 builder_block. chain_id = chain_id;
@@ -475,7 +244,7 @@ impl CircuitInputBuilder {
475244 * self . sdb . get_storage_mut ( & addr, & key) . 1 = val;
476245 }
477246
478- update_codedb ( & mut self . code_db , & self . sdb , & l2_trace) ?;
247+ self . code_db . update_codedb ( & self . sdb , & l2_trace) ?;
479248
480249 self . apply_l2_trace ( l2_trace, !more) ?;
481250 Ok ( ( ) )
0 commit comments