example_database_components/
lib.rs

1//! Database component example.
2#![cfg_attr(not(test), warn(unused_crate_dependencies))]
3
4//! Database that is split on State and BlockHash traits.
5pub mod block_hash;
6pub mod state;
7
8pub use block_hash::{BlockHash, BlockHashRef};
9pub use state::{State, StateRef};
10
11use revm::{
12    database_interface::{DBErrorMarker, Database, DatabaseCommit, DatabaseRef},
13    primitives::{Address, HashMap, StorageKey, StorageValue, B256},
14    state::{Account, AccountInfo, Bytecode},
15};
16
17/// A database implementation that separates state and block hash components.
18/// This allows for modular database design where state and block hash
19/// functionality can be implemented independently.
20#[derive(Debug)]
21pub struct DatabaseComponents<S, BH> {
22    /// State component for account and storage operations
23    pub state: S,
24    /// Block hash component for retrieving historical block hashes
25    pub block_hash: BH,
26}
27
28/// Error type for database component operations.
29/// Wraps errors from both state and block hash components.
30#[derive(Debug, thiserror::Error)]
31pub enum DatabaseComponentError<
32    SE: core::error::Error + Send + Sync + 'static,
33    BHE: core::error::Error + Send + Sync + 'static,
34> {
35    /// Error from state component operations
36    #[error(transparent)]
37    State(SE),
38    /// Error from block hash component operations
39    #[error(transparent)]
40    BlockHash(BHE),
41}
42
43impl<
44        SE: core::error::Error + Send + Sync + 'static,
45        BHE: core::error::Error + Send + Sync + 'static,
46    > DBErrorMarker for DatabaseComponentError<SE, BHE>
47{
48}
49
50unsafe impl<
51        SE: core::error::Error + Send + Sync + 'static,
52        BHE: core::error::Error + Send + Sync + 'static,
53    > Send for DatabaseComponentError<SE, BHE>
54{
55}
56
57impl<S: State, BH: BlockHash> Database for DatabaseComponents<S, BH> {
58    type Error = DatabaseComponentError<S::Error, BH::Error>;
59
60    fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
61        self.state.basic(address).map_err(Self::Error::State)
62    }
63
64    fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
65        self.state
66            .code_by_hash(code_hash)
67            .map_err(Self::Error::State)
68    }
69
70    fn storage(
71        &mut self,
72        address: Address,
73        index: StorageKey,
74    ) -> Result<StorageValue, Self::Error> {
75        self.state
76            .storage(address, index)
77            .map_err(Self::Error::State)
78    }
79
80    fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
81        self.block_hash
82            .block_hash(number)
83            .map_err(Self::Error::BlockHash)
84    }
85}
86
87impl<S: StateRef, BH: BlockHashRef> DatabaseRef for DatabaseComponents<S, BH> {
88    type Error = DatabaseComponentError<S::Error, BH::Error>;
89
90    fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
91        self.state.basic(address).map_err(Self::Error::State)
92    }
93
94    fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
95        self.state
96            .code_by_hash(code_hash)
97            .map_err(Self::Error::State)
98    }
99
100    fn storage_ref(
101        &self,
102        address: Address,
103        index: StorageKey,
104    ) -> Result<StorageValue, Self::Error> {
105        self.state
106            .storage(address, index)
107            .map_err(Self::Error::State)
108    }
109
110    fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
111        self.block_hash
112            .block_hash(number)
113            .map_err(Self::Error::BlockHash)
114    }
115}
116
117impl<S: DatabaseCommit, BH: BlockHashRef> DatabaseCommit for DatabaseComponents<S, BH> {
118    fn commit(&mut self, changes: HashMap<Address, Account>) {
119        self.state.commit(changes);
120    }
121}