reth_rpc_eth_api/helpers/
bal.rs1use 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
18pub trait GetBlockAccessList: Trace + Call + LoadBlock {
20 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(ð_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 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}