kabu_evm_db/
kabu_db_helper.rs

1use crate::error::KabuDBError;
2use alloy::primitives::{Address, BlockNumber, B256, U256};
3use eyre::eyre;
4use revm::state::{AccountInfo, Bytecode};
5use revm::DatabaseRef;
6use tracing::trace;
7
8pub struct KabuDBHelper {}
9
10impl KabuDBHelper {
11    #[inline]
12    pub fn get_code_by_hash<DB: DatabaseRef<Error = KabuDBError>>(
13        read_only_db: &Option<DB>,
14        code_hash: B256,
15    ) -> eyre::Result<Bytecode, KabuDBError> {
16        match read_only_db {
17            Some(read_only_db) => read_only_db.code_by_hash_ref(code_hash),
18            None => Err(KabuDBError::NoDB),
19        }
20    }
21
22    #[inline]
23    fn fetch_storage<ExtDB: DatabaseRef<Error = KabuDBError>>(
24        ext_db: &Option<ExtDB>,
25        address: Address,
26        slot: U256,
27    ) -> Result<U256, KabuDBError> {
28        trace!(%address, %slot, "fetch_storage");
29
30        if let Some(ext_db) = ext_db {
31            let value = ext_db.storage_ref(address, slot).map_err(|_| eyre!("ERROR_READING_ALLOY_DB"));
32            trace!(%address, %slot, ?value , "fetch_storage returned");
33            Ok(value.unwrap_or_default())
34        } else {
35            trace!("fetch_storage returned NO_EXT_DB");
36            Err(KabuDBError::NoDB)
37        }
38    }
39
40    #[inline]
41    pub fn get_or_fetch_storage<DB: DatabaseRef<Error = KabuDBError>, ExtDB: DatabaseRef<Error = KabuDBError>>(
42        read_only_db: &Option<DB>,
43        ext_db: &Option<ExtDB>,
44        address: Address,
45        slot: U256,
46    ) -> Result<U256, KabuDBError> {
47        trace!(%address, %slot, "get_or_fetch_storage");
48
49        match read_only_db {
50            Some(read_only_db) => {
51                let value = read_only_db.storage_ref(address, slot).or_else(|_| Self::fetch_storage(ext_db, address, slot));
52                trace!(%address, %slot, ?value , "get_or_fetch_storage with RO");
53                value
54            }
55            None => {
56                let value = Self::fetch_storage(ext_db, address, slot);
57                trace!(%address, %slot, ?value , "get_or_fetch_storage without RO");
58                value
59            }
60        }
61    }
62
63    #[inline]
64    fn fetch_basic<ExtDB: DatabaseRef<Error = KabuDBError>>(
65        ext_db: &Option<ExtDB>,
66        address: Address,
67    ) -> Result<Option<AccountInfo>, KabuDBError> {
68        trace!(%address, "fetch_basic");
69        if let Some(ext_db) = ext_db {
70            ext_db.basic_ref(address)
71        } else {
72            Err(KabuDBError::NoDB)
73        }
74    }
75
76    #[inline]
77    pub fn get_basic<DB: DatabaseRef<Error = KabuDBError>>(
78        read_only_db: &Option<DB>,
79        address: Address,
80    ) -> eyre::Result<Option<AccountInfo>> {
81        read_only_db
82            .as_ref()
83            .and_then(|db| db.basic_ref(address).ok().flatten())
84            .map_or_else(|| Err(eyre!("NO_ACCOUNT")), |info| Ok(Some(info)))
85    }
86
87    #[inline]
88    pub fn get_or_fetch_basic<DB: DatabaseRef<Error = KabuDBError>, ExtDB: DatabaseRef<Error = KabuDBError>>(
89        read_only_db: &Option<DB>,
90        ext_db: &Option<ExtDB>,
91        address: Address,
92    ) -> Result<Option<AccountInfo>, KabuDBError> {
93        trace!(%address, "get_or_fetch_basic");
94        match &read_only_db {
95            Some(read_only_db) => match read_only_db.basic_ref(address) {
96                Ok(Some(info)) => Ok(Some(info)),
97                _ => Self::fetch_basic(ext_db, address),
98            },
99            None => Self::fetch_basic(ext_db, address),
100        }
101    }
102
103    #[inline]
104    fn fetch_block_hash_ref<ExtDB: DatabaseRef<Error = KabuDBError>>(
105        ext_db: &Option<ExtDB>,
106        number: BlockNumber,
107    ) -> Result<B256, KabuDBError> {
108        if let Some(ext_db) = ext_db {
109            ext_db.block_hash_ref(number)
110        } else {
111            Err(KabuDBError::NoDB)
112        }
113    }
114
115    #[inline]
116    pub fn get_or_fetch_block_hash<DB: DatabaseRef<Error = KabuDBError>, ExtDB: DatabaseRef<Error = KabuDBError>>(
117        read_only_db: &Option<DB>,
118        ext_db: &Option<ExtDB>,
119        number: BlockNumber,
120    ) -> Result<B256, KabuDBError> {
121        match read_only_db {
122            Some(read_only_db) => read_only_db.block_hash_ref(number).or_else(|_| KabuDBHelper::fetch_block_hash_ref(ext_db, number)),
123            None => Self::fetch_block_hash_ref(ext_db, number),
124        }
125    }
126}