loom_evm_db/
database_helpers.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use alloy::primitives::map::HashMap;
use alloy::primitives::{Address, U256};
use alloy::rpc::types::trace::geth::AccountState;
use revm::primitives::{Account, AccountStatus, Bytecode, EvmStorageSlot};
use revm::{DatabaseCommit, DatabaseRef};
use std::collections::BTreeMap;
use tracing::trace;

pub struct DatabaseHelpers {}

impl DatabaseHelpers {
    #[inline]
    pub fn trace_update_to_commit_update<DB: DatabaseRef>(db: &DB, update: BTreeMap<Address, AccountState>) -> HashMap<Address, Account> {
        let mut result: HashMap<Address, Account> = Default::default();
        for (address, state) in update {
            trace!(%address, code=state.code.is_some(), storage=state.storage.len(), "trace_update_to_commit_update");
            if address.is_zero() {
                continue;
            }
            let mut info = db.basic_ref(address).map(|a| a.unwrap_or_default()).unwrap_or_default();

            if let Some(code) = state.code {
                let code = Bytecode::new_raw(code);
                let hash = code.hash_slow();
                info.code_hash = hash;
                info.code = Some(code);
            }

            if let Some(nonce) = state.nonce {
                info.nonce = nonce
            }

            if let Some(balance) = state.balance {
                info.balance = balance
            }

            let storage = state.storage.into_iter().map(|(k, v)| (k.into(), EvmStorageSlot::new_changed(U256::ZERO, v.into()))).collect();

            result.insert(address, Account { info, storage, status: AccountStatus::Touched });
        }
        result
    }
    #[inline]
    pub fn apply_geth_state_update<DB: DatabaseRef + DatabaseCommit>(db: &mut DB, update: BTreeMap<Address, AccountState>) {
        let update = Self::trace_update_to_commit_update(db, update);
        db.commit(update);
    }

    #[inline]
    pub fn apply_geth_state_update_vec<DB: DatabaseRef + DatabaseCommit>(db: &mut DB, update_vec: Vec<BTreeMap<Address, AccountState>>) {
        let mut update_map: HashMap<Address, Account> = Default::default();

        for update in update_vec {
            let update_record = Self::trace_update_to_commit_update(db, update);
            update_map.extend(update_record);
        }
        db.commit(update_map)
    }
}