@@ -32,23 +32,34 @@ impl<'a> LocalTraceIdentifier<'a> {
3232 self . known_contracts
3333 }
3434
35- /// Tries to the bytecode most similar to the given one.
36- pub fn identify_code ( & self , code : & [ u8 ] ) -> Option < ( & ' a ArtifactId , & ' a JsonAbi ) > {
37- let len = code. len ( ) ;
35+ /// Identifies the artifact based on score computed for both creation and deployed bytecodes.
36+ pub fn identify_code (
37+ & self ,
38+ runtime_code : & [ u8 ] ,
39+ creation_code : & [ u8 ] ,
40+ ) -> Option < ( & ' a ArtifactId , & ' a JsonAbi ) > {
41+ let len = runtime_code. len ( ) ;
3842
3943 let mut min_score = f64:: MAX ;
4044 let mut min_score_id = None ;
4145
42- let mut check = |id| {
46+ let mut check = |id, is_creation , min_score : & mut f64 | {
4347 let contract = self . known_contracts . get ( id) ?;
44- if let Some ( deployed_bytecode) = contract. deployed_bytecode ( ) {
45- let score = bytecode_diff_score ( deployed_bytecode, code) ;
48+ // Select bytecodes to compare based on `is_creation` flag.
49+ let ( contract_bytecode, current_bytecode) = if is_creation {
50+ ( contract. bytecode ( ) , creation_code)
51+ } else {
52+ ( contract. deployed_bytecode ( ) , runtime_code)
53+ } ;
54+
55+ if let Some ( bytecode) = contract_bytecode {
56+ let score = bytecode_diff_score ( bytecode, current_bytecode) ;
4657 if score == 0.0 {
4758 trace ! ( target: "evm::traces" , "found exact match" ) ;
4859 return Some ( ( id, & contract. abi ) ) ;
4960 }
50- if score < min_score {
51- min_score = score;
61+ if score < * min_score {
62+ * min_score = score;
5263 min_score_id = Some ( ( id, & contract. abi ) ) ;
5364 }
5465 }
@@ -65,7 +76,7 @@ impl<'a> LocalTraceIdentifier<'a> {
6576 if len > max_len {
6677 break ;
6778 }
68- if let found @ Some ( _) = check ( id) {
79+ if let found @ Some ( _) = check ( id, true , & mut min_score ) {
6980 return found;
7081 }
7182 }
@@ -75,11 +86,20 @@ impl<'a> LocalTraceIdentifier<'a> {
7586 let idx = self . find_index ( min_len) ;
7687 for i in idx..same_length_idx {
7788 let ( id, _) = self . ordered_ids [ i] ;
78- if let found @ Some ( _) = check ( id) {
89+ if let found @ Some ( _) = check ( id, true , & mut min_score ) {
7990 return found;
8091 }
8192 }
8293
94+ // Fallback to comparing deployed code if min score greater than threshold.
95+ if min_score >= 0.85 {
96+ for ( artifact, _) in & self . ordered_ids {
97+ if let found @ Some ( _) = check ( artifact, false , & mut min_score) {
98+ return found;
99+ }
100+ }
101+ }
102+
83103 trace ! ( target: "evm::traces" , %min_score, "no exact match found" ) ;
84104
85105 // Note: the diff score can be inaccurate for small contracts so we're using a relatively
@@ -109,16 +129,16 @@ impl<'a> LocalTraceIdentifier<'a> {
109129impl TraceIdentifier for LocalTraceIdentifier < ' _ > {
110130 fn identify_addresses < ' a , A > ( & mut self , addresses : A ) -> Vec < AddressIdentity < ' _ > >
111131 where
112- A : Iterator < Item = ( & ' a Address , Option < & ' a [ u8 ] > ) > ,
132+ A : Iterator < Item = ( & ' a Address , Option < & ' a [ u8 ] > , Option < & ' a [ u8 ] > ) > ,
113133 {
114134 trace ! ( target: "evm::traces" , "identify {:?} addresses" , addresses. size_hint( ) . 1 ) ;
115135
116136 addresses
117- . filter_map ( |( address, code ) | {
137+ . filter_map ( |( address, runtime_code , creation_code ) | {
118138 let _span = trace_span ! ( target: "evm::traces" , "identify" , %address) . entered ( ) ;
119139
120140 trace ! ( target: "evm::traces" , "identifying" ) ;
121- let ( id, abi) = self . identify_code ( code ?) ?;
141+ let ( id, abi) = self . identify_code ( runtime_code? , creation_code ?) ?;
122142 trace ! ( target: "evm::traces" , id=%id. identifier( ) , "identified" ) ;
123143
124144 Some ( AddressIdentity {
0 commit comments