kabu_evm_db/
database_helpers.rs

1use crate::fast_cache_db::FastDbAccount;
2use alloy::primitives::map::HashMap;
3use alloy::primitives::{Address, U256};
4use alloy::rpc::types::trace::geth::AccountState;
5use revm::bytecode::Bytecode;
6use revm::state::{Account, EvmStorageSlot};
7use revm::{DatabaseCommit, DatabaseRef};
8use std::collections::BTreeMap;
9use tracing::trace;
10
11pub struct DatabaseHelpers {}
12
13impl DatabaseHelpers {
14    #[inline]
15    pub fn account_db_to_revm(db: FastDbAccount) -> Account {
16        let storage = db.storage.into_iter().map(|(k, v)| (k, EvmStorageSlot::new(v, 0))).collect();
17        Account { info: db.info, storage, status: Default::default(), transaction_id: 0 }
18    }
19
20    #[inline]
21    pub fn trace_update_to_commit_update<DB: DatabaseRef>(db: &DB, update: BTreeMap<Address, AccountState>) -> HashMap<Address, Account> {
22        let mut result: HashMap<Address, Account> = Default::default();
23        for (address, state) in update {
24            trace!(%address, code=state.code.is_some(), storage=state.storage.len(), "trace_update_to_commit_update");
25            if address.is_zero() {
26                continue;
27            }
28            let mut info = db.basic_ref(address).map(|a| a.unwrap_or_default()).unwrap_or_default();
29
30            if let Some(code) = state.code {
31                let code = Bytecode::new_raw(code);
32                let hash = code.hash_slow();
33                info.code_hash = hash;
34                info.code = Some(code);
35            }
36
37            if let Some(nonce) = state.nonce {
38                info.nonce = nonce
39            }
40
41            if let Some(balance) = state.balance {
42                info.balance = balance
43            }
44
45            let storage =
46                state.storage.into_iter().map(|(k, v)| (k.into(), EvmStorageSlot::new_changed(U256::ZERO, v.into(), 0))).collect();
47
48            result.insert(address, Account { info, storage, status: Default::default(), transaction_id: 0 });
49        }
50        result
51    }
52    #[inline]
53    pub fn apply_geth_state_update<DB: DatabaseRef + DatabaseCommit>(db: &mut DB, update: BTreeMap<Address, AccountState>) {
54        let update = Self::trace_update_to_commit_update(db, update);
55        db.commit(update);
56    }
57
58    #[inline]
59    pub fn apply_geth_state_update_vec<DB: DatabaseRef + DatabaseCommit>(db: &mut DB, update_vec: Vec<BTreeMap<Address, AccountState>>) {
60        let mut update_map: HashMap<Address, Account> = Default::default();
61
62        for update in update_vec {
63            let update_record = Self::trace_update_to_commit_update(db, update);
64            update_map.extend(update_record);
65        }
66        db.commit(update_map)
67    }
68}