Skip to main content

reth_rpc_eth_api/helpers/
bal.rs

1//! Helpers for `eth_blockAccessList` RPC method.
2use alloy_consensus::BlockHeader;
3use alloy_eips::eip7928::BlockAccessList;
4use alloy_rpc_types_eth::BlockId;
5use reth_errors::RethError;
6use reth_evm::{block::BlockExecutor, ConfigureEvm, Evm};
7use reth_revm::{database::StateProviderDatabase, State};
8use reth_rpc_eth_types::{
9    cache::db::StateProviderTraitObjWrapper, error::FromEthApiError, EthApiError,
10};
11use reth_storage_api::StateProviderFactory;
12
13use crate::{
14    helpers::{Call, LoadBlock, Trace},
15    RpcNodeCore,
16};
17
18/// Helper trait for `eth_blockAccessList` RPC method.
19pub trait GetBlockAccessList: Trace + Call + LoadBlock {
20    /// Retrieves the block access list for a block identified by its hash.
21    fn get_block_access_list(
22        &self,
23        block_id: BlockId,
24    ) -> impl Future<Output = Result<Option<BlockAccessList>, Self::Error>> + Send {
25        async move {
26            let block = self
27                .recovered_block(block_id)
28                .await?
29                .ok_or_else(|| EthApiError::HeaderNotFound(block_id))?;
30
31            self.spawn_blocking_io(move |eth_api| {
32                let state = eth_api
33                    .provider()
34                    .state_by_block_id(block.parent_hash().into())
35                    .map_err(Self::Error::from_eth_err)?;
36
37                let mut db = State::builder()
38                    .with_database(StateProviderDatabase::new(StateProviderTraitObjWrapper(state)))
39                    .with_bal_builder()
40                    .build();
41
42                let block_txs = block.transactions_recovered();
43                let mut executor = RpcNodeCore::evm_config(&eth_api)
44                    .executor_for_block(&mut db, block.sealed_block())
45                    .map_err(RethError::other)
46                    .map_err(Self::Error::from_eth_err)?;
47
48                executor.apply_pre_execution_changes().map_err(Self::Error::from_eth_err)?;
49                executor.evm_mut().db_mut().bump_bal_index();
50
51                // replay all transactions prior to the targeted transaction
52                for block_tx in block_txs {
53                    executor.execute_transaction(block_tx).map_err(Self::Error::from_eth_err)?;
54                    executor.evm_mut().db_mut().bump_bal_index();
55                }
56
57                executor
58                    .apply_post_execution_changes()
59                    .map_err(|err| EthApiError::Internal(err.into()))?;
60
61                let bal = db.take_built_alloy_bal();
62                Ok(bal)
63            })
64            .await
65        }
66    }
67}