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)]
93pub trait DatabaseCommit {
94 fn commit(&mut self, changes: HashMap<Address, Account>);
96
97 fn commit_iter(&mut self, changes: &mut dyn Iterator<Item = (Address, Account)>) {
109 let changes: HashMap<Address, Account> = changes.collect();
110 self.commit(changes);
111 }
112}
113
114impl dyn DatabaseCommit {
119 #[inline]
124 pub fn commit_from_iter(&mut self, changes: impl IntoIterator<Item = (Address, Account)>) {
125 self.commit_iter(&mut changes.into_iter())
126 }
127}
128
129#[auto_impl(&, &mut, Box, Rc, Arc)]
136pub trait DatabaseRef {
137 type Error: DBErrorMarker;
139
140 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error>;
142
143 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error>;
145
146 fn storage_ref(&self, address: Address, index: StorageKey)
148 -> Result<StorageValue, Self::Error>;
149
150 #[inline]
154 fn storage_by_account_id_ref(
155 &self,
156 address: Address,
157 account_id: usize,
158 storage_key: StorageKey,
159 ) -> Result<StorageValue, Self::Error> {
160 let _ = account_id;
161 self.storage_ref(address, storage_key)
162 }
163
164 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error>;
166}
167
168#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
170pub struct WrapDatabaseRef<T: DatabaseRef>(pub T);
171
172impl<F: DatabaseRef> From<F> for WrapDatabaseRef<F> {
173 #[inline]
174 fn from(f: F) -> Self {
175 WrapDatabaseRef(f)
176 }
177}
178
179impl<T: DatabaseRef> Database for WrapDatabaseRef<T> {
180 type Error = T::Error;
181
182 #[inline]
183 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
184 self.0.basic_ref(address)
185 }
186
187 #[inline]
188 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
189 self.0.code_by_hash_ref(code_hash)
190 }
191
192 #[inline]
193 fn storage(
194 &mut self,
195 address: Address,
196 index: StorageKey,
197 ) -> Result<StorageValue, Self::Error> {
198 self.0.storage_ref(address, index)
199 }
200
201 #[inline]
202 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
203 self.0.block_hash_ref(number)
204 }
205}
206
207impl<T: DatabaseRef + DatabaseCommit> DatabaseCommit for WrapDatabaseRef<T> {
208 #[inline]
209 fn commit(&mut self, changes: HashMap<Address, Account>) {
210 self.0.commit(changes)
211 }
212}
213
214impl<T: DatabaseRef> DatabaseRef for WrapDatabaseRef<T> {
215 type Error = T::Error;
216
217 #[inline]
218 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
219 self.0.basic_ref(address)
220 }
221
222 #[inline]
223 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
224 self.0.code_by_hash_ref(code_hash)
225 }
226
227 #[inline]
228 fn storage_ref(
229 &self,
230 address: Address,
231 index: StorageKey,
232 ) -> Result<StorageValue, Self::Error> {
233 self.0.storage_ref(address, index)
234 }
235
236 #[inline]
237 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
238 self.0.block_hash_ref(number)
239 }
240}
241
242impl<T: Database + DatabaseCommit> DatabaseCommitExt for T {
243 }
245
246pub trait DatabaseCommitExt: Database + DatabaseCommit {
248 fn increment_balances(
252 &mut self,
253 balances: impl IntoIterator<Item = (Address, u128)>,
254 ) -> Result<(), Self::Error> {
255 let transitions = balances
257 .into_iter()
258 .map(|(address, balance)| {
259 let mut original_account = match self.basic(address)? {
260 Some(acc_info) => Account::from(acc_info),
261 None => Account::new_not_existing(0),
262 };
263 original_account.info.balance = original_account
264 .info
265 .balance
266 .saturating_add(U256::from(balance));
267 original_account.mark_touch();
268 Ok((address, original_account))
269 })
270 .collect::<Result<Vec<_>, _>>()?;
272
273 self.commit_iter(&mut transitions.into_iter());
274 Ok(())
275 }
276
277 fn drain_balances(
281 &mut self,
282 addresses: impl IntoIterator<Item = Address>,
283 ) -> Result<Vec<u128>, Self::Error> {
284 let addresses_iter = addresses.into_iter();
286 let (lower, _) = addresses_iter.size_hint();
287 let mut transitions = Vec::with_capacity(lower);
288 let balances = addresses_iter
289 .map(|address| {
290 let mut original_account = match self.basic(address)? {
291 Some(acc_info) => Account::from(acc_info),
292 None => Account::new_not_existing(0),
293 };
294 let balance = core::mem::take(&mut original_account.info.balance);
295 original_account.mark_touch();
296 transitions.push((address, original_account));
297 Ok(balance.try_into().unwrap())
298 })
299 .collect::<Result<Vec<_>, _>>()?;
300
301 self.commit_iter(&mut transitions.into_iter());
302 Ok(balances)
303 }
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309
310 struct _DatabaseCommitObjectSafe(dyn DatabaseCommit);
313
314 #[test]
316 fn test_dyn_database_commit() {
317 use std::collections::HashMap as StdHashMap;
318
319 struct MockDb {
320 commits: Vec<StdHashMap<Address, Account>>,
321 }
322
323 impl DatabaseCommit for MockDb {
324 fn commit(&mut self, changes: HashMap<Address, Account>) {
325 let std_map: StdHashMap<_, _> = changes.into_iter().collect();
326 self.commits.push(std_map);
327 }
328 }
329
330 let mut db = MockDb { commits: vec![] };
331
332 let items: Vec<(Address, Account)> = vec![];
334 db.commit_iter(&mut items.into_iter());
335 assert_eq!(db.commits.len(), 1);
336
337 {
339 let db_dyn: &mut dyn DatabaseCommit = &mut db;
340 db_dyn.commit(HashMap::default());
341 }
342 assert_eq!(db.commits.len(), 2);
343
344 {
346 let db_dyn: &mut dyn DatabaseCommit = &mut db;
347 let items: Vec<(Address, Account)> = vec![];
348 db_dyn.commit_iter(&mut items.into_iter());
349 }
350 assert_eq!(db.commits.len(), 3);
351
352 {
354 let db_dyn: &mut dyn DatabaseCommit = &mut db;
355 db_dyn.commit_from_iter(vec![]);
356 }
357 assert_eq!(db.commits.len(), 4);
358 }
359}