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, AddressMap, StorageKey, StorageValue, B256, U256};
12use state::{Account, AccountId, AccountInfo, Bytecode, TransactionId};
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
30pub use primitives;
31pub use state;
32
33#[cfg(feature = "asyncdb")]
34pub mod async_db;
35pub mod bal;
36pub mod either;
37pub mod empty_db;
38pub mod erased_error;
39pub mod try_commit;
40
41#[cfg(feature = "asyncdb")]
42pub use async_db::{DatabaseAsync, WrapDatabaseAsync};
43pub use empty_db::{EmptyDB, EmptyDBTyped};
44pub use erased_error::ErasedError;
45pub use try_commit::{ArcUpgradeError, TryDatabaseCommit};
46
47pub trait DBErrorMarker: core::error::Error + Send + Sync + 'static {
49 fn is_fatal(&self) -> bool {
53 true
54 }
55}
56
57impl DBErrorMarker for Infallible {}
59impl DBErrorMarker for ErasedError {}
60
61#[auto_impl(&mut, Box)]
63pub trait Database {
64 type Error: DBErrorMarker;
66
67 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error>;
69
70 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error>;
72
73 fn storage(&mut self, address: Address, index: StorageKey)
75 -> Result<StorageValue, Self::Error>;
76
77 #[inline]
82 fn storage_by_account_id(
83 &mut self,
84 address: Address,
85 account_id: AccountId,
86 storage_key: StorageKey,
87 ) -> Result<StorageValue, Self::Error> {
88 let _ = account_id;
89 self.storage(address, storage_key)
90 }
91
92 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error>;
94}
95
96#[auto_impl(&mut, Box)]
103pub trait DatabaseCommit {
104 fn commit(&mut self, changes: AddressMap<Account>);
106
107 fn commit_iter(&mut self, changes: &mut dyn Iterator<Item = (Address, Account)>) {
119 let changes: AddressMap<Account> = changes.collect();
120 self.commit(changes);
121 }
122}
123
124impl dyn DatabaseCommit {
129 #[inline]
134 pub fn commit_from_iter(&mut self, changes: impl IntoIterator<Item = (Address, Account)>) {
135 self.commit_iter(&mut changes.into_iter())
136 }
137}
138
139#[auto_impl(&, &mut, Box, Rc, Arc)]
146pub trait DatabaseRef {
147 type Error: DBErrorMarker;
149
150 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error>;
152
153 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error>;
155
156 fn storage_ref(&self, address: Address, index: StorageKey)
158 -> Result<StorageValue, Self::Error>;
159
160 #[inline]
164 fn storage_by_account_id_ref(
165 &self,
166 address: Address,
167 account_id: AccountId,
168 storage_key: StorageKey,
169 ) -> Result<StorageValue, Self::Error> {
170 let _ = account_id;
171 self.storage_ref(address, storage_key)
172 }
173
174 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error>;
176}
177
178#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
180pub struct WrapDatabaseRef<T: DatabaseRef>(pub T);
181
182impl<F: DatabaseRef> From<F> for WrapDatabaseRef<F> {
183 #[inline]
184 fn from(f: F) -> Self {
185 WrapDatabaseRef(f)
186 }
187}
188
189impl<T: DatabaseRef> Database for WrapDatabaseRef<T> {
190 type Error = T::Error;
191
192 #[inline]
193 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
194 self.0.basic_ref(address)
195 }
196
197 #[inline]
198 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
199 self.0.code_by_hash_ref(code_hash)
200 }
201
202 #[inline]
203 fn storage(
204 &mut self,
205 address: Address,
206 index: StorageKey,
207 ) -> Result<StorageValue, Self::Error> {
208 self.0.storage_ref(address, index)
209 }
210
211 #[inline]
212 fn storage_by_account_id(
213 &mut self,
214 address: Address,
215 account_id: AccountId,
216 storage_key: StorageKey,
217 ) -> Result<StorageValue, Self::Error> {
218 self.0
219 .storage_by_account_id_ref(address, account_id, storage_key)
220 }
221
222 #[inline]
223 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
224 self.0.block_hash_ref(number)
225 }
226}
227
228impl<T: DatabaseRef + DatabaseCommit> DatabaseCommit for WrapDatabaseRef<T> {
229 #[inline]
230 fn commit(&mut self, changes: AddressMap<Account>) {
231 self.0.commit(changes)
232 }
233
234 #[inline]
235 fn commit_iter(&mut self, changes: &mut dyn Iterator<Item = (Address, Account)>) {
236 self.0.commit_iter(changes)
237 }
238}
239
240impl<T: DatabaseRef> DatabaseRef for WrapDatabaseRef<T> {
241 type Error = T::Error;
242
243 #[inline]
244 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
245 self.0.basic_ref(address)
246 }
247
248 #[inline]
249 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
250 self.0.code_by_hash_ref(code_hash)
251 }
252
253 #[inline]
254 fn storage_ref(
255 &self,
256 address: Address,
257 index: StorageKey,
258 ) -> Result<StorageValue, Self::Error> {
259 self.0.storage_ref(address, index)
260 }
261
262 #[inline]
263 fn storage_by_account_id_ref(
264 &self,
265 address: Address,
266 account_id: AccountId,
267 storage_key: StorageKey,
268 ) -> Result<StorageValue, Self::Error> {
269 self.0
270 .storage_by_account_id_ref(address, account_id, storage_key)
271 }
272
273 #[inline]
274 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
275 self.0.block_hash_ref(number)
276 }
277}
278
279impl<T: Database + DatabaseCommit> DatabaseCommitExt for T {
280 }
282
283pub trait DatabaseCommitExt: Database + DatabaseCommit {
285 fn increment_balances(
289 &mut self,
290 balances: impl IntoIterator<Item = (Address, u128)>,
291 ) -> Result<(), Self::Error> {
292 let transitions = balances
294 .into_iter()
295 .map(|(address, balance)| {
296 let mut original_account = match self.basic(address)? {
297 Some(acc_info) => Account::from(acc_info),
298 None => Account::new_not_existing(TransactionId::ZERO),
299 };
300 original_account.info.balance = original_account
301 .info
302 .balance
303 .saturating_add(U256::from(balance));
304 original_account.mark_touch();
305 Ok((address, original_account))
306 })
307 .collect::<Result<Vec<_>, _>>()?;
309
310 self.commit_iter(&mut transitions.into_iter());
311 Ok(())
312 }
313
314 fn drain_balances(
318 &mut self,
319 addresses: impl IntoIterator<Item = Address>,
320 ) -> Result<Vec<u128>, Self::Error> {
321 let addresses_iter = addresses.into_iter();
323 let (lower, _) = addresses_iter.size_hint();
324 let mut transitions = Vec::with_capacity(lower);
325 let balances = addresses_iter
326 .map(|address| {
327 let mut original_account = match self.basic(address)? {
328 Some(acc_info) => Account::from(acc_info),
329 None => Account::new_not_existing(TransactionId::ZERO),
330 };
331 let balance = core::mem::take(&mut original_account.info.balance);
332 original_account.mark_touch();
333 transitions.push((address, original_account));
334 Ok(balance.try_into().unwrap())
335 })
336 .collect::<Result<Vec<_>, _>>()?;
337
338 self.commit_iter(&mut transitions.into_iter());
339 Ok(balances)
340 }
341}
342
343#[cfg(test)]
344mod tests {
345 use super::*;
346
347 struct _DatabaseCommitObjectSafe(dyn DatabaseCommit);
350
351 #[test]
353 fn test_dyn_database_commit() {
354 use std::collections::HashMap as StdHashMap;
355
356 struct MockDb {
357 commits: Vec<StdHashMap<Address, Account>>,
358 }
359
360 impl DatabaseCommit for MockDb {
361 fn commit(&mut self, changes: AddressMap<Account>) {
362 let std_map: StdHashMap<_, _> = changes.into_iter().collect();
363 self.commits.push(std_map);
364 }
365 }
366
367 let mut db = MockDb { commits: vec![] };
368
369 let items: Vec<(Address, Account)> = vec![];
371 db.commit_iter(&mut items.into_iter());
372 assert_eq!(db.commits.len(), 1);
373
374 {
376 let db_dyn: &mut dyn DatabaseCommit = &mut db;
377 db_dyn.commit(AddressMap::default());
378 }
379 assert_eq!(db.commits.len(), 2);
380
381 {
383 let db_dyn: &mut dyn DatabaseCommit = &mut db;
384 let items: Vec<(Address, Account)> = vec![];
385 db_dyn.commit_iter(&mut items.into_iter());
386 }
387 assert_eq!(db.commits.len(), 3);
388
389 {
391 let db_dyn: &mut dyn DatabaseCommit = &mut db;
392 db_dyn.commit_from_iter(vec![]);
393 }
394 assert_eq!(db.commits.len(), 4);
395 }
396
397 #[test]
398 fn wrappers_forward_commit_iter() {
399 #[derive(Default)]
400 struct MockDb {
401 commits: usize,
402 commit_iters: usize,
403 committed_accounts: usize,
404 }
405
406 impl DatabaseCommit for MockDb {
407 fn commit(&mut self, changes: AddressMap<Account>) {
408 self.commits += 1;
409 self.committed_accounts += changes.len();
410 }
411
412 fn commit_iter(&mut self, changes: &mut dyn Iterator<Item = (Address, Account)>) {
413 self.commit_iters += 1;
414 self.committed_accounts += changes.count();
415 }
416 }
417
418 impl DatabaseRef for MockDb {
419 type Error = Infallible;
420
421 fn basic_ref(&self, _address: Address) -> Result<Option<AccountInfo>, Self::Error> {
422 Ok(None)
423 }
424
425 fn code_by_hash_ref(&self, _code_hash: B256) -> Result<Bytecode, Self::Error> {
426 Ok(Bytecode::default())
427 }
428
429 fn storage_ref(
430 &self,
431 _address: Address,
432 _index: StorageKey,
433 ) -> Result<StorageValue, Self::Error> {
434 Ok(StorageValue::ZERO)
435 }
436
437 fn block_hash_ref(&self, _number: u64) -> Result<B256, Self::Error> {
438 Ok(B256::ZERO)
439 }
440 }
441
442 fn changes() -> Vec<(Address, Account)> {
443 vec![(Address::with_last_byte(1), Account::default())]
444 }
445
446 let mut db = WrapDatabaseRef(MockDb::default());
447 db.commit_iter(&mut changes().into_iter());
448 assert_eq!(db.0.commits, 0);
449 assert_eq!(db.0.commit_iters, 1);
450 assert_eq!(db.0.committed_accounts, 1);
451
452 let mut db: ::either::Either<MockDb, MockDb> = ::either::Either::Left(MockDb::default());
453 db.commit_iter(&mut changes().into_iter());
454 let ::either::Either::Left(db) = db else {
455 unreachable!()
456 };
457 assert_eq!(db.commits, 0);
458 assert_eq!(db.commit_iters, 1);
459 assert_eq!(db.committed_accounts, 1);
460
461 let address = Address::with_last_byte(2);
462 let mut account = Account::default();
463 account.mark_touch();
464
465 let mut db = bal::BalDatabase::new(MockDb::default()).with_bal_builder();
466 db.commit_iter(&mut [(address, account)].into_iter());
467 assert_eq!(db.db.commits, 0);
468 assert_eq!(db.db.commit_iters, 1);
469 assert_eq!(db.db.committed_accounts, 1);
470
471 let bal = db.bal_state.take_built_bal().expect("BAL should be built");
472 assert!(bal.accounts.get(&address).is_some());
473 }
474}