Skip to content

Commit ed3ed15

Browse files
authored
chore(anvil): use dyn DatabaseRef instead of generics (#8920)
1 parent a301f26 commit ed3ed15

File tree

9 files changed

+80
-58
lines changed

9 files changed

+80
-58
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/anvil/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ clap = { version = "4", features = [
103103
], optional = true }
104104
clap_complete = { version = "4", optional = true }
105105
chrono.workspace = true
106-
auto_impl.workspace = true
107106
ctrlc = { version = "3", optional = true }
108107
fdlimit = { version = "0.3", optional = true }
109108
clap_complete_fig = "4"

crates/anvil/src/eth/api.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2445,23 +2445,20 @@ impl EthApi {
24452445
state,
24462446
)?);
24472447
}
2448-
self.do_estimate_gas_with_state(request, state, block)
2448+
self.do_estimate_gas_with_state(request, &state, block)
24492449
})
24502450
.await?
24512451
}
24522452

24532453
/// Estimates the gas usage of the `request` with the state.
24542454
///
24552455
/// This will execute the transaction request and find the best gas limit via binary search.
2456-
fn do_estimate_gas_with_state<D>(
2456+
fn do_estimate_gas_with_state(
24572457
&self,
24582458
mut request: WithOtherFields<TransactionRequest>,
2459-
state: D,
2459+
state: &dyn DatabaseRef<Error = DatabaseError>,
24602460
block_env: BlockEnv,
2461-
) -> Result<u128>
2462-
where
2463-
D: DatabaseRef<Error = DatabaseError>,
2464-
{
2461+
) -> Result<u128> {
24652462
// If the request is a simple native token transfer we can optimize
24662463
// We assume it's a transfer if we have no input data.
24672464
let to = request.to.as_ref().and_then(TxKind::to);
@@ -2497,7 +2494,7 @@ impl EthApi {
24972494
// If we have non-zero gas price, cap gas limit by sender balance
24982495
if gas_price > 0 {
24992496
if let Some(from) = request.from {
2500-
let mut available_funds = self.backend.get_balance_with_state(&state, from)?;
2497+
let mut available_funds = self.backend.get_balance_with_state(state, from)?;
25012498
if let Some(value) = request.value {
25022499
if value > available_funds {
25032500
return Err(InvalidTransactionError::InsufficientFunds.into());

crates/anvil/src/eth/backend/db.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ use serde::{
2626
use std::{collections::BTreeMap, fmt, path::Path};
2727

2828
/// Helper trait get access to the full state data of the database
29-
#[auto_impl::auto_impl(Box)]
3029
pub trait MaybeFullDatabase: DatabaseRef<Error = DatabaseError> {
30+
/// Returns a reference to the database as a `dyn DatabaseRef`.
31+
// TODO: Required until trait upcasting is stabilized: <https://github.com/rust-lang/rust/issues/65991>
32+
fn as_dyn(&self) -> &dyn DatabaseRef<Error = DatabaseError>;
33+
3134
fn maybe_as_full_db(&self) -> Option<&HashMap<Address, DbAccount>> {
3235
None
3336
}
@@ -51,6 +54,10 @@ impl<'a, T: 'a + MaybeFullDatabase + ?Sized> MaybeFullDatabase for &'a T
5154
where
5255
&'a T: DatabaseRef<Error = DatabaseError>,
5356
{
57+
fn as_dyn(&self) -> &dyn DatabaseRef<Error = DatabaseError> {
58+
T::as_dyn(self)
59+
}
60+
5461
fn maybe_as_full_db(&self) -> Option<&HashMap<Address, DbAccount>> {
5562
T::maybe_as_full_db(self)
5663
}
@@ -69,7 +76,6 @@ where
6976
}
7077

7178
/// Helper trait to reset the DB if it's forked
72-
#[auto_impl::auto_impl(Box)]
7379
pub trait MaybeForkedDatabase {
7480
fn maybe_reset(&mut self, _url: Option<String>, block_number: BlockId) -> Result<(), String>;
7581

@@ -79,7 +85,6 @@ pub trait MaybeForkedDatabase {
7985
}
8086

8187
/// This bundles all required revm traits
82-
#[auto_impl::auto_impl(Box)]
8388
pub trait Db:
8489
DatabaseRef<Error = DatabaseError>
8590
+ Database<Error = DatabaseError>
@@ -188,6 +193,13 @@ pub trait Db:
188193
fn current_state(&self) -> StateDb;
189194
}
190195

196+
impl dyn Db {
197+
// TODO: Required until trait upcasting is stabilized: <https://github.com/rust-lang/rust/issues/65991>
198+
pub fn as_dbref(&self) -> &dyn DatabaseRef<Error = DatabaseError> {
199+
self.as_dyn()
200+
}
201+
}
202+
191203
/// Convenience impl only used to use any `Db` on the fly as the db layer for revm's CacheDB
192204
/// This is useful to create blocks without actually writing to the `Db`, but rather in the cache of
193205
/// the `CacheDB` see also
@@ -230,6 +242,10 @@ impl<T: DatabaseRef<Error = DatabaseError> + Send + Sync + Clone + fmt::Debug> D
230242
}
231243

232244
impl<T: DatabaseRef<Error = DatabaseError>> MaybeFullDatabase for CacheDB<T> {
245+
fn as_dyn(&self) -> &dyn DatabaseRef<Error = DatabaseError> {
246+
self
247+
}
248+
233249
fn maybe_as_full_db(&self) -> Option<&HashMap<Address, DbAccount>> {
234250
Some(&self.accounts)
235251
}
@@ -338,6 +354,10 @@ impl DatabaseRef for StateDb {
338354
}
339355

340356
impl MaybeFullDatabase for StateDb {
357+
fn as_dyn(&self) -> &dyn DatabaseRef<Error = DatabaseError> {
358+
self.0.as_dyn()
359+
}
360+
341361
fn maybe_as_full_db(&self) -> Option<&HashMap<Address, DbAccount>> {
342362
self.0.maybe_as_full_db()
343363
}

crates/anvil/src/eth/backend/executor.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ pub struct ExecutedTransactions {
8989
}
9090

9191
/// An executor for a series of transactions
92-
pub struct TransactionExecutor<'a, Db: ?Sized, Validator: TransactionValidator> {
92+
pub struct TransactionExecutor<'a, Db: ?Sized, V: TransactionValidator> {
9393
/// where to insert the transactions
9494
pub db: &'a mut Db,
9595
/// type used to validate before inclusion
96-
pub validator: Validator,
96+
pub validator: &'a V,
9797
/// all pending transactions
9898
pub pending: std::vec::IntoIter<Arc<PoolTransaction>>,
9999
pub block_env: BlockEnv,
@@ -111,7 +111,7 @@ pub struct TransactionExecutor<'a, Db: ?Sized, Validator: TransactionValidator>
111111
pub precompile_factory: Option<Arc<dyn PrecompileFactory>>,
112112
}
113113

114-
impl<'a, DB: Db + ?Sized, Validator: TransactionValidator> TransactionExecutor<'a, DB, Validator> {
114+
impl<'a, DB: Db + ?Sized, V: TransactionValidator> TransactionExecutor<'a, DB, V> {
115115
/// Executes all transactions and puts them in a new block with the provided `timestamp`
116116
pub fn execute(mut self) -> ExecutedTransactions {
117117
let mut transactions = Vec::new();
@@ -262,8 +262,8 @@ pub enum TransactionExecutionOutcome {
262262
DatabaseError(Arc<PoolTransaction>, DatabaseError),
263263
}
264264

265-
impl<'a, 'b, DB: Db + ?Sized, Validator: TransactionValidator> Iterator
266-
for &'b mut TransactionExecutor<'a, DB, Validator>
265+
impl<'a, 'b, DB: Db + ?Sized, V: TransactionValidator> Iterator
266+
for &'b mut TransactionExecutor<'a, DB, V>
267267
{
268268
type Item = TransactionExecutionOutcome;
269269

crates/anvil/src/eth/backend/mem/fork_db.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ use crate::{
88
use alloy_primitives::{Address, B256, U256, U64};
99
use alloy_rpc_types::BlockId;
1010
use foundry_evm::{
11-
backend::{BlockchainDb, DatabaseResult, RevertSnapshotAction, StateSnapshot},
11+
backend::{BlockchainDb, DatabaseError, DatabaseResult, RevertSnapshotAction, StateSnapshot},
1212
fork::database::ForkDbSnapshot,
13-
revm::Database,
13+
revm::{primitives::BlockEnv, Database},
1414
};
15+
use revm::DatabaseRef;
1516

1617
pub use foundry_evm::fork::database::ForkedDatabase;
17-
use foundry_evm::revm::primitives::BlockEnv;
1818

19-
/// Implement the helper for the fork database
2019
impl Db for ForkedDatabase {
2120
fn insert_account(&mut self, address: Address, account: AccountInfo) {
2221
self.database_mut().insert_account(address, account)
@@ -87,6 +86,10 @@ impl Db for ForkedDatabase {
8786
}
8887

8988
impl MaybeFullDatabase for ForkedDatabase {
89+
fn as_dyn(&self) -> &dyn DatabaseRef<Error = DatabaseError> {
90+
self
91+
}
92+
9093
fn clear_into_snapshot(&mut self) -> StateSnapshot {
9194
let db = self.inner().db();
9295
let accounts = std::mem::take(&mut *db.accounts.write());
@@ -118,6 +121,10 @@ impl MaybeFullDatabase for ForkedDatabase {
118121
}
119122

120123
impl MaybeFullDatabase for ForkDbSnapshot {
124+
fn as_dyn(&self) -> &dyn DatabaseRef<Error = DatabaseError> {
125+
self
126+
}
127+
121128
fn clear_into_snapshot(&mut self) -> StateSnapshot {
122129
std::mem::take(&mut self.snapshot)
123130
}

crates/anvil/src/eth/backend/mem/in_memory_db.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ impl Db for MemDb {
104104
}
105105

106106
impl MaybeFullDatabase for MemDb {
107+
fn as_dyn(&self) -> &dyn DatabaseRef<Error = foundry_evm::backend::DatabaseError> {
108+
self
109+
}
110+
107111
fn maybe_as_full_db(&self) -> Option<&HashMap<Address, DbAccount>> {
108112
Some(&self.inner.accounts)
109113
}

crates/anvil/src/eth/backend/mem/mod.rs

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -857,16 +857,19 @@ impl Backend {
857857
}
858858

859859
/// Creates an EVM instance with optionally injected precompiles.
860-
fn new_evm_with_inspector_ref<DB, I>(
860+
#[allow(clippy::type_complexity)]
861+
fn new_evm_with_inspector_ref<'i, 'db>(
861862
&self,
862-
db: DB,
863+
db: &'db dyn DatabaseRef<Error = DatabaseError>,
863864
env: EnvWithHandlerCfg,
864-
inspector: I,
865-
) -> revm::Evm<'_, I, WrapDatabaseRef<DB>>
866-
where
867-
DB: revm::DatabaseRef,
868-
I: InspectorExt<WrapDatabaseRef<DB>>,
869-
{
865+
inspector: &'i mut dyn InspectorExt<
866+
WrapDatabaseRef<&'db dyn DatabaseRef<Error = DatabaseError>>,
867+
>,
868+
) -> revm::Evm<
869+
'_,
870+
&'i mut dyn InspectorExt<WrapDatabaseRef<&'db dyn DatabaseRef<Error = DatabaseError>>>,
871+
WrapDatabaseRef<&'db dyn DatabaseRef<Error = DatabaseError>>,
872+
> {
870873
let mut evm = new_evm_with_inspector_ref(db, env, inspector);
871874
if let Some(factory) = &self.precompile_factory {
872875
inject_precompiles(&mut evm, factory.precompiles());
@@ -892,7 +895,7 @@ impl Backend {
892895

893896
let db = self.db.read().await;
894897
let mut inspector = self.build_inspector();
895-
let mut evm = self.new_evm_with_inspector_ref(&**db, env, &mut inspector);
898+
let mut evm = self.new_evm_with_inspector_ref(db.as_dyn(), env, &mut inspector);
896899
let ResultAndState { result, state } = evm.transact()?;
897900
let (exit_reason, gas_used, out, logs) = match result {
898901
ExecutionResult::Success { reason, gas_used, logs, output, .. } => {
@@ -1011,7 +1014,7 @@ impl Backend {
10111014
env.block.timestamp = U256::from(self.time.next_timestamp());
10121015

10131016
let executor = TransactionExecutor {
1014-
db: &mut *db,
1017+
db: &mut **db,
10151018
validator: self,
10161019
pending: pool_transactions.into_iter(),
10171020
block_env: env.block.clone(),
@@ -1151,10 +1154,10 @@ impl Backend {
11511154
self.with_database_at(block_request, |state, block| {
11521155
let block_number = block.number.to::<u64>();
11531156
let (exit, out, gas, state) = match overrides {
1154-
None => self.call_with_state(state, request, fee_details, block),
1157+
None => self.call_with_state(state.as_dyn(), request, fee_details, block),
11551158
Some(overrides) => {
11561159
let state = state::apply_state_override(overrides.into_iter().collect(), state)?;
1157-
self.call_with_state(state, request, fee_details, block)
1160+
self.call_with_state(state.as_dyn(), request, fee_details, block)
11581161
},
11591162
}?;
11601163
trace!(target: "backend", "call return {:?} out: {:?} gas {} on block {}", exit, out, gas, block_number);
@@ -1263,16 +1266,13 @@ impl Backend {
12631266
inspector
12641267
}
12651268

1266-
pub fn call_with_state<D>(
1269+
pub fn call_with_state(
12671270
&self,
1268-
state: D,
1271+
state: &dyn DatabaseRef<Error = DatabaseError>,
12691272
request: WithOtherFields<TransactionRequest>,
12701273
fee_details: FeeDetails,
12711274
block_env: BlockEnv,
1272-
) -> Result<(InstructionResult, Option<Output>, u128, State), BlockchainError>
1273-
where
1274-
D: DatabaseRef<Error = DatabaseError>,
1275-
{
1275+
) -> Result<(InstructionResult, Option<Output>, u128, State), BlockchainError> {
12761276
let mut inspector = self.build_inspector();
12771277

12781278
let env = self.build_call_env(request, fee_details, block_env);
@@ -1319,8 +1319,11 @@ impl Backend {
13191319
);
13201320

13211321
let env = self.build_call_env(request, fee_details, block);
1322-
let mut evm =
1323-
self.new_evm_with_inspector_ref(state, env, &mut inspector);
1322+
let mut evm = self.new_evm_with_inspector_ref(
1323+
state.as_dyn(),
1324+
env,
1325+
&mut inspector,
1326+
);
13241327
let ResultAndState { result, state: _ } = evm.transact()?;
13251328

13261329
drop(evm);
@@ -1352,7 +1355,7 @@ impl Backend {
13521355
.with_tracing_config(TracingInspectorConfig::from_geth_config(&config));
13531356

13541357
let env = self.build_call_env(request, fee_details, block);
1355-
let mut evm = self.new_evm_with_inspector_ref(state, env, &mut inspector);
1358+
let mut evm = self.new_evm_with_inspector_ref(state.as_dyn(), env, &mut inspector);
13561359
let ResultAndState { result, state: _ } = evm.transact()?;
13571360

13581361
let (exit_reason, gas_used, out) = match result {
@@ -1381,16 +1384,13 @@ impl Backend {
13811384
.await?
13821385
}
13831386

1384-
pub fn build_access_list_with_state<D>(
1387+
pub fn build_access_list_with_state(
13851388
&self,
1386-
state: D,
1389+
state: &dyn DatabaseRef<Error = DatabaseError>,
13871390
request: WithOtherFields<TransactionRequest>,
13881391
fee_details: FeeDetails,
13891392
block_env: BlockEnv,
1390-
) -> Result<(InstructionResult, Option<Output>, u64, AccessList), BlockchainError>
1391-
where
1392-
D: DatabaseRef<Error = DatabaseError>,
1393-
{
1393+
) -> Result<(InstructionResult, Option<Output>, u64, AccessList), BlockchainError> {
13941394
let from = request.from.unwrap_or_default();
13951395
let to = if let Some(TxKind::Call(to)) = request.to {
13961396
to
@@ -1911,7 +1911,7 @@ impl Backend {
19111911

19121912
let db = self.db.read().await;
19131913
let block = self.env.read().block.clone();
1914-
Ok(f(Box::new(&*db), block))
1914+
Ok(f(Box::new(&**db), block))
19151915
}
19161916

19171917
pub async fn storage_at(
@@ -1937,17 +1937,14 @@ impl Backend {
19371937
address: Address,
19381938
block_request: Option<BlockRequest>,
19391939
) -> Result<Bytes, BlockchainError> {
1940-
self.with_database_at(block_request, |db, _| self.get_code_with_state(db, address)).await?
1940+
self.with_database_at(block_request, |db, _| self.get_code_with_state(&db, address)).await?
19411941
}
19421942

1943-
pub fn get_code_with_state<D>(
1943+
pub fn get_code_with_state(
19441944
&self,
1945-
state: D,
1945+
state: &dyn DatabaseRef<Error = DatabaseError>,
19461946
address: Address,
1947-
) -> Result<Bytes, BlockchainError>
1948-
where
1949-
D: DatabaseRef<Error = DatabaseError>,
1950-
{
1947+
) -> Result<Bytes, BlockchainError> {
19511948
trace!(target: "backend", "get code for {:?}", address);
19521949
let account = state.basic_ref(address)?.unwrap_or_default();
19531950
if account.code_hash == KECCAK_EMPTY {

crates/anvil/src/eth/backend/validate.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use foundry_evm::revm::primitives::{AccountInfo, EnvWithHandlerCfg};
66

77
/// A trait for validating transactions
88
#[async_trait::async_trait]
9-
#[auto_impl::auto_impl(&, Box)]
109
pub trait TransactionValidator {
1110
/// Validates the transaction's validity when it comes to nonce, payment
1211
///

0 commit comments

Comments
 (0)