Skip to content

Commit 92a287a

Browse files
authored
fix: cache analyzed code (#67)
1 parent 1e6ed00 commit 92a287a

File tree

1 file changed

+27
-15
lines changed

1 file changed

+27
-15
lines changed

crates/core/src/database.rs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::error::DatabaseError;
2+
use revm::interpreter::analysis::to_analysed;
23
use 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>;
2324
pub 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

126145
impl<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

Comments
 (0)