1#![cfg_attr(not(test), warn(unused_crate_dependencies))]
3#![cfg_attr(not(feature = "std"), no_std)]
4
5#[cfg(not(feature = "std"))]
6extern crate alloc as std;
7
8use core::convert::Infallible;
9
10use auto_impl::auto_impl;
11use primitives::{address, Address, HashMap, StorageKey, StorageValue, B256, U256};
12use state::{Account, AccountInfo, Bytecode};
13use std::vec::Vec;
14
15pub const FFADDRESS: Address = address!("0xffffffffffffffffffffffffffffffffffffffff");
17pub const BENCH_TARGET: Address = FFADDRESS;
19pub const TEST_BALANCE: U256 = U256::from_limbs([10_000_000_000_000_000, 0, 0, 0]);
21pub const BENCH_TARGET_BALANCE: U256 = TEST_BALANCE;
23pub const EEADDRESS: Address = address!("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
25pub const BENCH_CALLER: Address = EEADDRESS;
27pub const BENCH_CALLER_BALANCE: U256 = TEST_BALANCE;
29
30#[cfg(feature = "asyncdb")]
31pub mod async_db;
32pub mod bal;
33pub mod either;
34pub mod empty_db;
35pub mod erased_error;
36pub mod try_commit;
37
38#[cfg(feature = "asyncdb")]
39pub use async_db::{DatabaseAsync, WrapDatabaseAsync};
40pub use empty_db::{EmptyDB, EmptyDBTyped};
41pub use erased_error::ErasedError;
42pub use try_commit::{ArcUpgradeError, TryDatabaseCommit};
43
44pub trait DBErrorMarker: core::error::Error + Send + Sync + 'static {}
46
47impl DBErrorMarker for Infallible {}
49impl DBErrorMarker for ErasedError {}
50
51#[auto_impl(&mut, Box)]
53pub trait Database {
54 type Error: DBErrorMarker;
56
57 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error>;
59
60 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error>;
62
63 fn storage(&mut self, address: Address, index: StorageKey)
65 -> Result<StorageValue, Self::Error>;
66
67 #[inline]
72 fn storage_by_account_id(
73 &mut self,
74 address: Address,
75 account_id: usize,
76 storage_key: StorageKey,
77 ) -> Result<StorageValue, Self::Error> {
78 let _ = account_id;
79 self.storage(address, storage_key)
80 }
81
82 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error>;
84}
85
86#[auto_impl(&mut, Box)]
88pub trait DatabaseCommit {
89 fn commit(&mut self, changes: HashMap<Address, Account>);
91
92 fn commit_iter(&mut self, changes: impl IntoIterator<Item = (Address, Account)>) {
98 let changes: HashMap<Address, Account> = changes.into_iter().collect();
99 self.commit(changes);
100 }
101}
102
103#[auto_impl(&, &mut, Box, Rc, Arc)]
110pub trait DatabaseRef {
111 type Error: DBErrorMarker;
113
114 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error>;
116
117 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error>;
119
120 fn storage_ref(&self, address: Address, index: StorageKey)
122 -> Result<StorageValue, Self::Error>;
123
124 #[inline]
128 fn storage_by_account_id_ref(
129 &self,
130 address: Address,
131 account_id: usize,
132 storage_key: StorageKey,
133 ) -> Result<StorageValue, Self::Error> {
134 let _ = account_id;
135 self.storage_ref(address, storage_key)
136 }
137
138 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error>;
140}
141
142#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
144pub struct WrapDatabaseRef<T: DatabaseRef>(pub T);
145
146impl<F: DatabaseRef> From<F> for WrapDatabaseRef<F> {
147 #[inline]
148 fn from(f: F) -> Self {
149 WrapDatabaseRef(f)
150 }
151}
152
153impl<T: DatabaseRef> Database for WrapDatabaseRef<T> {
154 type Error = T::Error;
155
156 #[inline]
157 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
158 self.0.basic_ref(address)
159 }
160
161 #[inline]
162 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
163 self.0.code_by_hash_ref(code_hash)
164 }
165
166 #[inline]
167 fn storage(
168 &mut self,
169 address: Address,
170 index: StorageKey,
171 ) -> Result<StorageValue, Self::Error> {
172 self.0.storage_ref(address, index)
173 }
174
175 #[inline]
176 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
177 self.0.block_hash_ref(number)
178 }
179}
180
181impl<T: DatabaseRef + DatabaseCommit> DatabaseCommit for WrapDatabaseRef<T> {
182 #[inline]
183 fn commit(&mut self, changes: HashMap<Address, Account>) {
184 self.0.commit(changes)
185 }
186}
187
188impl<T: DatabaseRef> DatabaseRef for WrapDatabaseRef<T> {
189 type Error = T::Error;
190
191 #[inline]
192 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
193 self.0.basic_ref(address)
194 }
195
196 #[inline]
197 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
198 self.0.code_by_hash_ref(code_hash)
199 }
200
201 #[inline]
202 fn storage_ref(
203 &self,
204 address: Address,
205 index: StorageKey,
206 ) -> Result<StorageValue, Self::Error> {
207 self.0.storage_ref(address, index)
208 }
209
210 #[inline]
211 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
212 self.0.block_hash_ref(number)
213 }
214}
215
216impl<T: Database + DatabaseCommit> DatabaseCommitExt for T {
217 }
219
220pub trait DatabaseCommitExt: Database + DatabaseCommit {
222 fn increment_balances(
226 &mut self,
227 balances: impl IntoIterator<Item = (Address, u128)>,
228 ) -> Result<(), Self::Error> {
229 let transitions = balances
231 .into_iter()
232 .map(|(address, balance)| {
233 let mut original_account = match self.basic(address)? {
234 Some(acc_info) => Account::from(acc_info),
235 None => Account::new_not_existing(0),
236 };
237 original_account.info.balance = original_account
238 .info
239 .balance
240 .saturating_add(U256::from(balance));
241 original_account.mark_touch();
242 Ok((address, original_account))
243 })
244 .collect::<Result<Vec<_>, _>>()?;
246
247 self.commit_iter(transitions);
248 Ok(())
249 }
250
251 fn drain_balances(
255 &mut self,
256 addresses: impl IntoIterator<Item = Address>,
257 ) -> Result<Vec<u128>, Self::Error> {
258 let addresses_iter = addresses.into_iter();
260 let (lower, _) = addresses_iter.size_hint();
261 let mut transitions = Vec::with_capacity(lower);
262 let balances = addresses_iter
263 .map(|address| {
264 let mut original_account = match self.basic(address)? {
265 Some(acc_info) => Account::from(acc_info),
266 None => Account::new_not_existing(0),
267 };
268 let balance = core::mem::take(&mut original_account.info.balance);
269 original_account.mark_touch();
270 transitions.push((address, original_account));
271 Ok(balance.try_into().unwrap())
272 })
273 .collect::<Result<Vec<_>, _>>()?;
274
275 self.commit_iter(transitions);
276 Ok(balances)
277 }
278}