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
50impl DBErrorMarker for Infallible {}
52impl DBErrorMarker for ErasedError {}
53
54#[auto_impl(&mut, Box)]
56pub trait Database {
57 type Error: DBErrorMarker;
59
60 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error>;
62
63 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error>;
65
66 fn storage(&mut self, address: Address, index: StorageKey)
68 -> Result<StorageValue, Self::Error>;
69
70 #[inline]
75 fn storage_by_account_id(
76 &mut self,
77 address: Address,
78 account_id: AccountId,
79 storage_key: StorageKey,
80 ) -> Result<StorageValue, Self::Error> {
81 let _ = account_id;
82 self.storage(address, storage_key)
83 }
84
85 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error>;
87}
88
89#[auto_impl(&mut, Box)]
96pub trait DatabaseCommit {
97 fn commit(&mut self, changes: AddressMap<Account>);
99
100 fn commit_iter(&mut self, changes: &mut dyn Iterator<Item = (Address, Account)>) {
112 let changes: AddressMap<Account> = changes.collect();
113 self.commit(changes);
114 }
115}
116
117impl dyn DatabaseCommit {
122 #[inline]
127 pub fn commit_from_iter(&mut self, changes: impl IntoIterator<Item = (Address, Account)>) {
128 self.commit_iter(&mut changes.into_iter())
129 }
130}
131
132#[auto_impl(&, &mut, Box, Rc, Arc)]
139pub trait DatabaseRef {
140 type Error: DBErrorMarker;
142
143 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error>;
145
146 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error>;
148
149 fn storage_ref(&self, address: Address, index: StorageKey)
151 -> Result<StorageValue, Self::Error>;
152
153 #[inline]
157 fn storage_by_account_id_ref(
158 &self,
159 address: Address,
160 account_id: AccountId,
161 storage_key: StorageKey,
162 ) -> Result<StorageValue, Self::Error> {
163 let _ = account_id;
164 self.storage_ref(address, storage_key)
165 }
166
167 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error>;
169}
170
171#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
173pub struct WrapDatabaseRef<T: DatabaseRef>(pub T);
174
175impl<F: DatabaseRef> From<F> for WrapDatabaseRef<F> {
176 #[inline]
177 fn from(f: F) -> Self {
178 WrapDatabaseRef(f)
179 }
180}
181
182impl<T: DatabaseRef> Database for WrapDatabaseRef<T> {
183 type Error = T::Error;
184
185 #[inline]
186 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
187 self.0.basic_ref(address)
188 }
189
190 #[inline]
191 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
192 self.0.code_by_hash_ref(code_hash)
193 }
194
195 #[inline]
196 fn storage(
197 &mut self,
198 address: Address,
199 index: StorageKey,
200 ) -> Result<StorageValue, Self::Error> {
201 self.0.storage_ref(address, index)
202 }
203
204 #[inline]
205 fn storage_by_account_id(
206 &mut self,
207 address: Address,
208 account_id: AccountId,
209 storage_key: StorageKey,
210 ) -> Result<StorageValue, Self::Error> {
211 self.0
212 .storage_by_account_id_ref(address, account_id, storage_key)
213 }
214
215 #[inline]
216 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
217 self.0.block_hash_ref(number)
218 }
219}
220
221impl<T: DatabaseRef + DatabaseCommit> DatabaseCommit for WrapDatabaseRef<T> {
222 #[inline]
223 fn commit(&mut self, changes: AddressMap<Account>) {
224 self.0.commit(changes)
225 }
226
227 #[inline]
228 fn commit_iter(&mut self, changes: &mut dyn Iterator<Item = (Address, Account)>) {
229 self.0.commit_iter(changes)
230 }
231}
232
233impl<T: DatabaseRef> DatabaseRef for WrapDatabaseRef<T> {
234 type Error = T::Error;
235
236 #[inline]
237 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
238 self.0.basic_ref(address)
239 }
240
241 #[inline]
242 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
243 self.0.code_by_hash_ref(code_hash)
244 }
245
246 #[inline]
247 fn storage_ref(
248 &self,
249 address: Address,
250 index: StorageKey,
251 ) -> Result<StorageValue, Self::Error> {
252 self.0.storage_ref(address, index)
253 }
254
255 #[inline]
256 fn storage_by_account_id_ref(
257 &self,
258 address: Address,
259 account_id: AccountId,
260 storage_key: StorageKey,
261 ) -> Result<StorageValue, Self::Error> {
262 self.0
263 .storage_by_account_id_ref(address, account_id, storage_key)
264 }
265
266 #[inline]
267 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
268 self.0.block_hash_ref(number)
269 }
270}
271
272impl<T: Database + DatabaseCommit> DatabaseCommitExt for T {
273 }
275
276pub trait DatabaseCommitExt: Database + DatabaseCommit {
278 fn increment_balances(
282 &mut self,
283 balances: impl IntoIterator<Item = (Address, u128)>,
284 ) -> Result<(), Self::Error> {
285 let transitions = balances
287 .into_iter()
288 .map(|(address, balance)| {
289 let mut original_account = match self.basic(address)? {
290 Some(acc_info) => Account::from(acc_info),
291 None => Account::new_not_existing(TransactionId::ZERO),
292 };
293 original_account.info.balance = original_account
294 .info
295 .balance
296 .saturating_add(U256::from(balance));
297 original_account.mark_touch();
298 Ok((address, original_account))
299 })
300 .collect::<Result<Vec<_>, _>>()?;
302
303 self.commit_iter(&mut transitions.into_iter());
304 Ok(())
305 }
306
307 fn drain_balances(
311 &mut self,
312 addresses: impl IntoIterator<Item = Address>,
313 ) -> Result<Vec<u128>, Self::Error> {
314 let addresses_iter = addresses.into_iter();
316 let (lower, _) = addresses_iter.size_hint();
317 let mut transitions = Vec::with_capacity(lower);
318 let balances = addresses_iter
319 .map(|address| {
320 let mut original_account = match self.basic(address)? {
321 Some(acc_info) => Account::from(acc_info),
322 None => Account::new_not_existing(TransactionId::ZERO),
323 };
324 let balance = core::mem::take(&mut original_account.info.balance);
325 original_account.mark_touch();
326 transitions.push((address, original_account));
327 Ok(balance.try_into().unwrap())
328 })
329 .collect::<Result<Vec<_>, _>>()?;
330
331 self.commit_iter(&mut transitions.into_iter());
332 Ok(balances)
333 }
334}
335
336#[cfg(test)]
337mod tests {
338 use super::*;
339
340 struct _DatabaseCommitObjectSafe(dyn DatabaseCommit);
343
344 #[test]
346 fn test_dyn_database_commit() {
347 use std::collections::HashMap as StdHashMap;
348
349 struct MockDb {
350 commits: Vec<StdHashMap<Address, Account>>,
351 }
352
353 impl DatabaseCommit for MockDb {
354 fn commit(&mut self, changes: AddressMap<Account>) {
355 let std_map: StdHashMap<_, _> = changes.into_iter().collect();
356 self.commits.push(std_map);
357 }
358 }
359
360 let mut db = MockDb { commits: vec![] };
361
362 let items: Vec<(Address, Account)> = vec![];
364 db.commit_iter(&mut items.into_iter());
365 assert_eq!(db.commits.len(), 1);
366
367 {
369 let db_dyn: &mut dyn DatabaseCommit = &mut db;
370 db_dyn.commit(AddressMap::default());
371 }
372 assert_eq!(db.commits.len(), 2);
373
374 {
376 let db_dyn: &mut dyn DatabaseCommit = &mut db;
377 let items: Vec<(Address, Account)> = vec![];
378 db_dyn.commit_iter(&mut items.into_iter());
379 }
380 assert_eq!(db.commits.len(), 3);
381
382 {
384 let db_dyn: &mut dyn DatabaseCommit = &mut db;
385 db_dyn.commit_from_iter(vec![]);
386 }
387 assert_eq!(db.commits.len(), 4);
388 }
389
390 #[test]
391 fn wrappers_forward_commit_iter() {
392 #[derive(Default)]
393 struct MockDb {
394 commits: usize,
395 commit_iters: usize,
396 committed_accounts: usize,
397 }
398
399 impl DatabaseCommit for MockDb {
400 fn commit(&mut self, changes: AddressMap<Account>) {
401 self.commits += 1;
402 self.committed_accounts += changes.len();
403 }
404
405 fn commit_iter(&mut self, changes: &mut dyn Iterator<Item = (Address, Account)>) {
406 self.commit_iters += 1;
407 self.committed_accounts += changes.count();
408 }
409 }
410
411 impl DatabaseRef for MockDb {
412 type Error = Infallible;
413
414 fn basic_ref(&self, _address: Address) -> Result<Option<AccountInfo>, Self::Error> {
415 Ok(None)
416 }
417
418 fn code_by_hash_ref(&self, _code_hash: B256) -> Result<Bytecode, Self::Error> {
419 Ok(Bytecode::default())
420 }
421
422 fn storage_ref(
423 &self,
424 _address: Address,
425 _index: StorageKey,
426 ) -> Result<StorageValue, Self::Error> {
427 Ok(StorageValue::ZERO)
428 }
429
430 fn block_hash_ref(&self, _number: u64) -> Result<B256, Self::Error> {
431 Ok(B256::ZERO)
432 }
433 }
434
435 fn changes() -> Vec<(Address, Account)> {
436 vec![(Address::with_last_byte(1), Account::default())]
437 }
438
439 let mut db = WrapDatabaseRef(MockDb::default());
440 db.commit_iter(&mut changes().into_iter());
441 assert_eq!(db.0.commits, 0);
442 assert_eq!(db.0.commit_iters, 1);
443 assert_eq!(db.0.committed_accounts, 1);
444
445 let mut db: ::either::Either<MockDb, MockDb> = ::either::Either::Left(MockDb::default());
446 db.commit_iter(&mut changes().into_iter());
447 let ::either::Either::Left(db) = db else {
448 unreachable!()
449 };
450 assert_eq!(db.commits, 0);
451 assert_eq!(db.commit_iters, 1);
452 assert_eq!(db.committed_accounts, 1);
453
454 let address = Address::with_last_byte(2);
455 let mut account = Account::default();
456 account.mark_touch();
457
458 let mut db = bal::BalDatabase::new(MockDb::default()).with_bal_builder();
459 db.commit_iter(&mut [(address, account)].into_iter());
460 assert_eq!(db.db.commits, 0);
461 assert_eq!(db.db.commit_iters, 1);
462 assert_eq!(db.db.committed_accounts, 1);
463
464 let bal = db.bal_state.take_built_bal().expect("BAL should be built");
465 assert!(bal.accounts.get(&address).is_some());
466 }
467}