revm_database_interface/
lib.rs1#![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};
13
14pub const FFADDRESS: Address = address!("0xffffffffffffffffffffffffffffffffffffffff");
16pub const BENCH_TARGET: Address = FFADDRESS;
18pub const TEST_BALANCE: U256 = U256::from_limbs([10_000_000_000_000_000, 0, 0, 0]);
20pub const BENCH_TARGET_BALANCE: U256 = TEST_BALANCE;
22pub const EEADDRESS: Address = address!("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
24pub const BENCH_CALLER: Address = EEADDRESS;
26pub const BENCH_CALLER_BALANCE: U256 = TEST_BALANCE;
28
29#[cfg(feature = "asyncdb")]
30pub mod async_db;
31pub mod either;
32pub mod empty_db;
33pub mod erased_error;
34pub mod try_commit;
35
36#[cfg(feature = "asyncdb")]
37pub use async_db::{DatabaseAsync, WrapDatabaseAsync};
38pub use empty_db::{EmptyDB, EmptyDBTyped};
39pub use erased_error::ErasedError;
40pub use try_commit::{ArcUpgradeError, TryDatabaseCommit};
41
42pub trait DBErrorMarker: core::error::Error + Send + Sync + 'static {}
44
45impl DBErrorMarker for Infallible {}
47impl DBErrorMarker for ErasedError {}
48
49#[auto_impl(&mut, Box)]
51pub trait Database {
52 type Error: DBErrorMarker;
54
55 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error>;
57
58 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error>;
60
61 fn storage(&mut self, address: Address, index: StorageKey)
63 -> Result<StorageValue, Self::Error>;
64
65 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error>;
67}
68
69#[auto_impl(&mut, Box)]
71pub trait DatabaseCommit {
72 fn commit(&mut self, changes: HashMap<Address, Account>);
74
75 fn commit_iter(&mut self, changes: impl IntoIterator<Item = (Address, Account)>) {
81 let changes: HashMap<Address, Account> = changes.into_iter().collect();
82 self.commit(changes);
83 }
84}
85
86#[auto_impl(&, &mut, Box, Rc, Arc)]
93pub trait DatabaseRef {
94 type Error: DBErrorMarker;
96
97 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error>;
99
100 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error>;
102
103 fn storage_ref(&self, address: Address, index: StorageKey)
105 -> Result<StorageValue, Self::Error>;
106
107 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error>;
109}
110
111#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
113pub struct WrapDatabaseRef<T: DatabaseRef>(pub T);
114
115impl<F: DatabaseRef> From<F> for WrapDatabaseRef<F> {
116 #[inline]
117 fn from(f: F) -> Self {
118 WrapDatabaseRef(f)
119 }
120}
121
122impl<T: DatabaseRef> Database for WrapDatabaseRef<T> {
123 type Error = T::Error;
124
125 #[inline]
126 fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
127 self.0.basic_ref(address)
128 }
129
130 #[inline]
131 fn code_by_hash(&mut self, code_hash: B256) -> Result<Bytecode, Self::Error> {
132 self.0.code_by_hash_ref(code_hash)
133 }
134
135 #[inline]
136 fn storage(
137 &mut self,
138 address: Address,
139 index: StorageKey,
140 ) -> Result<StorageValue, Self::Error> {
141 self.0.storage_ref(address, index)
142 }
143
144 #[inline]
145 fn block_hash(&mut self, number: u64) -> Result<B256, Self::Error> {
146 self.0.block_hash_ref(number)
147 }
148}
149
150impl<T: DatabaseRef + DatabaseCommit> DatabaseCommit for WrapDatabaseRef<T> {
151 #[inline]
152 fn commit(&mut self, changes: HashMap<Address, Account>) {
153 self.0.commit(changes)
154 }
155}
156
157impl<T: DatabaseRef> DatabaseRef for WrapDatabaseRef<T> {
158 type Error = T::Error;
159
160 #[inline]
161 fn basic_ref(&self, address: Address) -> Result<Option<AccountInfo>, Self::Error> {
162 self.0.basic_ref(address)
163 }
164
165 #[inline]
166 fn code_by_hash_ref(&self, code_hash: B256) -> Result<Bytecode, Self::Error> {
167 self.0.code_by_hash_ref(code_hash)
168 }
169
170 #[inline]
171 fn storage_ref(
172 &self,
173 address: Address,
174 index: StorageKey,
175 ) -> Result<StorageValue, Self::Error> {
176 self.0.storage_ref(address, index)
177 }
178
179 #[inline]
180 fn block_hash_ref(&self, number: u64) -> Result<B256, Self::Error> {
181 self.0.block_hash_ref(number)
182 }
183}
184
185impl<T: Database + DatabaseCommit> DatabaseCommitExt for T {
186 }
188
189pub trait DatabaseCommitExt: Database + DatabaseCommit {
191 fn increment_balances(
195 &mut self,
196 balances: impl IntoIterator<Item = (Address, u128)>,
197 ) -> Result<(), Self::Error> {
198 let balances = balances.into_iter();
200 let mut transitions: HashMap<Address, Account> = HashMap::default();
201 transitions.reserve(balances.size_hint().0);
202 for (address, balance) in balances {
203 let mut original_account = match self.basic(address)? {
204 Some(acc_info) => Account::from(acc_info),
205 None => Account::new_not_existing(0),
206 };
207 original_account.info.balance = original_account
208 .info
209 .balance
210 .saturating_add(U256::from(balance));
211 original_account.mark_touch();
212 transitions.insert(address, original_account);
213 }
214 self.commit(transitions);
215 Ok(())
216 }
217}