loom_evm_db/
in_memory_db.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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::fast_cache_db::FastCacheDB;
use alloy::primitives::Address;
use alloy::rpc::types::trace::geth::AccountState as GethAccountState;
use revm::db::{AccountState, EmptyDB};
use revm::primitives::Bytecode;
use std::collections::BTreeMap;
use std::sync::Arc;
use tracing::{error, trace};

pub type LoomInMemoryDB = FastCacheDB<Arc<FastCacheDB<EmptyDB>>>;

impl LoomInMemoryDB {
    pub fn with_db(self, db: Arc<FastCacheDB<EmptyDB>>) -> Self {
        Self { db, ..self }
    }

    pub fn merge(&self) -> FastCacheDB<EmptyDB> {
        let mut db: FastCacheDB<EmptyDB> = FastCacheDB {
            accounts: self.db.accounts.clone(),
            logs: self.db.logs.clone(),
            contracts: self.db.contracts.clone(),
            block_hashes: self.db.block_hashes.clone(),
            db: self.db.db,
        };
        for (k, v) in self.block_hashes.iter() {
            db.block_hashes.insert(*k, *v);
        }
        for (k, v) in self.contracts.iter() {
            db.contracts.insert(*k, v.clone());
        }
        db.logs.clone_from(&self.logs);
        for (address, account) in self.accounts.iter() {
            let mut info = account.info.clone();
            db.insert_contract(&mut info);

            let entry = db.accounts.entry(*address).or_default();
            entry.info = info;
            for (k, v) in account.storage.iter() {
                entry.storage.insert(*k, *v);
            }
        }
        db
    }

    pub fn update_accounts(&self) -> FastCacheDB<EmptyDB> {
        let mut db = (*self.db.as_ref()).clone();

        for (k, v) in self.block_hashes.iter() {
            db.block_hashes.insert(*k, *v);
        }
        for (k, v) in self.contracts.iter() {
            db.contracts.entry(*k).and_modify(|k| k.clone_from(v));
        }
        db.logs.clone_from(&self.logs);

        for (address, account) in self.accounts.iter() {
            db.accounts.entry(*address).and_modify(|db_account| {
                let info = account.info.clone();
                db_account.info = info;
                for (k, v) in account.storage.iter() {
                    db_account.storage.insert(*k, *v);
                }
                db_account.account_state = AccountState::Touched
            });
        }
        db
    }

    pub fn update_cells(&self) -> FastCacheDB<EmptyDB> {
        let mut db = self.db.as_ref().clone();

        for (k, v) in self.block_hashes.iter() {
            db.block_hashes.insert(*k, *v);
        }
        for (k, v) in self.contracts.iter() {
            db.contracts.entry(*k).and_modify(|k| k.clone_from(v));
        }
        db.logs.clone_from(&self.logs);

        for (address, account) in self.accounts.iter() {
            db.accounts.entry(*address).and_modify(|db_account| {
                let info = account.info.clone();
                db_account.info = info;
                for (k, v) in account.storage.iter() {
                    db_account.storage.entry(*k).and_modify(|cv| cv.clone_from(v));
                }
                db_account.account_state = AccountState::Touched
            });
        }
        db
    }

    #[allow(irrefutable_let_patterns)]
    pub fn apply_geth_update(&mut self, update: BTreeMap<Address, GethAccountState>) {
        for (addr, acc_state) in update {
            trace!("apply_geth_update {} is code {} storage_len {} ", addr, acc_state.code.is_some(), acc_state.storage.len());

            for (k, v) in acc_state.storage.iter() {
                if let Err(e) = self.insert_account_storage(addr, (*k).into(), (*v).into()) {
                    error!("apply_geth_update :{}", e);
                }
            }

            if let Ok(account) = self.load_account(addr) {
                if let Some(code) = acc_state.code.clone() {
                    let bytecode = Bytecode::new_raw(code);
                    account.info.code_hash = bytecode.hash_slow();
                    account.info.code = Some(bytecode);
                }
                if let Some(nonce) = acc_state.nonce {
                    //trace!("nonce : {} -> {}", account.info.nonce, nonce);
                    account.info.nonce = nonce;
                }
                if let Some(balance) = acc_state.balance {
                    account.info.balance = balance;
                }
                account.account_state = AccountState::Touched;
            }
        }
    }

    pub fn apply_geth_update_vec(&mut self, update: Vec<BTreeMap<Address, GethAccountState>>) {
        for entry in update.into_iter() {
            self.apply_geth_update(entry);
        }
    }
}