11use crate :: error:: DatabaseError ;
2+ use revm:: interpreter:: analysis:: to_analysed;
23use revm:: {
34 db:: DatabaseRef ,
45 primitives:: { AccountInfo , Address , Bytecode , B256 , U256 } ,
@@ -23,6 +24,8 @@ type Result<T, E = DatabaseError> = std::result::Result<T, E>;
2324pub struct EvmDatabase < ' a , CodeDb , ZkDb > {
2425 /// Map of code hash to bytecode.
2526 pub ( crate ) code_db : & ' a mut CodeDb ,
27+ /// Cache of analyzed code
28+ analyzed_code_cache : RefCell < HashMap < B256 , Option < Bytecode > > > ,
2629 /// Storage root cache, avoid re-query account when storage root is needed
2730 storage_root_caches : RefCell < HashMap < Address , ZkHash > > ,
2831 /// Storage trie cache, avoid re-creating trie for the same account.
@@ -56,6 +59,7 @@ impl<'a, CodeDb: KVDatabase, ZkDb: KVDatabase + 'static> EvmDatabase<'a, CodeDb,
5659
5760 Ok ( EvmDatabase {
5861 code_db,
62+ analyzed_code_cache : Default :: default ( ) ,
5963 storage_root_caches : Default :: default ( ) ,
6064 storage_trie_caches : Default :: default ( ) ,
6165 committed_zktrie_root,
@@ -121,6 +125,21 @@ impl<'a, CodeDb: KVDatabase, ZkDb: KVDatabase + 'static> EvmDatabase<'a, CodeDb,
121125 cycle_tracker_end ! ( "insert CodeDB" ) ;
122126 Ok ( ( ) )
123127 }
128+
129+ fn load_code ( & self , hash : B256 ) -> Result < Option < Bytecode > > {
130+ let mut code_cache = self . analyzed_code_cache . borrow_mut ( ) ;
131+ if let Some ( code) = code_cache. get ( & hash) {
132+ Ok ( code. clone ( ) )
133+ } else {
134+ let code = self
135+ . code_db
136+ . get ( & hash)
137+ . map_err ( DatabaseError :: code_db) ?
138+ . map ( |v| to_analysed ( Bytecode :: new_legacy ( v. into_bytes ( ) . into ( ) ) ) ) ;
139+ code_cache. insert ( hash, code. clone ( ) ) ;
140+ Ok ( code)
141+ }
142+ }
124143}
125144
126145impl < CodeDb : KVDatabase , ZkDb : KVDatabase + ' static > DatabaseRef for EvmDatabase < ' _ , CodeDb , ZkDb > {
@@ -142,11 +161,8 @@ impl<CodeDb: KVDatabase, ZkDb: KVDatabase + 'static> DatabaseRef for EvmDatabase
142161 . insert ( address, account. storage_root ) ;
143162
144163 let mut info = AccountInfo :: from ( account) ;
145- info. code = self
146- . code_db
147- . get ( & account. code_hash )
148- . map_err ( DatabaseError :: code_db) ?
149- . map ( |v| Bytecode :: new_legacy ( v. into_bytes ( ) . into ( ) ) ) ;
164+ info. code = self . load_code ( account. code_hash ) ?;
165+
150166 if let Some ( ref code) = info. code {
151167 debug_assert_eq ! (
152168 info. code_hash,
@@ -170,16 +186,12 @@ impl<CodeDb: KVDatabase, ZkDb: KVDatabase + 'static> DatabaseRef for EvmDatabase
170186 // then the upcoming trace contains code (meaning the code is used in this new block),
171187 // we can't directly update the CacheDB, so we offer the code by hash here.
172188 // However, if the code still cannot be found, this is an error.
173- self . code_db
174- . get ( & hash)
175- . map_err ( DatabaseError :: code_db) ?
176- . map ( |v| Bytecode :: new_legacy ( v. into_bytes ( ) . into ( ) ) )
177- . ok_or_else ( || {
178- unreachable ! (
179- "Code is either loaded or not needed (like EXTCODESIZE), code hash: {:?}" ,
180- hash
181- ) ;
182- } )
189+ self . load_code ( hash) ?. ok_or_else ( || {
190+ unreachable ! (
191+ "Code is either loaded or not needed (like EXTCODESIZE), code hash: {:?}" ,
192+ hash
193+ ) ;
194+ } )
183195 }
184196
185197 /// Get storage value of address at index.
0 commit comments