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, 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
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: usize,
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: usize,
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: usize,
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
228impl<T: DatabaseRef> DatabaseRef for WrapDatabaseRef<T> {
229 type Error = T::Error;
230
231 #[inline]
232 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
233 self.0.basic_ref(address)
234 }
235
236 #[inline]
237 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
238 self.0.code_by_hash_ref(code_hash)
239 }
240
241 #[inline]
242 fn storage_ref(
243 &self,
244 address: Address,
245 index: StorageKey,
246 ) -> Result<StorageValue, Self::Error> {
247 self.0.storage_ref(address, index)
248 }
249
250 #[inline]
251 fn storage_by_account_id_ref(
252 &self,
253 address: Address,
254 account_id: usize,
255 storage_key: StorageKey,
256 ) -> Result<StorageValue, Self::Error> {
257 self.0
258 .storage_by_account_id_ref(address, account_id, storage_key)
259 }
260
261 #[inline]
262 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
263 self.0.block_hash_ref(number)
264 }
265}
266
267impl<T: Database + DatabaseCommit> DatabaseCommitExt for T {
268 }
270
271pub trait DatabaseCommitExt: Database + DatabaseCommit {
273 fn increment_balances(
277 &mut self,
278 balances: impl IntoIterator<Item = (Address, u128)>,
279 ) -> Result<(), Self::Error> {
280 let transitions = balances
282 .into_iter()
283 .map(|(address, balance)| {
284 let mut original_account = match self.basic(address)? {
285 Some(acc_info) => Account::from(acc_info),
286 None => Account::new_not_existing(0),
287 };
288 original_account.info.balance = original_account
289 .info
290 .balance
291 .saturating_add(U256::from(balance));
292 original_account.mark_touch();
293 Ok((address, original_account))
294 })
295 .collect::<Result<Vec<_>, _>>()?;
297
298 self.commit_iter(&mut transitions.into_iter());
299 Ok(())
300 }
301
302 fn drain_balances(
306 &mut self,
307 addresses: impl IntoIterator<Item = Address>,
308 ) -> Result<Vec<u128>, Self::Error> {
309 let addresses_iter = addresses.into_iter();
311 let (lower, _) = addresses_iter.size_hint();
312 let mut transitions = Vec::with_capacity(lower);
313 let balances = addresses_iter
314 .map(|address| {
315 let mut original_account = match self.basic(address)? {
316 Some(acc_info) => Account::from(acc_info),
317 None => Account::new_not_existing(0),
318 };
319 let balance = core::mem::take(&mut original_account.info.balance);
320 original_account.mark_touch();
321 transitions.push((address, original_account));
322 Ok(balance.try_into().unwrap())
323 })
324 .collect::<Result<Vec<_>, _>>()?;
325
326 self.commit_iter(&mut transitions.into_iter());
327 Ok(balances)
328 }
329}
330
331#[cfg(test)]
332mod tests {
333 use super::*;
334
335 struct _DatabaseCommitObjectSafe(dyn DatabaseCommit);
338
339 #[test]
341 fn test_dyn_database_commit() {
342 use std::collections::HashMap as StdHashMap;
343
344 struct MockDb {
345 commits: Vec<StdHashMap<Address, Account>>,
346 }
347
348 impl DatabaseCommit for MockDb {
349 fn commit(&mut self, changes: AddressMap<Account>) {
350 let std_map: StdHashMap<_, _> = changes.into_iter().collect();
351 self.commits.push(std_map);
352 }
353 }
354
355 let mut db = MockDb { commits: vec![] };
356
357 let items: Vec<(Address, Account)> = vec![];
359 db.commit_iter(&mut items.into_iter());
360 assert_eq!(db.commits.len(), 1);
361
362 {
364 let db_dyn: &mut dyn DatabaseCommit = &mut db;
365 db_dyn.commit(AddressMap::default());
366 }
367 assert_eq!(db.commits.len(), 2);
368
369 {
371 let db_dyn: &mut dyn DatabaseCommit = &mut db;
372 let items: Vec<(Address, Account)> = vec![];
373 db_dyn.commit_iter(&mut items.into_iter());
374 }
375 assert_eq!(db.commits.len(), 3);
376
377 {
379 let db_dyn: &mut dyn DatabaseCommit = &mut db;
380 db_dyn.commit_from_iter(vec![]);
381 }
382 assert_eq!(db.commits.len(), 4);
383 }
384}