refactor(rpc): use ChainState type (#1756)

This commit is contained in:
Matthias Seitz
2023-03-15 14:06:53 +01:00
committed by GitHub
parent a00df7ffbb
commit bba61c0b61
4 changed files with 34 additions and 61 deletions

View File

@ -27,7 +27,6 @@ use revm::{
},
Database,
};
use std::ops::Deref;
// Gas per transaction not creating a contract.
const MIN_TRANSACTION_GAS: u64 = 21_000u64;
@ -48,7 +47,7 @@ where
) -> EthResult<(ResultAndState, Env)> {
let (cfg, block_env, at) = self.evm_env_at(at).await?;
let state = self.state_at_block_id(at)?.ok_or_else(|| EthApiError::UnknownBlockNumber)?;
self.call_with(cfg, block_env, request, &*state, state_overrides)
self.call_with(cfg, block_env, request, state, state_overrides)
}
/// Executes the call request using the given environment against the state provider
@ -88,7 +87,7 @@ where
) -> EthResult<U256> {
let (cfg, block_env, at) = self.evm_env_at(at).await?;
let state = self.state_at_block_id(at)?.ok_or_else(|| EthApiError::UnknownBlockNumber)?;
self.estimate_gas_with(cfg, block_env, request, &*state)
self.estimate_gas_with(cfg, block_env, request, state)
}
/// Estimates the gas usage of the `request` with the state.
@ -280,7 +279,7 @@ where
cfg.disable_block_gas_limit = true;
let env = build_call_evm_env(cfg, block, request.clone())?;
let mut db = SubState::new(State::new(state.deref()));
let mut db = SubState::new(State::new(state));
let from = request.from.unwrap_or_default();
let to = if let Some(to) = request.to {

View File

@ -8,12 +8,10 @@ use async_trait::async_trait;
use reth_interfaces::Result;
use reth_network_api::NetworkInfo;
use reth_primitives::{Address, BlockId, BlockNumberOrTag, ChainInfo, H256, U64};
use reth_provider::{
BlockProvider, EvmEnvProvider, StateProvider as StateProviderTrait, StateProviderFactory,
};
use reth_provider::{providers::ChainState, BlockProvider, EvmEnvProvider, StateProviderFactory};
use reth_rpc_types::FeeHistoryCache;
use reth_transaction_pool::TransactionPool;
use std::{num::NonZeroUsize, ops::Deref, sync::Arc};
use std::{num::NonZeroUsize, sync::Arc};
mod block;
mod call;
@ -92,37 +90,6 @@ impl<Client, Pool, Network> EthApi<Client, Pool, Network> {
}
}
// Transparent wrapper to enable state access helpers
// returning latest state provider when appropiate
pub(crate) enum StateProvider<'a, H, L> {
History(H),
Latest(L),
_Unreachable(&'a ()), // like a PhantomData for 'a
}
type HistoryOrLatest<'a, Client> = StateProvider<
'a,
<Client as StateProviderFactory>::HistorySP<'a>,
<Client as StateProviderFactory>::LatestSP<'a>,
>;
impl<'a, H, L> Deref for StateProvider<'a, H, L>
where
Self: 'a,
H: StateProviderTrait + 'a,
L: StateProviderTrait + 'a,
{
type Target = dyn StateProviderTrait + 'a;
fn deref(&self) -> &Self::Target {
match self {
StateProvider::History(h) => h,
StateProvider::Latest(l) => l,
StateProvider::_Unreachable(()) => unreachable!(),
}
}
}
// === State access helpers ===
impl<Client, Pool, Network> EthApi<Client, Pool, Network>
@ -137,23 +104,18 @@ where
pub(crate) fn state_at_block_id_or_latest(
&self,
block_id: Option<BlockId>,
) -> Result<Option<HistoryOrLatest<'_, Client>>> {
) -> Result<Option<ChainState<'_>>> {
if let Some(block_id) = block_id {
self.state_at_block_id(block_id)
} else {
self.latest_state().map(|v| Some(StateProvider::Latest(v)))
self.latest_state().map(ChainState::boxed).map(Some)
}
}
/// Returns the state at the given [BlockId] enum.
pub(crate) fn state_at_block_id(
&self,
block_id: BlockId,
) -> Result<Option<HistoryOrLatest<'_, Client>>> {
pub(crate) fn state_at_block_id(&self, block_id: BlockId) -> Result<Option<ChainState<'_>>> {
match block_id {
BlockId::Hash(hash) => {
self.state_at_hash(hash.into()).map(|s| Some(StateProvider::History(s)))
}
BlockId::Hash(hash) => self.state_at_hash(hash.into()).map(ChainState::boxed).map(Some),
BlockId::Number(num) => self.state_at_block_number(num),
}
}
@ -164,7 +126,7 @@ where
pub(crate) fn state_at_block_number(
&self,
num: BlockNumberOrTag,
) -> Result<Option<HistoryOrLatest<'_, Client>>> {
) -> Result<Option<ChainState<'_>>> {
if let Some(number) = self.convert_block_number(num)? {
self.state_at_number(number).map(Some)
} else {
@ -181,10 +143,10 @@ where
}
/// Returns the state at the given block number
pub(crate) fn state_at_number(&self, block_number: u64) -> Result<HistoryOrLatest<'_, Client>> {
pub(crate) fn state_at_number(&self, block_number: u64) -> Result<ChainState<'_>> {
match self.convert_block_number(BlockNumberOrTag::Latest)? {
Some(num) if num == block_number => self.latest_state().map(StateProvider::Latest),
_ => self.client().history_by_block_number(block_number).map(StateProvider::History),
Some(num) if num == block_number => self.latest_state().map(ChainState::boxed),
_ => self.client().history_by_block_number(block_number).map(ChainState::boxed),
}
}

View File

@ -1,14 +1,13 @@
//! Contains RPC handler implementations specific to state.
use crate::{
eth::{
api::StateProvider,
error::{EthApiError, EthResult},
},
eth::error::{EthApiError, EthResult},
EthApi,
};
use reth_primitives::{Address, BlockId, Bytes, H256, KECCAK_EMPTY, U256};
use reth_provider::{BlockProvider, EvmEnvProvider, StateProviderFactory};
use reth_primitives::{Address, BlockId, BlockNumberOrTag, Bytes, H256, KECCAK_EMPTY, U256};
use reth_provider::{
AccountProvider, BlockProvider, EvmEnvProvider, StateProvider, StateProviderFactory,
};
use reth_rpc_types::{EIP1186AccountProofResponse, StorageProof};
impl<Client, Pool, Network> EthApi<Client, Pool, Network>
@ -59,14 +58,17 @@ where
keys: Vec<H256>,
block_id: Option<BlockId>,
) -> EthResult<EIP1186AccountProofResponse> {
let state =
self.state_at_block_id_or_latest(block_id)?.ok_or(EthApiError::UnknownBlockNumber)?;
let block_id = block_id.unwrap_or(BlockId::Number(BlockNumberOrTag::Latest));
// TODO: remove when HistoricalStateProviderRef::proof is implemented
if matches!(state, StateProvider::History(_)) {
if !block_id.is_latest() {
return Err(EthApiError::InvalidBlockRange)
}
let state = self
.state_at_block_id_or_latest(Some(block_id))?
.ok_or(EthApiError::UnknownBlockNumber)?;
let (account_proof, storage_hash, stg_proofs) = state.proof(address, &keys)?;
let storage_proof = keys