Skip to content

Commit 939e95f

Browse files
authored
chore(levm): improve storage_original_values hashmap and gen_db field names (#3261)
**Motivation** We can avoid a double lookup with `storage_original_values` by using a tuple. I found gen_db field names to be a bit confusing and not giving useful information, "immutable_cache" is not really a cache but a store for initial account states, so i changed it. Same with cache. **Description** <!-- A clear and concise general description of the changes this PR introduces --> <!-- Link to issues: Resolves #111, Resolves #222 --> Closes #issue_number
1 parent d9d68eb commit 939e95f

File tree

7 files changed

+52
-57
lines changed

7 files changed

+52
-57
lines changed

cmd/ef_tests/state/runner/levm_runner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ pub async fn ensure_post_state(
330330
fork: &Fork,
331331
db: &mut GeneralizedDatabase,
332332
) -> Result<(), EFTestRunnerError> {
333-
let cache = db.cache.clone();
333+
let cache = db.current_accounts_state.clone();
334334
match levm_execution_result {
335335
Ok(execution_report) => {
336336
match test.post.vector_post_value(vector, *fork).expect_exception {

cmd/ef_tests/state/runner/revm_runner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ pub async fn ensure_post_state(
376376
// We only want to compare account updates when no exception is expected.
377377
None => {
378378
let mut db = load_initial_state_levm(test).await;
379-
db.cache = levm_cache;
379+
db.current_accounts_state = levm_cache;
380380
let levm_account_updates = backends::levm::LEVM::get_state_transitions(&mut db)
381381
.map_err(|_| {
382382
InternalError::Custom("Error at LEVM::get_state_transitions()".to_owned())

crates/l2/sequencer/block_producer/payload_builder.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,9 @@ fn get_account_diffs_in_tx(
276276
})?;
277277
// First we add the account info
278278
for (address, original_account) in transaction_backup.original_accounts_info.iter() {
279-
let new_account =
280-
db.cache
281-
.get(address)
282-
.ok_or(BlockProducerError::FailedToGetDataFrom(
283-
"DB Cache".to_owned(),
284-
))?;
279+
let new_account = db.current_accounts_state.get(address).ok_or(
280+
BlockProducerError::FailedToGetDataFrom("DB Cache".to_owned()),
281+
)?;
285282

286283
let nonce_diff: u16 = (new_account.info.nonce - original_account.info.nonce)
287284
.try_into()
@@ -314,12 +311,9 @@ fn get_account_diffs_in_tx(
314311
for (address, original_storage_slots) in
315312
transaction_backup.original_account_storage_slots.iter()
316313
{
317-
let account_info =
318-
db.cache
319-
.get(address)
320-
.ok_or(BlockProducerError::FailedToGetDataFrom(
321-
"DB Cache".to_owned(),
322-
))?;
314+
let account_info = db.current_accounts_state.get(address).ok_or(
315+
BlockProducerError::FailedToGetDataFrom("DB Cache".to_owned()),
316+
)?;
323317

324318
let mut added_storage = BTreeMap::new();
325319
for key in original_storage_slots.keys() {

crates/vm/backends/levm/mod.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,10 @@ impl LEVM {
192192
db: &mut GeneralizedDatabase,
193193
) -> Result<Vec<AccountUpdate>, EvmError> {
194194
let mut account_updates: Vec<AccountUpdate> = vec![];
195-
for (address, new_state_account) in db.cache.iter() {
195+
for (address, new_state_account) in db.current_accounts_state.iter() {
196196
// In case the account is not in immutable_cache (rare) we search for it in the actual database.
197197
let initial_state_account =
198-
db.immutable_cache
198+
db.initial_accounts_state
199199
.get(address)
200200
.ok_or(EvmError::Custom(format!(
201201
"Failed to get account {address} from immutable cache",
@@ -258,8 +258,8 @@ impl LEVM {
258258

259259
account_updates.push(account_update);
260260
}
261-
db.cache.clear();
262-
db.immutable_cache.clear();
261+
db.current_accounts_state.clear();
262+
db.initial_accounts_state.clear();
263263
Ok(account_updates)
264264
}
265265

@@ -279,7 +279,7 @@ impl LEVM {
279279
.clone(); // Not a big deal cloning here because it's an EOA.
280280

281281
account.info.balance += increment.into();
282-
db.cache.insert(address, account);
282+
db.current_accounts_state.insert(address, account);
283283
}
284284
Ok(())
285285
}
@@ -435,8 +435,11 @@ pub fn generic_system_contract_levm(
435435
) -> Result<ExecutionReport, EvmError> {
436436
let chain_config = db.store.get_chain_config()?;
437437
let config = EVMConfig::new_from_chain_config(&chain_config, block_header);
438-
let system_account_backup = db.cache.get(&system_address).cloned();
439-
let coinbase_backup = db.cache.get(&block_header.coinbase).cloned();
438+
let system_account_backup = db.current_accounts_state.get(&system_address).cloned();
439+
let coinbase_backup = db
440+
.current_accounts_state
441+
.get(&block_header.coinbase)
442+
.cloned();
440443
let env = Environment {
441444
origin: system_address,
442445
// EIPs 2935, 4788, 7002 and 7251 dictate that the system calls have a gas limit of 30 million and they do not use intrinsic gas.
@@ -466,17 +469,19 @@ pub fn generic_system_contract_levm(
466469
let report = vm.execute().map_err(EvmError::from)?;
467470

468471
if let Some(system_account) = system_account_backup {
469-
db.cache.insert(system_address, system_account);
472+
db.current_accounts_state
473+
.insert(system_address, system_account);
470474
} else {
471475
// If the system account was not in the cache, we need to remove it
472-
db.cache.remove(&system_address);
476+
db.current_accounts_state.remove(&system_address);
473477
}
474478

475479
if let Some(coinbase_account) = coinbase_backup {
476-
db.cache.insert(block_header.coinbase, coinbase_account);
480+
db.current_accounts_state
481+
.insert(block_header.coinbase, coinbase_account);
477482
} else {
478483
// If the coinbase account was not in the cache, we need to remove it
479-
db.cache.remove(&block_header.coinbase);
484+
db.current_accounts_state.remove(&block_header.coinbase);
480485
}
481486

482487
Ok(report)

crates/vm/levm/src/db/gen_db.rs

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,17 @@ use super::cache;
2121
#[derive(Clone)]
2222
pub struct GeneralizedDatabase {
2323
pub store: Arc<dyn Database>,
24-
pub cache: CacheDB,
25-
pub immutable_cache: HashMap<Address, Account>,
24+
pub current_accounts_state: CacheDB,
25+
pub initial_accounts_state: HashMap<Address, Account>,
2626
pub tx_backup: Option<CallFrameBackup>,
2727
}
2828

2929
impl GeneralizedDatabase {
30-
pub fn new(store: Arc<dyn Database>, cache: CacheDB) -> Self {
30+
pub fn new(store: Arc<dyn Database>, current_accounts_state: CacheDB) -> Self {
3131
Self {
3232
store,
33-
cache: cache.clone(),
34-
immutable_cache: cache,
33+
current_accounts_state: current_accounts_state.clone(),
34+
initial_accounts_state: current_accounts_state,
3535
tx_backup: None,
3636
}
3737
}
@@ -40,11 +40,12 @@ impl GeneralizedDatabase {
4040
/// Gets account, first checking the cache and then the database
4141
/// (caching in the second case)
4242
pub fn get_account(&mut self, address: Address) -> Result<&Account, InternalError> {
43-
if !cache::account_is_cached(&self.cache, &address) {
43+
if !cache::account_is_cached(&self.current_accounts_state, &address) {
4444
let account = self.get_account_from_database(address)?;
45-
cache::insert_account(&mut self.cache, address, account);
45+
cache::insert_account(&mut self.current_accounts_state, address, account);
4646
}
47-
cache::get_account(&self.cache, &address).ok_or(InternalError::AccountNotFound)
47+
cache::get_account(&self.current_accounts_state, &address)
48+
.ok_or(InternalError::AccountNotFound)
4849
}
4950

5051
/// **Accesses to an account's information.**
@@ -62,25 +63,25 @@ impl GeneralizedDatabase {
6263
Ok((account, address_was_cold))
6364
}
6465

65-
/// Gets account from storage, storing in Immutable Cache for efficiency when getting AccountUpdates.
66+
/// Gets account from storage, storing in initial_accounts_state for efficiency when getting AccountUpdates.
6667
pub fn get_account_from_database(
6768
&mut self,
6869
address: Address,
6970
) -> Result<Account, InternalError> {
7071
let account = self.store.get_account(address)?;
71-
self.immutable_cache.insert(address, account.clone());
72+
self.initial_accounts_state.insert(address, account.clone());
7273
Ok(account)
7374
}
7475

75-
/// Gets storage slot from Database, storing in Immutable Cache for efficiency when getting AccountUpdates.
76+
/// Gets storage slot from Database, storing in initial_accounts_state for efficiency when getting AccountUpdates.
7677
pub fn get_value_from_database(
7778
&mut self,
7879
address: Address,
7980
key: H256,
8081
) -> Result<U256, InternalError> {
8182
let value = self.store.get_storage_value(address, key)?;
82-
// Account must already be in immutable_cache
83-
match self.immutable_cache.get_mut(&address) {
83+
// Account must already be in initial_accounts_state
84+
match self.initial_accounts_state.get_mut(&address) {
8485
Some(account) => {
8586
account.storage.insert(key, value);
8687
}
@@ -133,15 +134,15 @@ impl<'a> VM<'a> {
133134
134135
*/
135136
pub fn get_account_mut(&mut self, address: Address) -> Result<&mut Account, InternalError> {
136-
if cache::is_account_cached(&self.db.cache, &address) {
137+
if cache::is_account_cached(&self.db.current_accounts_state, &address) {
137138
self.backup_account_info(address)?;
138-
cache::get_account_mut(&mut self.db.cache, &address)
139+
cache::get_account_mut(&mut self.db.current_accounts_state, &address)
139140
.ok_or(InternalError::AccountNotFound)
140141
} else {
141142
let acc = self.db.get_account_from_database(address)?;
142-
cache::insert_account(&mut self.db.cache, address, acc);
143+
cache::insert_account(&mut self.db.current_accounts_state, address, acc);
143144
self.backup_account_info(address)?;
144-
cache::get_account_mut(&mut self.db.cache, &address)
145+
cache::get_account_mut(&mut self.db.current_accounts_state, &address)
145146
.ok_or(InternalError::AccountNotFound)
146147
}
147148
}
@@ -214,7 +215,7 @@ impl<'a> VM<'a> {
214215
account: Account,
215216
) -> Result<(), InternalError> {
216217
self.backup_account_info(address)?;
217-
let _ = cache::insert_account(&mut self.db.cache, address, account);
218+
let _ = cache::insert_account(&mut self.db.current_accounts_state, address, account);
218219

219220
Ok(())
220221
}
@@ -226,19 +227,12 @@ impl<'a> VM<'a> {
226227
address: Address,
227228
key: H256,
228229
) -> Result<U256, InternalError> {
229-
if let Some(value) = self
230-
.storage_original_values
231-
.get(&address)
232-
.and_then(|account_storage| account_storage.get(&key))
233-
{
230+
if let Some(value) = self.storage_original_values.get(&(address, key)) {
234231
return Ok(*value);
235232
}
236233

237234
let value = self.get_storage_value(address, key)?;
238-
self.storage_original_values
239-
.entry(address)
240-
.or_default()
241-
.insert(key, value);
235+
self.storage_original_values.insert((address, key), value);
242236
Ok(value)
243237
}
244238

@@ -270,7 +264,7 @@ impl<'a> VM<'a> {
270264
address: Address,
271265
key: H256,
272266
) -> Result<U256, InternalError> {
273-
if let Some(account) = cache::get_account(&self.db.cache, &address) {
267+
if let Some(account) = cache::get_account(&self.db.current_accounts_state, &address) {
274268
if let Some(value) = account.storage.get(&key) {
275269
return Ok(*value);
276270
}
@@ -333,7 +327,7 @@ impl<'a> VM<'a> {
333327
.contains_key(&address);
334328

335329
if is_not_backed_up {
336-
let account = cache::get_account(&self.db.cache, &address)
330+
let account = cache::get_account(&self.db.current_accounts_state, &address)
337331
.ok_or(InternalError::AccountNotFound)?;
338332
let info = account.info.clone();
339333
let code = account.code.clone();

crates/vm/levm/src/utils.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ pub fn restore_cache_state(
130130
callframe_backup: CallFrameBackup,
131131
) -> Result<(), VMError> {
132132
for (address, account) in callframe_backup.original_accounts_info {
133-
if let Some(current_account) = cache::get_account_mut(&mut db.cache, &address) {
133+
if let Some(current_account) =
134+
cache::get_account_mut(&mut db.current_accounts_state, &address)
135+
{
134136
current_account.info = account.info;
135137
current_account.code = account.code;
136138
}
@@ -140,7 +142,7 @@ pub fn restore_cache_state(
140142
// This call to `get_account_mut` should never return None, because we are looking up accounts
141143
// that had their storage modified, which means they should be in the cache. That's why
142144
// we return an internal error in case we haven't found it.
143-
let account = cache::get_account_mut(&mut db.cache, &address)
145+
let account = cache::get_account_mut(&mut db.current_accounts_state, &address)
144146
.ok_or(InternalError::AccountNotFound)?;
145147

146148
for (key, value) in storage {

crates/vm/levm/src/vm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub struct VM<'a> {
4747
pub hooks: Vec<Rc<RefCell<dyn Hook>>>,
4848
pub substate_backups: Vec<Substate>,
4949
/// Original storage values before the transaction. Used for gas calculations in SSTORE.
50-
pub storage_original_values: HashMap<Address, HashMap<H256, U256>>,
50+
pub storage_original_values: HashMap<(Address, H256), U256>,
5151
/// When enabled, it "logs" relevant information during execution
5252
pub tracer: LevmCallTracer,
5353
/// Mode for printing some useful stuff, only used in development!

0 commit comments

Comments
 (0)