kabu_evm_db/
kabu_db_helper.rs

1use crate::error::KabuDBError;
2use alloy::primitives::{Address, B256, BlockNumber, U256};
3use eyre::eyre;
4use revm::DatabaseRef;
5use revm::state::{AccountInfo, Bytecode};
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 { ext_db.basic_ref(address) } else { Err(KabuDBError::NoDB) }
70    }
71
72    #[inline]
73    pub fn get_basic<DB: DatabaseRef<Error = KabuDBError>>(
74        read_only_db: &Option<DB>,
75        address: Address,
76    ) -> eyre::Result<Option<AccountInfo>> {
77        read_only_db
78            .as_ref()
79            .and_then(|db| db.basic_ref(address).ok().flatten())
80            .map_or_else(|| Err(eyre!("NO_ACCOUNT")), |info| Ok(Some(info)))
81    }
82
83    #[inline]
84    pub fn get_or_fetch_basic<DB: DatabaseRef<Error = KabuDBError>, ExtDB: DatabaseRef<Error = KabuDBError>>(
85        read_only_db: &Option<DB>,
86        ext_db: &Option<ExtDB>,
87        address: Address,
88    ) -> Result<Option<AccountInfo>, KabuDBError> {
89        trace!(%address, "get_or_fetch_basic");
90        match &read_only_db {
91            Some(read_only_db) => match read_only_db.basic_ref(address) {
92                Ok(Some(info)) => Ok(Some(info)),
93                _ => Self::fetch_basic(ext_db, address),
94            },
95            None => Self::fetch_basic(ext_db, address),
96        }
97    }
98
99    #[inline]
100    fn fetch_block_hash_ref<ExtDB: DatabaseRef<Error = KabuDBError>>(
101        ext_db: &Option<ExtDB>,
102        number: BlockNumber,
103    ) -> Result<B256, KabuDBError> {
104        if let Some(ext_db) = ext_db { ext_db.block_hash_ref(number) } else { Err(KabuDBError::NoDB) }
105    }
106
107    #[inline]
108    pub fn get_or_fetch_block_hash<DB: DatabaseRef<Error = KabuDBError>, ExtDB: DatabaseRef<Error = KabuDBError>>(
109        read_only_db: &Option<DB>,
110        ext_db: &Option<ExtDB>,
111        number: BlockNumber,
112    ) -> Result<B256, KabuDBError> {
113        match read_only_db {
114            Some(read_only_db) => read_only_db.block_hash_ref(number).or_else(|_| KabuDBHelper::fetch_block_hash_ref(ext_db, number)),
115            None => Self::fetch_block_hash_ref(ext_db, number),
116        }
117    }
118}