fix: improve eth_createAccessList (#4954)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
Yash Atreya
2023-10-09 08:01:23 -04:00
committed by GitHub
parent 18c4891238
commit 9561f2860a
2 changed files with 28 additions and 11 deletions

View File

@ -12,7 +12,7 @@ use crate::{
EthApi, EthApi,
}; };
use reth_network_api::NetworkInfo; use reth_network_api::NetworkInfo;
use reth_primitives::{AccessList, BlockId, BlockNumberOrTag, Bytes, U256}; use reth_primitives::{AccessListWithGasUsed, BlockId, BlockNumberOrTag, Bytes, U256};
use reth_provider::{ use reth_provider::{
BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProvider, StateProviderFactory, BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProvider, StateProviderFactory,
}; };
@ -168,7 +168,7 @@ where
/// Estimates the gas usage of the `request` with the state. /// Estimates the gas usage of the `request` with the state.
/// ///
/// This will execute the [CallRequest] and find the best gas limit via binary search /// This will execute the [CallRequest] and find the best gas limit via binary search
fn estimate_gas_with<S>( pub fn estimate_gas_with<S>(
&self, &self,
mut cfg: CfgEnv, mut cfg: CfgEnv,
block: BlockEnv, block: BlockEnv,
@ -337,11 +337,23 @@ where
Ok(U256::from(highest_gas_limit)) Ok(U256::from(highest_gas_limit))
} }
/// Creates the AccessList for the `request` at the [BlockId] or latest.
pub(crate) async fn create_access_list_at( pub(crate) async fn create_access_list_at(
&self,
request: CallRequest,
block_number: Option<BlockId>,
) -> EthResult<AccessListWithGasUsed> {
self.on_blocking_task(|this| async move {
this.create_access_list_with(request, block_number).await
})
.await
}
async fn create_access_list_with(
&self, &self,
mut request: CallRequest, mut request: CallRequest,
at: Option<BlockId>, at: Option<BlockId>,
) -> EthResult<AccessList> { ) -> EthResult<AccessListWithGasUsed> {
let block_id = at.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest)); let block_id = at.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest));
let (cfg, block, at) = self.evm_env_at(block_id).await?; let (cfg, block, at) = self.evm_env_at(block_id).await?;
let state = self.state_at(at)?; let state = self.state_at(at)?;
@ -377,7 +389,7 @@ where
let precompiles = get_precompiles(env.cfg.spec_id); let precompiles = get_precompiles(env.cfg.spec_id);
let mut inspector = AccessListInspector::new(initial, from, to, precompiles); let mut inspector = AccessListInspector::new(initial, from, to, precompiles);
let (result, _env) = inspect(&mut db, env, &mut inspector)?; let (result, env) = inspect(&mut db, env, &mut inspector)?;
match result.result { match result.result {
ExecutionResult::Halt { reason, .. } => Err(match reason { ExecutionResult::Halt { reason, .. } => Err(match reason {
@ -389,7 +401,14 @@ where
} }
ExecutionResult::Success { .. } => Ok(()), ExecutionResult::Success { .. } => Ok(()),
}?; }?;
Ok(inspector.into_access_list())
let access_list = inspector.into_access_list();
// calculate the gas used using the access list
request.access_list = Some(access_list.clone());
let gas_used = self.estimate_gas_with(env.cfg, env.block, request, db.db.state())?;
Ok(AccessListWithGasUsed { access_list, gas_used })
} }
} }

View File

@ -254,15 +254,13 @@ where
/// Handler for: `eth_createAccessList` /// Handler for: `eth_createAccessList`
async fn create_access_list( async fn create_access_list(
&self, &self,
mut request: CallRequest, request: CallRequest,
block_number: Option<BlockId>, block_number: Option<BlockId>,
) -> Result<AccessListWithGasUsed> { ) -> Result<AccessListWithGasUsed> {
trace!(target: "rpc::eth", ?request, ?block_number, "Serving eth_createAccessList"); trace!(target: "rpc::eth", ?request, ?block_number, "Serving eth_createAccessList");
let block_id = block_number.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest)); let access_list_with_gas_used = self.create_access_list_at(request, block_number).await?;
let access_list = self.create_access_list_at(request.clone(), block_number).await?;
request.access_list = Some(access_list.clone()); Ok(access_list_with_gas_used)
let gas_used = self.estimate_gas_at(request, block_id).await?;
Ok(AccessListWithGasUsed { access_list, gas_used })
} }
/// Handler for: `eth_estimateGas` /// Handler for: `eth_estimateGas`