feat: use BlockHashOrNum in providers (#2627)

This commit is contained in:
Dan Cline
2023-05-10 16:03:16 -04:00
committed by GitHub
parent abcadd987c
commit 7d3016f0f2
31 changed files with 498 additions and 248 deletions

View File

@ -7,7 +7,8 @@ use clap::{
use futures::FutureExt;
use reth_network_api::{NetworkInfo, Peers};
use reth_provider::{
BlockProvider, CanonStateSubscriptions, EvmEnvProvider, HeaderProvider, StateProviderFactory,
BlockProviderIdExt, CanonStateSubscriptions, EvmEnvProvider, HeaderProvider,
StateProviderFactory,
};
use reth_rpc::{JwtError, JwtSecret};
use reth_rpc_builder::{
@ -141,7 +142,7 @@ impl RpcServerArgs {
jwt_secret: JwtSecret,
) -> Result<(RpcServerHandle, AuthServerHandle), RpcError>
where
Client: BlockProvider
Client: BlockProviderIdExt
+ HeaderProvider
+ StateProviderFactory
+ EvmEnvProvider
@ -193,7 +194,7 @@ impl RpcServerArgs {
events: Events,
) -> Result<RpcServerHandle, RpcError>
where
Client: BlockProvider
Client: BlockProviderIdExt
+ HeaderProvider
+ StateProviderFactory
+ EvmEnvProvider
@ -228,7 +229,7 @@ impl RpcServerArgs {
jwt_secret: JwtSecret,
) -> Result<AuthServerHandle, RpcError>
where
Client: BlockProvider
Client: BlockProviderIdExt
+ HeaderProvider
+ StateProviderFactory
+ EvmEnvProvider

View File

@ -17,8 +17,8 @@ use reth_primitives::{
use reth_provider::{
chain::{ChainSplit, SplitAt},
post_state::PostState,
BlockIdProvider, CanonStateNotification, CanonStateNotificationSender, CanonStateNotifications,
Chain, ExecutorFactory, HeaderProvider, Transaction,
BlockNumProvider, CanonStateNotification, CanonStateNotificationSender,
CanonStateNotifications, Chain, ExecutorFactory, HeaderProvider, Transaction,
};
use std::{
collections::{BTreeMap, HashMap},

View File

@ -389,8 +389,9 @@ mod tests {
use mockall::mock;
use reth_interfaces::{Error::Consensus, Result};
use reth_primitives::{
hex_literal::hex, proofs, Account, Address, BlockHash, BlockId, Bytes, ChainSpecBuilder,
Header, Signature, TransactionKind, TransactionSigned, Withdrawal, MAINNET, U256,
hex_literal::hex, proofs, Account, Address, BlockHash, BlockHashOrNumber, Bytes,
ChainSpecBuilder, Header, Signature, TransactionKind, TransactionSigned, Withdrawal,
MAINNET, U256,
};
use std::ops::RangeBounds;
@ -402,7 +403,7 @@ mod tests {
fn withdrawals_by_block(
&self,
_id: BlockId,
_id: BlockHashOrNumber,
_timestamp: u64,
) -> RethResult<Option<Vec<Withdrawal>>> ;
}
@ -475,7 +476,7 @@ mod tests {
fn withdrawals_by_block(
&self,
_id: BlockId,
_id: BlockHashOrNumber,
_timestamp: u64,
) -> RethResult<Option<Vec<Withdrawal>>> {
self.withdrawals_provider.withdrawals_by_block(_id, _timestamp)

View File

@ -23,7 +23,7 @@ use reth_primitives::{
proofs, Block, BlockNumberOrTag, ChainSpec, Header, IntoRecoveredTransaction, Receipt,
SealedBlock, Withdrawal, EMPTY_OMMER_ROOT, H256, U256,
};
use reth_provider::{BlockProvider, BlockSource, PostState, StateProviderFactory};
use reth_provider::{BlockProviderIdExt, BlockSource, PostState, StateProviderFactory};
use reth_revm::{
database::{State, SubState},
env::tx_env_with_recovered,
@ -98,7 +98,7 @@ impl<Client, Pool, Tasks> BasicPayloadJobGenerator<Client, Pool, Tasks> {}
impl<Client, Pool, Tasks> PayloadJobGenerator for BasicPayloadJobGenerator<Client, Pool, Tasks>
where
Client: StateProviderFactory + BlockProvider + Clone + Unpin + 'static,
Client: StateProviderFactory + BlockProviderIdExt + Clone + Unpin + 'static,
Pool: TransactionPool + Unpin + 'static,
Tasks: TaskSpawner + Clone + Unpin + 'static,
{
@ -111,7 +111,7 @@ where
let parent_block = if attributes.parent.is_zero() {
// use latest block if parent is zero: genesis block
self.client
.block(BlockNumberOrTag::Latest.into())?
.block_by_number_or_tag(BlockNumberOrTag::Latest)?
.ok_or_else(|| PayloadBuilderError::MissingParentBlock(attributes.parent))?
.seal_slow()
} else {

View File

@ -1,4 +1,4 @@
use crate::{BlockNumber, BlockNumberOrTag, H256};
use crate::{BlockNumber, H256};
/// Current status of the blockchain's head.
#[derive(Default, Clone, Debug, Eq, PartialEq)]
@ -7,22 +7,4 @@ pub struct ChainInfo {
pub best_hash: H256,
/// The block number of the highest fully synced block.
pub best_number: BlockNumber,
/// Last block that was finalized.
pub last_finalized: Option<BlockNumber>,
/// Safe block
pub safe_finalized: Option<BlockNumber>,
}
impl ChainInfo {
/// Attempts to convert a [BlockNumber](crate::rpc::BlockNumber) enum to a numeric value
pub fn convert_block_number(&self, number: BlockNumberOrTag) -> Option<u64> {
match number {
BlockNumberOrTag::Finalized => self.last_finalized,
BlockNumberOrTag::Safe => self.safe_finalized,
BlockNumberOrTag::Earliest => Some(0),
BlockNumberOrTag::Number(num) => Some(num),
BlockNumberOrTag::Pending => None,
BlockNumberOrTag::Latest => Some(self.best_number),
}
}
}

View File

@ -10,7 +10,9 @@ use jsonrpsee::{
server::{RpcModule, ServerHandle},
};
use reth_network_api::{NetworkInfo, Peers};
use reth_provider::{BlockProvider, EvmEnvProvider, HeaderProvider, StateProviderFactory};
use reth_provider::{
BlockProviderIdExt, EvmEnvProvider, HeaderProvider, ReceiptProviderIdExt, StateProviderFactory,
};
use reth_rpc::{
eth::cache::EthStateCache, AuthLayer, Claims, EngineEthApi, EthApi, EthFilter,
JwtAuthValidator, JwtSecret,
@ -35,7 +37,8 @@ pub async fn launch<Client, Pool, Network, Tasks, EngineApi>(
secret: JwtSecret,
) -> Result<AuthServerHandle, RpcError>
where
Client: BlockProvider
Client: BlockProviderIdExt
+ ReceiptProviderIdExt
+ HeaderProvider
+ StateProviderFactory
+ EvmEnvProvider
@ -63,7 +66,7 @@ pub async fn launch_with_eth_api<Client, Pool, Network, EngineApi>(
secret: JwtSecret,
) -> Result<AuthServerHandle, RpcError>
where
Client: BlockProvider
Client: BlockProviderIdExt
+ HeaderProvider
+ StateProviderFactory
+ EvmEnvProvider

View File

@ -25,13 +25,13 @@
//!
//! ```
//! use reth_network_api::{NetworkInfo, Peers};
//! use reth_provider::{BlockProvider, CanonStateSubscriptions, StateProviderFactory, EvmEnvProvider};
//! use reth_provider::{BlockProviderIdExt, CanonStateSubscriptions, StateProviderFactory, EvmEnvProvider};
//! use reth_rpc_builder::{RethRpcModule, RpcModuleBuilder, RpcServerConfig, ServerBuilder, TransportRpcModuleConfig};
//! use reth_tasks::TokioTaskExecutor;
//! use reth_transaction_pool::TransactionPool;
//! pub async fn launch<Client, Pool, Network, Events>(client: Client, pool: Pool, network: Network, events: Events)
//! where
//! Client: BlockProvider + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
//! Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
//! Pool: TransactionPool + Clone + 'static,
//! Network: NetworkInfo + Peers + Clone + 'static,
//! Events: CanonStateSubscriptions + Clone + 'static,
@ -58,7 +58,7 @@
//! ```
//! use tokio::try_join;
//! use reth_network_api::{NetworkInfo, Peers};
//! use reth_provider::{BlockProvider, CanonStateSubscriptions, StateProviderFactory, EvmEnvProvider};
//! use reth_provider::{BlockProviderIdExt, CanonStateSubscriptions, StateProviderFactory, EvmEnvProvider};
//! use reth_rpc::JwtSecret;
//! use reth_rpc_builder::{RethRpcModule, RpcModuleBuilder, RpcServerConfig, TransportRpcModuleConfig};
//! use reth_tasks::TokioTaskExecutor;
@ -67,7 +67,7 @@
//! use reth_rpc_builder::auth::AuthServerConfig;
//! pub async fn launch<Client, Pool, Network, Events, EngineApi>(client: Client, pool: Pool, network: Network, events: Events, engine_api: EngineApi)
//! where
//! Client: BlockProvider + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
//! Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
//! Pool: TransactionPool + Clone + 'static,
//! Network: NetworkInfo + Peers + Clone + 'static,
//! Events: CanonStateSubscriptions + Clone + 'static,
@ -106,7 +106,10 @@ use jsonrpsee::{
};
use reth_ipc::server::IpcServer;
use reth_network_api::{NetworkInfo, Peers};
use reth_provider::{BlockProvider, CanonStateSubscriptions, EvmEnvProvider, StateProviderFactory};
use reth_provider::{
BlockProvider, BlockProviderIdExt, CanonStateSubscriptions, EvmEnvProvider,
StateProviderFactory,
};
use reth_rpc::{
eth::cache::EthStateCache, AdminApi, DebugApi, EngineEthApi, EthApi, EthFilter, EthPubSub,
EthSubscriptionIdProvider, NetApi, TraceApi, TracingCallGuard, TxPoolApi, Web3Api,
@ -159,7 +162,7 @@ pub async fn launch<Client, Pool, Network, Tasks, Events>(
events: Events,
) -> Result<RpcServerHandle, RpcError>
where
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Pool: TransactionPool + Clone + 'static,
Network: NetworkInfo + Peers + Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,
@ -252,7 +255,7 @@ impl<Client, Pool, Network, Tasks, Events> RpcModuleBuilder<Client, Pool, Networ
impl<Client, Pool, Network, Tasks, Events> RpcModuleBuilder<Client, Pool, Network, Tasks, Events>
where
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Pool: TransactionPool + Clone + 'static,
Network: NetworkInfo + Peers + Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,
@ -450,7 +453,8 @@ impl RpcModuleSelection {
config: RpcModuleConfig,
) -> RpcModule<()>
where
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Client:
BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Pool: TransactionPool + Clone + 'static,
Network: NetworkInfo + Peers + Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,
@ -651,7 +655,7 @@ where
impl<Client, Pool, Network, Tasks, Events> RethModuleRegistry<Client, Pool, Network, Tasks, Events>
where
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + Clone + Unpin + 'static,
Pool: TransactionPool + Clone + 'static,
Network: NetworkInfo + Peers + Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,

View File

@ -4,7 +4,7 @@ use jsonrpsee_core::RpcResult as Result;
use reth_beacon_consensus::BeaconConsensusEngineHandle;
use reth_interfaces::consensus::ForkchoiceState;
use reth_payload_builder::PayloadStore;
use reth_primitives::{BlockHash, BlockId, BlockNumber, ChainSpec, Hardfork, U64};
use reth_primitives::{BlockHash, BlockHashOrNumber, BlockNumber, ChainSpec, Hardfork, U64};
use reth_provider::{BlockProvider, EvmEnvProvider, HeaderProvider, StateProviderFactory};
use reth_rpc_api::EngineApiServer;
use reth_rpc_types::engine::{
@ -170,7 +170,7 @@ where
for num in start..start + count {
let block = self
.client
.block(BlockId::Number(num.into()))
.block(BlockHashOrNumber::Number(num))
.map_err(|err| EngineApiError::Internal(Box::new(err)))?;
result.push(block.map(Into::into));
}
@ -192,7 +192,7 @@ where
for hash in hashes {
let block = self
.client
.block(BlockId::Hash(hash.into()))
.block(BlockHashOrNumber::Hash(hash))
.map_err(|err| EngineApiError::Internal(Box::new(err)))?;
result.push(block.map(Into::into));
}

View File

@ -10,7 +10,7 @@ use crate::{
use async_trait::async_trait;
use jsonrpsee::core::RpcResult;
use reth_primitives::{Block, BlockId, BlockNumberOrTag, Bytes, TransactionSigned, H256, U256};
use reth_provider::{BlockProvider, HeaderProvider, StateProviderBox};
use reth_provider::{BlockProviderIdExt, HeaderProvider, ReceiptProviderIdExt, StateProviderBox};
use reth_revm::{
database::{State, SubState},
env::tx_env_with_recovered,
@ -56,7 +56,7 @@ impl<Client, Eth> DebugApi<Client, Eth> {
impl<Client, Eth> DebugApi<Client, Eth>
where
Client: BlockProvider + HeaderProvider + 'static,
Client: BlockProviderIdExt + HeaderProvider + 'static,
Eth: EthTransactions + 'static,
{
/// Acquires a permit to execute a tracing call.
@ -206,7 +206,7 @@ where
#[async_trait]
impl<Client, Eth> DebugApiServer for DebugApi<Client, Eth>
where
Client: BlockProvider + HeaderProvider + 'static,
Client: BlockProviderIdExt + HeaderProvider + 'static,
Eth: EthApiSpec + 'static,
{
/// Handler for `debug_getRawHeader`
@ -232,7 +232,7 @@ where
/// Handler for `debug_getRawBlock`
async fn raw_block(&self, block_id: BlockId) -> RpcResult<Bytes> {
let block = self.client.block(block_id).to_rpc_result()?;
let block = self.client.block_by_id(block_id).to_rpc_result()?;
let mut res = Vec::new();
if let Some(mut block) = block {
@ -261,7 +261,8 @@ where
/// Handler for `debug_getRawReceipts`
async fn raw_receipts(&self, block_id: BlockId) -> RpcResult<Vec<Bytes>> {
let receipts = self.client.receipts_by_block(block_id).to_rpc_result()?.unwrap_or_default();
let receipts =
self.client.receipts_by_block_id(block_id).to_rpc_result()?.unwrap_or_default();
let mut all_receipts = Vec::with_capacity(receipts.len());
for receipt in receipts {

View File

@ -5,12 +5,12 @@ use crate::{
EthApi,
};
use reth_primitives::BlockId;
use reth_provider::{BlockProvider, EvmEnvProvider, StateProviderFactory};
use reth_provider::{BlockProviderIdExt, EvmEnvProvider, StateProviderFactory};
use reth_rpc_types::{Block, Index, RichBlock};
impl<Client, Pool, Network> EthApi<Client, Pool, Network>
where
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + 'static,
{
/// Returns the uncle headers of the given block
///
@ -20,7 +20,7 @@ where
block_id: impl Into<BlockId>,
) -> EthResult<Option<Vec<reth_primitives::Header>>> {
let block_id = block_id.into();
Ok(self.client().ommers(block_id)?)
Ok(self.client().ommers_by_id(block_id)?)
}
pub(crate) async fn ommer_by_block_and_index(
@ -34,7 +34,7 @@ where
// Pending block can be fetched directly without need for caching
self.client().pending_block()?.map(|block| block.ommers)
} else {
self.client().ommers(block_id)?
self.client().ommers_by_id(block_id)?
}
.unwrap_or_default();

View File

@ -14,7 +14,7 @@ use crate::{
use ethers_core::utils::get_contract_address;
use reth_network_api::NetworkInfo;
use reth_primitives::{AccessList, BlockId, BlockNumberOrTag, U256};
use reth_provider::{BlockProvider, EvmEnvProvider, StateProvider, StateProviderFactory};
use reth_provider::{BlockProviderIdExt, EvmEnvProvider, StateProvider, StateProviderFactory};
use reth_revm::{
access_list::AccessListInspector,
database::{State, SubState},
@ -34,7 +34,7 @@ const MIN_CREATE_GAS: u64 = 53_000u64;
impl<Client, Pool, Network> EthApi<Client, Pool, Network>
where
Pool: TransactionPool + Clone + 'static,
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + 'static,
Network: NetworkInfo + Send + Sync + 'static,
{
/// Estimate gas needed for execution of the `request` at the [BlockId].

View File

@ -6,7 +6,7 @@ use crate::{
};
use reth_network_api::NetworkInfo;
use reth_primitives::{BlockId, BlockNumberOrTag, U256};
use reth_provider::{BlockProvider, EvmEnvProvider, StateProviderFactory};
use reth_provider::{BlockProviderIdExt, EvmEnvProvider, StateProviderFactory};
use reth_rpc_types::{FeeHistory, FeeHistoryCacheItem, TxGasAndReward};
use reth_transaction_pool::TransactionPool;
use std::collections::BTreeMap;
@ -14,7 +14,7 @@ use std::collections::BTreeMap;
impl<Client, Pool, Network> EthApi<Client, Pool, Network>
where
Pool: TransactionPool + Clone + 'static,
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + 'static,
Network: NetworkInfo + Send + Sync + 'static,
{
/// Returns a suggestion for a gas price for legacy transactions.

View File

@ -12,7 +12,7 @@ use async_trait::async_trait;
use reth_interfaces::Result;
use reth_network_api::NetworkInfo;
use reth_primitives::{Address, BlockId, BlockNumberOrTag, ChainInfo, H256, U256, U64};
use reth_provider::{BlockProvider, EvmEnvProvider, StateProviderBox, StateProviderFactory};
use reth_provider::{BlockProviderIdExt, EvmEnvProvider, StateProviderBox, StateProviderFactory};
use reth_rpc_types::{FeeHistoryCache, SyncInfo, SyncStatus};
use reth_transaction_pool::TransactionPool;
use std::{num::NonZeroUsize, sync::Arc};
@ -106,7 +106,7 @@ impl<Client, Pool, Network> EthApi<Client, Pool, Network> {
impl<Client, Pool, Network> EthApi<Client, Pool, Network>
where
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + 'static,
{
fn convert_block_number(&self, num: BlockNumberOrTag) -> Result<Option<u64>> {
self.client().convert_block_number(num)
@ -177,7 +177,7 @@ impl<Client, Pool, Events> std::fmt::Debug for EthApi<Client, Pool, Events> {
impl<Client, Pool, Network> EthApiSpec for EthApi<Client, Pool, Network>
where
Pool: TransactionPool + Clone + 'static,
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + 'static,
Network: NetworkInfo + 'static,
{
/// Returns the current ethereum protocol version.

View File

@ -15,7 +15,10 @@ use reth_primitives::{
serde_helper::JsonStorageKey, AccessListWithGasUsed, Address, BlockId, BlockNumberOrTag, Bytes,
H256, H64, U256, U64,
};
use reth_provider::{BlockProvider, EvmEnvProvider, HeaderProvider, StateProviderFactory};
use reth_provider::{
BlockIdProvider, BlockProvider, BlockProviderIdExt, EvmEnvProvider, HeaderProvider,
StateProviderFactory,
};
use reth_rpc_api::EthApiServer;
use reth_rpc_types::{
state::StateOverride, CallRequest, EIP1186AccountProofResponse, FeeHistory, Index, RichBlock,
@ -30,7 +33,13 @@ impl<Client, Pool, Network> EthApiServer for EthApi<Client, Pool, Network>
where
Self: EthApiSpec + EthTransactions,
Pool: TransactionPool + 'static,
Client: BlockProvider + HeaderProvider + StateProviderFactory + EvmEnvProvider + 'static,
Client: BlockProvider
+ BlockIdProvider
+ BlockProviderIdExt
+ HeaderProvider
+ StateProviderFactory
+ EvmEnvProvider
+ 'static,
Network: NetworkInfo + Send + Sync + 'static,
{
/// Handler for: `eth_protocolVersion`

View File

@ -9,14 +9,14 @@ use reth_primitives::{
U256,
};
use reth_provider::{
AccountProvider, BlockProvider, EvmEnvProvider, StateProvider, StateProviderFactory,
AccountProvider, BlockProviderIdExt, EvmEnvProvider, StateProvider, StateProviderFactory,
};
use reth_rpc_types::{EIP1186AccountProofResponse, StorageProof};
use reth_transaction_pool::{PoolTransaction, TransactionPool};
impl<Client, Pool, Network> EthApi<Client, Pool, Network>
where
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + 'static,
Pool: TransactionPool + Clone + 'static,
{
pub(crate) fn get_code(&self, address: Address, block_id: Option<BlockId>) -> EthResult<Bytes> {

View File

@ -16,7 +16,7 @@ use reth_primitives::{
TransactionKind::{Call, Create},
TransactionMeta, TransactionSigned, TransactionSignedEcRecovered, H256, U128, U256, U64,
};
use reth_provider::{BlockProvider, EvmEnvProvider, StateProviderBox, StateProviderFactory};
use reth_provider::{BlockProviderIdExt, EvmEnvProvider, StateProviderBox, StateProviderFactory};
use reth_revm::{
database::{State, SubState},
env::{fill_block_env_with_coinbase, tx_env_with_recovered},
@ -181,7 +181,7 @@ pub trait EthTransactions: Send + Sync {
impl<Client, Pool, Network> EthTransactions for EthApi<Client, Pool, Network>
where
Pool: TransactionPool + Clone + 'static,
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + 'static,
Network: NetworkInfo + Send + Sync + 'static,
{
fn state_at(&self, at: BlockId) -> EthResult<StateProviderBox<'_>> {
@ -534,7 +534,7 @@ where
impl<Client, Pool, Network> EthApi<Client, Pool, Network>
where
Pool: TransactionPool + 'static,
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + 'static,
Network: 'static,
{
pub(crate) fn sign_request(

View File

@ -13,7 +13,7 @@ use reth_primitives::{
filter::{Filter, FilterBlockOption, FilteredParams},
SealedBlock,
};
use reth_provider::{BlockProvider, EvmEnvProvider};
use reth_provider::{BlockIdProvider, BlockProvider, EvmEnvProvider};
use reth_rpc_api::EthFilterApiServer;
use reth_rpc_types::{FilterChanges, FilterId, Log};
use reth_transaction_pool::TransactionPool;
@ -61,7 +61,7 @@ impl<Client, Pool> EthFilter<Client, Pool> {
#[async_trait]
impl<Client, Pool> EthFilterApiServer for EthFilter<Client, Pool>
where
Client: BlockProvider + EvmEnvProvider + 'static,
Client: BlockProvider + BlockIdProvider + EvmEnvProvider + 'static,
Pool: TransactionPool + 'static,
{
/// Handler for `eth_newFilter`
@ -122,7 +122,17 @@ where
FilterKind::Log(filter) => {
let (from_block_number, to_block_number) = match filter.block_option {
FilterBlockOption::Range { from_block, to_block } => {
logs_utils::get_filter_block_range(from_block, to_block, start_block, info)
let from = from_block
.map(|num| self.inner.client.convert_block_number(num))
.transpose()
.to_rpc_result()?
.flatten();
let to = to_block
.map(|num| self.inner.client.convert_block_number(num))
.transpose()
.to_rpc_result()?
.flatten();
logs_utils::get_filter_block_range(from, to, start_block, info)
}
FilterBlockOption::AtBlockHash(_) => {
// blockHash is equivalent to fromBlock = toBlock = the block number with
@ -203,7 +213,7 @@ struct EthFilterInner<Client, Pool> {
impl<Client, Pool> EthFilterInner<Client, Pool>
where
Client: BlockProvider + EvmEnvProvider + 'static,
Client: BlockProvider + BlockIdProvider + EvmEnvProvider + 'static,
Pool: TransactionPool + 'static,
{
/// Returns logs matching given filter object.
@ -235,8 +245,18 @@ where
// we start at the most recent block if unset in filter
let start_block = info.best_number;
let from = from_block
.map(|num| self.client.convert_block_number(num))
.transpose()
.to_rpc_result()?
.flatten();
let to = to_block
.map(|num| self.client.convert_block_number(num))
.transpose()
.to_rpc_result()?
.flatten();
let (from_block_number, to_block_number) =
logs_utils::get_filter_block_range(from_block, to_block, start_block, info);
logs_utils::get_filter_block_range(from, to, start_block, info);
Ok(self
.get_logs_in_block_range(&filter, from_block_number, to_block_number)
.await?)

View File

@ -1,6 +1,4 @@
use reth_primitives::{
filter::FilteredParams, BlockNumHash, BlockNumberOrTag, ChainInfo, Receipt, TxHash, U256,
};
use reth_primitives::{filter::FilteredParams, BlockNumHash, ChainInfo, Receipt, TxHash, U256};
use reth_rpc_types::Log;
/// Returns all matching logs of a block's receipts grouped with the hash of their transaction.
@ -72,8 +70,8 @@ pub(crate) fn log_matches_filter(
/// Computes the block range based on the filter range and current block numbers
pub(crate) fn get_filter_block_range(
from_block: Option<BlockNumberOrTag>,
to_block: Option<BlockNumberOrTag>,
from_block: Option<u64>,
to_block: Option<u64>,
start_block: u64,
info: ChainInfo,
) -> (u64, u64) {
@ -83,13 +81,13 @@ pub(crate) fn get_filter_block_range(
// if a `from_block` argument is provided then the `from_block_number` is the converted value or
// the start block if the converted value is larger than the start block, since `from_block`
// can't be a future block: `min(head, from_block)`
if let Some(filter_from_block) = from_block.and_then(|num| info.convert_block_number(num)) {
if let Some(filter_from_block) = from_block {
from_block_number = start_block.min(filter_from_block)
}
// upper end of the range is the converted `to_block` argument, restricted by the best block:
// `min(best_number,to_block_number)`
if let Some(filter_to_block) = to_block.and_then(|num| info.convert_block_number(num)) {
if let Some(filter_to_block) = to_block {
to_block_number = info.best_number.min(filter_to_block);
}
@ -102,17 +100,17 @@ mod tests {
#[test]
fn test_log_range_from_and_to() {
let from: BlockNumberOrTag = 14000000u64.into();
let to: BlockNumberOrTag = 14000100u64.into();
let from = 14000000u64;
let to = 14000100u64;
let info = ChainInfo { best_number: 15000000, ..Default::default() };
let range = get_filter_block_range(Some(from), Some(to), info.best_number, info);
assert_eq!(range, (from.as_number().unwrap(), to.as_number().unwrap()));
assert_eq!(range, (from, to));
}
#[test]
fn test_log_range_higher() {
let from: BlockNumberOrTag = 15000001u64.into();
let to: BlockNumberOrTag = 15000002u64.into();
let from = 15000001u64;
let to = 15000002u64;
let info = ChainInfo { best_number: 15000000, ..Default::default() };
let range = get_filter_block_range(Some(from), Some(to), info.best_number, info.clone());
assert_eq!(range, (info.best_number, info.best_number));
@ -120,18 +118,18 @@ mod tests {
#[test]
fn test_log_range_from() {
let from: BlockNumberOrTag = 14000000u64.into();
let from = 14000000u64;
let info = ChainInfo { best_number: 15000000, ..Default::default() };
let range = get_filter_block_range(Some(from), None, info.best_number, info.clone());
assert_eq!(range, (from.as_number().unwrap(), info.best_number));
assert_eq!(range, (from, info.best_number));
}
#[test]
fn test_log_range_to() {
let to: BlockNumberOrTag = 14000000u64.into();
let to = 14000000u64;
let info = ChainInfo { best_number: 15000000, ..Default::default() };
let range = get_filter_block_range(None, Some(to), info.best_number, info.clone());
assert_eq!(range, (info.best_number, to.as_number().unwrap()));
assert_eq!(range, (info.best_number, to));
}
#[test]

View File

@ -11,10 +11,11 @@
/// Various provider traits.
mod traits;
pub use traits::{
AccountProvider, BlockExecutor, BlockHashProvider, BlockIdProvider, BlockProvider, BlockSource,
BlockchainTreePendingStateProvider, CanonStateNotification, CanonStateNotificationSender,
CanonStateNotifications, CanonStateSubscriptions, EvmEnvProvider, ExecutorFactory,
HeaderProvider, PostStateDataProvider, ReceiptProvider, StateProvider, StateProviderBox,
AccountProvider, BlockExecutor, BlockHashProvider, BlockIdProvider, BlockNumProvider,
BlockProvider, BlockProviderIdExt, BlockSource, BlockchainTreePendingStateProvider,
CanonStateNotification, CanonStateNotificationSender, CanonStateNotifications,
CanonStateSubscriptions, EvmEnvProvider, ExecutorFactory, HeaderProvider,
PostStateDataProvider, ReceiptProvider, ReceiptProviderIdExt, StateProvider, StateProviderBox,
StateProviderFactory, StateRootProvider, TransactionsProvider, WithdrawalsProvider,
};

View File

@ -1,14 +1,15 @@
use crate::{
providers::state::{historical::HistoricalStateProvider, latest::LatestStateProvider},
traits::{BlockSource, ReceiptProvider},
BlockHashProvider, BlockIdProvider, BlockProvider, EvmEnvProvider, HeaderProvider,
BlockHashProvider, BlockNumProvider, BlockProvider, EvmEnvProvider, HeaderProvider,
ProviderError, StateProviderBox, TransactionsProvider, WithdrawalsProvider,
};
use reth_db::{cursor::DbCursorRO, database::Database, tables, transaction::DbTx};
use reth_interfaces::Result;
use reth_primitives::{
Block, BlockHash, BlockId, BlockNumber, ChainInfo, ChainSpec, Hardfork, Head, Header, Receipt,
SealedBlock, TransactionMeta, TransactionSigned, TxHash, TxNumber, Withdrawal, H256, U256,
Block, BlockHash, BlockHashOrNumber, BlockNumber, ChainInfo, ChainSpec, Hardfork, Head, Header,
Receipt, SealedBlock, TransactionMeta, TransactionSigned, TxHash, TxNumber, Withdrawal, H256,
U256,
};
use reth_revm_primitives::{
config::revm_spec,
@ -149,11 +150,11 @@ impl<DB: Database> BlockHashProvider for ShareableDatabase<DB> {
}
}
impl<DB: Database> BlockIdProvider for ShareableDatabase<DB> {
impl<DB: Database> BlockNumProvider for ShareableDatabase<DB> {
fn chain_info(&self) -> Result<ChainInfo> {
let best_number = self.best_block_number()?;
let best_hash = self.block_hash(best_number)?.unwrap_or_default();
Ok(ChainInfo { best_hash, best_number, last_finalized: None, safe_finalized: None })
Ok(ChainInfo { best_hash, best_number })
}
fn best_block_number(&self) -> Result<BlockNumber> {
@ -174,10 +175,10 @@ impl<DB: Database> BlockProvider for ShareableDatabase<DB> {
}
}
fn block(&self, id: BlockId) -> Result<Option<Block>> {
if let Some(number) = self.block_number_for_id(id)? {
fn block(&self, id: BlockHashOrNumber) -> Result<Option<Block>> {
if let Some(number) = self.convert_hash(id)? {
if let Some(header) = self.header_by_number(number)? {
let id = BlockId::Number(number.into());
let id = BlockHashOrNumber::Number(number);
let tx = self.db.tx()?;
let transactions = self
.transactions_by_block(id)?
@ -202,8 +203,8 @@ impl<DB: Database> BlockProvider for ShareableDatabase<DB> {
Ok(None)
}
fn ommers(&self, id: BlockId) -> Result<Option<Vec<Header>>> {
if let Some(number) = self.block_number_for_id(id)? {
fn ommers(&self, id: BlockHashOrNumber) -> Result<Option<Vec<Header>>> {
if let Some(number) = self.convert_hash(id)? {
let tx = self.db.tx()?;
// TODO: this can be optimized to return empty Vec post-merge
let ommers = tx.get::<tables::BlockOmmers>(number)?.map(|o| o.ommers);
@ -293,8 +294,11 @@ impl<DB: Database> TransactionsProvider for ShareableDatabase<DB> {
.map_err(Into::into)
}
fn transactions_by_block(&self, id: BlockId) -> Result<Option<Vec<TransactionSigned>>> {
if let Some(number) = self.block_number_for_id(id)? {
fn transactions_by_block(
&self,
id: BlockHashOrNumber,
) -> Result<Option<Vec<TransactionSigned>>> {
if let Some(number) = self.convert_hash(id)? {
let tx = self.db.tx()?;
if let Some(body) = tx.get::<tables::BlockBodyIndices>(number)? {
let tx_range = body.tx_num_range();
@ -356,8 +360,8 @@ impl<DB: Database> ReceiptProvider for ShareableDatabase<DB> {
.map_err(Into::into)
}
fn receipts_by_block(&self, block: BlockId) -> Result<Option<Vec<Receipt>>> {
if let Some(number) = self.block_number_for_id(block)? {
fn receipts_by_block(&self, block: BlockHashOrNumber) -> Result<Option<Vec<Receipt>>> {
if let Some(number) = self.convert_hash(block)? {
let tx = self.db.tx()?;
if let Some(body) = tx.get::<tables::BlockBodyIndices>(number)? {
let tx_range = body.tx_num_range();
@ -378,9 +382,13 @@ impl<DB: Database> ReceiptProvider for ShareableDatabase<DB> {
}
impl<DB: Database> WithdrawalsProvider for ShareableDatabase<DB> {
fn withdrawals_by_block(&self, id: BlockId, timestamp: u64) -> Result<Option<Vec<Withdrawal>>> {
fn withdrawals_by_block(
&self,
id: BlockHashOrNumber,
timestamp: u64,
) -> Result<Option<Vec<Withdrawal>>> {
if self.chain_spec.fork(Hardfork::Shanghai).active_at_timestamp(timestamp) {
if let Some(number) = self.block_number_for_id(id)? {
if let Some(number) = self.convert_hash(id)? {
// If we are past shanghai, then all blocks should have a withdrawal list, even if
// empty
return Ok(Some(
@ -407,8 +415,13 @@ impl<DB: Database> WithdrawalsProvider for ShareableDatabase<DB> {
}
impl<DB: Database> EvmEnvProvider for ShareableDatabase<DB> {
fn fill_env_at(&self, cfg: &mut CfgEnv, block_env: &mut BlockEnv, at: BlockId) -> Result<()> {
let hash = self.block_hash_for_id(at)?.ok_or(ProviderError::HeaderNotFound)?;
fn fill_env_at(
&self,
cfg: &mut CfgEnv,
block_env: &mut BlockEnv,
at: BlockHashOrNumber,
) -> Result<()> {
let hash = self.convert_number(at)?.ok_or(ProviderError::HeaderNotFound)?;
let header = self.header(&hash)?.ok_or(ProviderError::HeaderNotFound)?;
self.fill_env_with_header(cfg, block_env, &header)
}
@ -425,8 +438,8 @@ impl<DB: Database> EvmEnvProvider for ShareableDatabase<DB> {
Ok(())
}
fn fill_block_env_at(&self, block_env: &mut BlockEnv, at: BlockId) -> Result<()> {
let hash = self.block_hash_for_id(at)?.ok_or(ProviderError::HeaderNotFound)?;
fn fill_block_env_at(&self, block_env: &mut BlockEnv, at: BlockHashOrNumber) -> Result<()> {
let hash = self.convert_number(at)?.ok_or(ProviderError::HeaderNotFound)?;
let header = self.header(&hash)?.ok_or(ProviderError::HeaderNotFound)?;
self.fill_block_env_with_header(block_env, &header)
@ -451,8 +464,8 @@ impl<DB: Database> EvmEnvProvider for ShareableDatabase<DB> {
Ok(())
}
fn fill_cfg_env_at(&self, cfg: &mut CfgEnv, at: BlockId) -> Result<()> {
let hash = self.block_hash_for_id(at)?.ok_or(ProviderError::HeaderNotFound)?;
fn fill_cfg_env_at(&self, cfg: &mut CfgEnv, at: BlockHashOrNumber) -> Result<()> {
let hash = self.convert_number(at)?.ok_or(ProviderError::HeaderNotFound)?;
let header = self.header(&hash)?.ok_or(ProviderError::HeaderNotFound)?;
self.fill_cfg_env_with_header(cfg, &header)
}
@ -525,7 +538,7 @@ where
#[cfg(test)]
mod tests {
use super::ShareableDatabase;
use crate::BlockIdProvider;
use crate::BlockNumProvider;
use reth_db::mdbx::{test_utils::create_test_db, EnvKind, WriteMap};
use reth_primitives::{ChainSpecBuilder, H256};
use std::sync::Arc;
@ -547,7 +560,5 @@ mod tests {
let chain_info = provider.chain_info().expect("should be ok");
assert_eq!(chain_info.best_number, 0);
assert_eq!(chain_info.best_hash, H256::zero());
assert_eq!(chain_info.last_finalized, None);
assert_eq!(chain_info.safe_finalized, None);
}
}

View File

@ -1,8 +1,8 @@
use crate::{
BlockHashProvider, BlockIdProvider, BlockProvider, BlockchainTreePendingStateProvider,
CanonStateNotifications, CanonStateSubscriptions, EvmEnvProvider, HeaderProvider,
PostStateDataProvider, ReceiptProvider, StateProviderBox, StateProviderFactory,
TransactionsProvider, WithdrawalsProvider,
BlockHashProvider, BlockIdProvider, BlockNumProvider, BlockProvider, BlockProviderIdExt,
BlockchainTreePendingStateProvider, CanonStateNotifications, CanonStateSubscriptions,
EvmEnvProvider, HeaderProvider, PostStateDataProvider, ReceiptProvider, StateProviderBox,
StateProviderFactory, TransactionsProvider, WithdrawalsProvider,
};
use reth_db::database::Database;
use reth_interfaces::{
@ -10,7 +10,7 @@ use reth_interfaces::{
Result,
};
use reth_primitives::{
Block, BlockHash, BlockId, BlockNumHash, BlockNumber, BlockNumberOrTag, ChainInfo, Header,
Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumber, ChainInfo, Header,
Receipt, SealedBlock, SealedBlockWithSenders, TransactionMeta, TransactionSigned, TxHash,
TxNumber, Withdrawal, H256, U256,
};
@ -92,7 +92,7 @@ where
}
}
impl<DB, Tree> BlockIdProvider for BlockchainProvider<DB, Tree>
impl<DB, Tree> BlockNumProvider for BlockchainProvider<DB, Tree>
where
DB: Database,
Tree: BlockchainTreeViewer + Send + Sync,
@ -105,40 +105,29 @@ where
self.database.best_block_number()
}
fn convert_block_number(&self, num: BlockNumberOrTag) -> Result<Option<BlockNumber>> {
let num = match num {
BlockNumberOrTag::Latest => self.chain_info()?.best_number,
BlockNumberOrTag::Number(num) => num,
BlockNumberOrTag::Pending => {
return Ok(self.tree.pending_block_num_hash().map(|b| b.number))
}
BlockNumberOrTag::Finalized => return Ok(self.chain_info()?.last_finalized),
BlockNumberOrTag::Safe => return Ok(self.chain_info()?.safe_finalized),
BlockNumberOrTag::Earliest => 0,
};
Ok(Some(num))
}
fn block_hash_for_id(&self, block_id: BlockId) -> Result<Option<H256>> {
match block_id {
BlockId::Hash(hash) => Ok(Some(hash.into())),
BlockId::Number(num) => match num {
BlockNumberOrTag::Latest => Ok(Some(self.chain_info()?.best_hash)),
BlockNumberOrTag::Pending => Ok(self.tree.pending_block_num_hash().map(|b| b.hash)),
_ => self
.convert_block_number(num)?
.map(|num| self.block_hash(num))
.transpose()
.map(|maybe_hash| maybe_hash.flatten()),
},
}
}
fn block_number(&self, hash: H256) -> Result<Option<BlockNumber>> {
self.database.block_number(hash)
}
}
impl<DB, Tree> BlockIdProvider for BlockchainProvider<DB, Tree>
where
DB: Database,
Tree: BlockchainTreeViewer + Send + Sync,
{
fn safe_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
todo!()
}
fn finalized_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
todo!()
}
fn pending_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>> {
Ok(self.tree.pending_block_num_hash())
}
}
impl<DB, Tree> BlockProvider for BlockchainProvider<DB, Tree>
where
DB: Database,
@ -163,18 +152,18 @@ where
Ok(block)
}
fn block(&self, id: BlockId) -> Result<Option<Block>> {
if id.is_pending() {
return Ok(self.tree.pending_block().map(SealedBlock::unseal))
fn block(&self, id: BlockHashOrNumber) -> Result<Option<Block>> {
match id {
BlockHashOrNumber::Hash(hash) => self.find_block_by_hash(hash, BlockSource::Any),
BlockHashOrNumber::Number(num) => self.database.block_by_number(num),
}
self.database.block(id)
}
fn pending_block(&self) -> Result<Option<SealedBlock>> {
Ok(self.tree.pending_block())
}
fn ommers(&self, id: BlockId) -> Result<Option<Vec<Header>>> {
fn ommers(&self, id: BlockHashOrNumber) -> Result<Option<Vec<Header>>> {
self.database.ommers(id)
}
}
@ -207,7 +196,10 @@ where
self.database.transaction_block(id)
}
fn transactions_by_block(&self, id: BlockId) -> Result<Option<Vec<TransactionSigned>>> {
fn transactions_by_block(
&self,
id: BlockHashOrNumber,
) -> Result<Option<Vec<TransactionSigned>>> {
self.database.transactions_by_block(id)
}
@ -232,7 +224,7 @@ where
self.database.receipt_by_hash(hash)
}
fn receipts_by_block(&self, block: BlockId) -> Result<Option<Vec<Receipt>>> {
fn receipts_by_block(&self, block: BlockHashOrNumber) -> Result<Option<Vec<Receipt>>> {
self.database.receipts_by_block(block)
}
}
@ -242,7 +234,11 @@ where
DB: Database,
Tree: Send + Sync,
{
fn withdrawals_by_block(&self, id: BlockId, timestamp: u64) -> Result<Option<Vec<Withdrawal>>> {
fn withdrawals_by_block(
&self,
id: BlockHashOrNumber,
timestamp: u64,
) -> Result<Option<Vec<Withdrawal>>> {
self.database.withdrawals_by_block(id, timestamp)
}
@ -256,7 +252,12 @@ where
DB: Database,
Tree: Send + Sync,
{
fn fill_env_at(&self, cfg: &mut CfgEnv, block_env: &mut BlockEnv, at: BlockId) -> Result<()> {
fn fill_env_at(
&self,
cfg: &mut CfgEnv,
block_env: &mut BlockEnv,
at: BlockHashOrNumber,
) -> Result<()> {
self.database.fill_env_at(cfg, block_env, at)
}
@ -269,7 +270,7 @@ where
self.database.fill_env_with_header(cfg, block_env, header)
}
fn fill_block_env_at(&self, block_env: &mut BlockEnv, at: BlockId) -> Result<()> {
fn fill_block_env_at(&self, block_env: &mut BlockEnv, at: BlockHashOrNumber) -> Result<()> {
self.database.fill_block_env_at(block_env, at)
}
@ -277,7 +278,7 @@ where
self.database.fill_block_env_with_header(block_env, header)
}
fn fill_cfg_env_at(&self, cfg: &mut CfgEnv, at: BlockId) -> Result<()> {
fn fill_cfg_env_at(&self, cfg: &mut CfgEnv, at: BlockHashOrNumber) -> Result<()> {
self.database.fill_cfg_env_at(cfg, at)
}
@ -407,6 +408,41 @@ where
}
}
impl<DB, Tree> BlockProviderIdExt for BlockchainProvider<DB, Tree>
where
Self: BlockProvider + BlockIdProvider,
Tree: BlockchainTreeEngine,
{
fn block_by_id(&self, id: BlockId) -> Result<Option<Block>> {
match id {
BlockId::Number(num) => self.block_by_number_or_tag(num),
BlockId::Hash(hash) => {
// TODO: should we only apply this for the RPCs that are listed in EIP-1898?
// so not at the provider level?
// if we decide to do this at a higher level, then we can make this an automatic
// trait impl
if Some(true) == hash.require_canonical {
// check the database, canonical blocks are only stored in the database
self.find_block_by_hash(hash.block_hash, BlockSource::Database)
} else {
self.block_by_hash(hash.block_hash)
}
}
}
}
fn ommers_by_id(&self, id: BlockId) -> Result<Option<Vec<Header>>> {
match id {
BlockId::Number(num) => self.ommers_by_number_or_tag(num),
BlockId::Hash(hash) => {
// TODO: EIP-1898 question, see above
// here it is not handled
self.ommers(BlockHashOrNumber::Hash(hash.block_hash))
}
}
}
}
impl<DB, Tree> BlockchainTreePendingStateProvider for BlockchainProvider<DB, Tree>
where
DB: Send + Sync,

View File

@ -1,13 +1,13 @@
use crate::{
traits::{BlockSource, ReceiptProvider},
AccountProvider, BlockHashProvider, BlockIdProvider, BlockProvider, EvmEnvProvider,
HeaderProvider, PostState, PostStateDataProvider, StateProvider, StateProviderBox,
StateProviderFactory, StateRootProvider, TransactionsProvider,
AccountProvider, BlockHashProvider, BlockIdProvider, BlockNumProvider, BlockProvider,
BlockProviderIdExt, EvmEnvProvider, HeaderProvider, PostState, PostStateDataProvider,
StateProvider, StateProviderBox, StateProviderFactory, StateRootProvider, TransactionsProvider,
};
use parking_lot::Mutex;
use reth_interfaces::Result;
use reth_primitives::{
keccak256, Account, Address, Block, BlockHash, BlockId, BlockNumber, BlockNumberOrTag,
keccak256, Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber,
Bytecode, Bytes, ChainInfo, Header, Receipt, SealedBlock, StorageKey, StorageValue,
TransactionMeta, TransactionSigned, TxHash, TxNumber, H256, U256,
};
@ -177,7 +177,10 @@ impl TransactionsProvider for MockEthProvider {
unimplemented!()
}
fn transactions_by_block(&self, id: BlockId) -> Result<Option<Vec<TransactionSigned>>> {
fn transactions_by_block(
&self,
id: BlockHashOrNumber,
) -> Result<Option<Vec<TransactionSigned>>> {
Ok(self.block(id)?.map(|b| b.body))
}
@ -206,7 +209,7 @@ impl ReceiptProvider for MockEthProvider {
Ok(None)
}
fn receipts_by_block(&self, _block: BlockId) -> Result<Option<Vec<Receipt>>> {
fn receipts_by_block(&self, _block: BlockHashOrNumber) -> Result<Option<Vec<Receipt>>> {
Ok(None)
}
}
@ -231,7 +234,7 @@ impl BlockHashProvider for MockEthProvider {
}
}
impl BlockIdProvider for MockEthProvider {
impl BlockNumProvider for MockEthProvider {
fn chain_info(&self) -> Result<ChainInfo> {
let best_block_number = self.best_block_number()?;
let lock = self.headers.lock();
@ -239,12 +242,7 @@ impl BlockIdProvider for MockEthProvider {
Ok(lock
.iter()
.find(|(_, header)| header.number == best_block_number)
.map(|(hash, header)| ChainInfo {
best_hash: *hash,
best_number: header.number,
last_finalized: None,
safe_finalized: None,
})
.map(|(hash, header)| ChainInfo { best_hash: *hash, best_number: header.number })
.expect("provider is empty"))
}
@ -264,21 +262,30 @@ impl BlockIdProvider for MockEthProvider {
}
}
impl BlockIdProvider for MockEthProvider {
fn safe_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
Ok(None)
}
fn pending_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>> {
Ok(None)
}
fn finalized_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
Ok(None)
}
}
impl BlockProvider for MockEthProvider {
fn find_block_by_hash(&self, hash: H256, _source: BlockSource) -> Result<Option<Block>> {
self.block(hash.into())
}
fn block(&self, id: BlockId) -> Result<Option<Block>> {
fn block(&self, id: BlockHashOrNumber) -> Result<Option<Block>> {
let lock = self.blocks.lock();
match id {
BlockId::Hash(hash) => Ok(lock.get(hash.as_ref()).cloned()),
BlockId::Number(BlockNumberOrTag::Number(num)) => {
Ok(lock.values().find(|b| b.number == num).cloned())
}
_ => {
unreachable!("unused in network tests")
}
BlockHashOrNumber::Hash(hash) => Ok(lock.get(&hash).cloned()),
BlockHashOrNumber::Number(num) => Ok(lock.values().find(|b| b.number == num).cloned()),
}
}
@ -286,11 +293,27 @@ impl BlockProvider for MockEthProvider {
Ok(None)
}
fn ommers(&self, _id: BlockId) -> Result<Option<Vec<Header>>> {
fn ommers(&self, _id: BlockHashOrNumber) -> Result<Option<Vec<Header>>> {
Ok(None)
}
}
impl BlockProviderIdExt for MockEthProvider {
fn block_by_id(&self, id: BlockId) -> Result<Option<Block>> {
match id {
BlockId::Number(num) => self.block_by_number_or_tag(num),
BlockId::Hash(hash) => self.block_by_hash(hash.block_hash),
}
}
fn ommers_by_id(&self, id: BlockId) -> Result<Option<Vec<Header>>> {
match id {
BlockId::Number(num) => self.ommers_by_number_or_tag(num),
BlockId::Hash(hash) => self.ommers(BlockHashOrNumber::Hash(hash.block_hash)),
}
}
}
impl AccountProvider for MockEthProvider {
fn basic_account(&self, address: Address) -> Result<Option<Account>> {
Ok(self.accounts.lock().get(&address).cloned().map(|a| a.account))
@ -335,7 +358,7 @@ impl EvmEnvProvider for MockEthProvider {
&self,
_cfg: &mut CfgEnv,
_block_env: &mut BlockEnv,
_at: BlockId,
_at: BlockHashOrNumber,
) -> Result<()> {
unimplemented!()
}
@ -349,7 +372,7 @@ impl EvmEnvProvider for MockEthProvider {
unimplemented!()
}
fn fill_block_env_at(&self, _block_env: &mut BlockEnv, _at: BlockId) -> Result<()> {
fn fill_block_env_at(&self, _block_env: &mut BlockEnv, _at: BlockHashOrNumber) -> Result<()> {
unimplemented!()
}
@ -361,7 +384,7 @@ impl EvmEnvProvider for MockEthProvider {
unimplemented!()
}
fn fill_cfg_env_at(&self, _cfg: &mut CfgEnv, _at: BlockId) -> Result<()> {
fn fill_cfg_env_at(&self, _cfg: &mut CfgEnv, _at: BlockHashOrNumber) -> Result<()> {
unimplemented!()
}

View File

@ -1,14 +1,14 @@
use crate::{
traits::{BlockSource, ReceiptProvider},
AccountProvider, BlockHashProvider, BlockIdProvider, BlockProvider, EvmEnvProvider,
HeaderProvider, PostState, StateProvider, StateProviderBox, StateProviderFactory,
StateRootProvider, TransactionsProvider,
AccountProvider, BlockHashProvider, BlockIdProvider, BlockNumProvider, BlockProvider,
BlockProviderIdExt, EvmEnvProvider, HeaderProvider, PostState, StateProvider, StateProviderBox,
StateProviderFactory, StateRootProvider, TransactionsProvider,
};
use reth_interfaces::Result;
use reth_primitives::{
Account, Address, Block, BlockHash, BlockId, BlockNumber, Bytecode, Bytes, ChainInfo, Header,
Receipt, SealedBlock, StorageKey, StorageValue, TransactionMeta, TransactionSigned, TxHash,
TxNumber, H256, KECCAK_EMPTY, U256,
Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber, Bytecode, Bytes,
ChainInfo, Header, Receipt, SealedBlock, StorageKey, StorageValue, TransactionMeta,
TransactionSigned, TxHash, TxNumber, H256, KECCAK_EMPTY, U256,
};
use reth_revm_primitives::primitives::{BlockEnv, CfgEnv};
use std::ops::RangeBounds;
@ -29,7 +29,7 @@ impl BlockHashProvider for NoopProvider {
}
}
impl BlockIdProvider for NoopProvider {
impl BlockNumProvider for NoopProvider {
fn chain_info(&self) -> Result<ChainInfo> {
Ok(ChainInfo::default())
}
@ -48,7 +48,7 @@ impl BlockProvider for NoopProvider {
self.block(hash.into())
}
fn block(&self, _id: BlockId) -> Result<Option<Block>> {
fn block(&self, _id: BlockHashOrNumber) -> Result<Option<Block>> {
Ok(None)
}
@ -56,7 +56,31 @@ impl BlockProvider for NoopProvider {
Ok(None)
}
fn ommers(&self, _id: BlockId) -> Result<Option<Vec<Header>>> {
fn ommers(&self, _id: BlockHashOrNumber) -> Result<Option<Vec<Header>>> {
Ok(None)
}
}
impl BlockProviderIdExt for NoopProvider {
fn block_by_id(&self, _id: BlockId) -> Result<Option<Block>> {
Ok(None)
}
fn ommers_by_id(&self, _id: BlockId) -> Result<Option<Vec<Header>>> {
Ok(None)
}
}
impl BlockIdProvider for NoopProvider {
fn pending_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>> {
Ok(None)
}
fn safe_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
Ok(None)
}
fn finalized_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>> {
Ok(None)
}
}
@ -85,7 +109,10 @@ impl TransactionsProvider for NoopProvider {
todo!()
}
fn transactions_by_block(&self, _block_id: BlockId) -> Result<Option<Vec<TransactionSigned>>> {
fn transactions_by_block(
&self,
_block_id: BlockHashOrNumber,
) -> Result<Option<Vec<TransactionSigned>>> {
Ok(None)
}
@ -106,7 +133,7 @@ impl ReceiptProvider for NoopProvider {
Ok(None)
}
fn receipts_by_block(&self, _block: BlockId) -> Result<Option<Vec<Receipt>>> {
fn receipts_by_block(&self, _block: BlockHashOrNumber) -> Result<Option<Vec<Receipt>>> {
Ok(None)
}
}
@ -168,7 +195,7 @@ impl EvmEnvProvider for NoopProvider {
&self,
_cfg: &mut CfgEnv,
_block_env: &mut BlockEnv,
_at: BlockId,
_at: BlockHashOrNumber,
) -> Result<()> {
Ok(())
}
@ -182,7 +209,7 @@ impl EvmEnvProvider for NoopProvider {
Ok(())
}
fn fill_block_env_at(&self, _block_env: &mut BlockEnv, _at: BlockId) -> Result<()> {
fn fill_block_env_at(&self, _block_env: &mut BlockEnv, _at: BlockHashOrNumber) -> Result<()> {
Ok(())
}
@ -194,7 +221,7 @@ impl EvmEnvProvider for NoopProvider {
Ok(())
}
fn fill_cfg_env_at(&self, _cfg: &mut CfgEnv, _at: BlockId) -> Result<()> {
fn fill_cfg_env_at(&self, _cfg: &mut CfgEnv, _at: BlockHashOrNumber) -> Result<()> {
Ok(())
}

View File

@ -1,6 +1,10 @@
use crate::{BlockIdProvider, HeaderProvider, ReceiptProvider, TransactionsProvider};
use crate::{
BlockIdProvider, BlockNumProvider, HeaderProvider, ReceiptProvider, TransactionsProvider,
};
use reth_interfaces::Result;
use reth_primitives::{Block, BlockId, BlockNumberOrTag, Header, SealedBlock, H256};
use reth_primitives::{
Block, BlockHashOrNumber, BlockId, BlockNumberOrTag, Header, SealedBlock, H256,
};
/// A helper enum that represents the origin of the requested block.
///
@ -39,7 +43,7 @@ impl BlockSource {
/// the database.
#[auto_impl::auto_impl(&, Arc)]
pub trait BlockProvider:
BlockIdProvider + HeaderProvider + TransactionsProvider + ReceiptProvider + Send + Sync
BlockNumProvider + HeaderProvider + TransactionsProvider + ReceiptProvider + Send + Sync
{
/// Tries to find in the given block source.
///
@ -51,7 +55,7 @@ pub trait BlockProvider:
/// Returns the block with given id from the database.
///
/// Returns `None` if block is not found.
fn block(&self, id: BlockId) -> Result<Option<Block>>;
fn block(&self, id: BlockHashOrNumber) -> Result<Option<Block>>;
/// Returns the pending block if available
///
@ -62,7 +66,7 @@ pub trait BlockProvider:
/// Returns the ommers/uncle headers of the given block from the database.
///
/// Returns `None` if block is not found.
fn ommers(&self, id: BlockId) -> Result<Option<Vec<Header>>>;
fn ommers(&self, id: BlockHashOrNumber) -> Result<Option<Vec<Header>>>;
/// Returns the block with matching hash from the database.
///
@ -71,13 +75,6 @@ pub trait BlockProvider:
self.block(hash.into())
}
/// Returns the block with matching tag from the database
///
/// Returns `None` if block is not found.
fn block_by_number_or_tag(&self, num: BlockNumberOrTag) -> Result<Option<Block>> {
self.block(num.into())
}
/// Returns the block with matching number from database.
///
/// Returns `None` if block is not found.
@ -85,3 +82,38 @@ pub trait BlockProvider:
self.block(num.into())
}
}
/// Trait extension for `BlockProvider`, for types that implement `BlockId` conversion.
///
/// The `BlockProvider` trait should be implemented on types that can retrieve a block from either
/// a block number or hash. However, it might be desirable to fetch a block from a `BlockId` type,
/// which can be a number, hash, or tag such as `BlockNumberOrTag::Safe`.
///
/// Resolving tags requires keeping track of block hashes or block numbers associated with the tag,
/// so this trait can only be implemented for types that implement `BlockIdProvider`. The
/// `BlockIdProvider` methods should be used to resolve `BlockId`s to block numbers or hashes, and
/// retrieving the block should be done using the type's `BlockProvider` methods.
#[auto_impl::auto_impl(&, Arc)]
pub trait BlockProviderIdExt: BlockProvider + BlockIdProvider {
/// Returns the block with matching tag from the database
///
/// Returns `None` if block is not found.
fn block_by_number_or_tag(&self, id: BlockNumberOrTag) -> Result<Option<Block>> {
self.convert_block_number(id)?.map_or_else(|| Ok(None), |num| self.block(num.into()))
}
/// Returns the block with the matching `BlockId` from the database.
///
/// Returns `None` if block is not found.
fn block_by_id(&self, id: BlockId) -> Result<Option<Block>>;
/// Returns the ommers with the matching tag from the database.
fn ommers_by_number_or_tag(&self, id: BlockNumberOrTag) -> Result<Option<Vec<Header>>> {
self.convert_block_number(id)?.map_or_else(|| Ok(None), |num| self.ommers(num.into()))
}
/// Returns the ommers with the matching `BlockId` from the database.
///
/// Returns `None` if block is not found.
fn ommers_by_id(&self, id: BlockId) -> Result<Option<Vec<Header>>>;
}

View File

@ -1,17 +1,53 @@
use super::BlockHashProvider;
use reth_interfaces::Result;
use reth_primitives::{BlockId, BlockNumber, BlockNumberOrTag, ChainInfo, H256};
use reth_primitives::{BlockHashOrNumber, BlockId, BlockNumber, BlockNumberOrTag, ChainInfo, H256};
/// Client trait for transforming [BlockId].
/// Client trait for getting important block numbers (such as the latest block number), converting
/// block hashes to numbers, and fetching a block hash from its block number.
///
/// This trait also supports fetching block hashes and block numbers from a [BlockHashOrNumber].
#[auto_impl::auto_impl(&, Arc)]
pub trait BlockIdProvider: BlockHashProvider + Send + Sync {
pub trait BlockNumProvider: BlockHashProvider + Send + Sync {
/// Returns the current info for the chain.
fn chain_info(&self) -> Result<ChainInfo>;
/// Returns the best block number in the chain.
fn best_block_number(&self) -> Result<BlockNumber>;
/// Converts the `BlockNumberOrTag` variants.
/// Gets the `BlockNumber` for the given hash. Returns `None` if no block with this hash exists.
fn block_number(&self, hash: H256) -> Result<Option<reth_primitives::BlockNumber>>;
/// Gets the block number for the given `BlockHashOrNumber`. Returns `None` if no block with
/// this hash exists. If the `BlockHashOrNumber` is a `Number`, it is returned as is.
fn convert_hash(&self, id: BlockHashOrNumber) -> Result<Option<reth_primitives::BlockNumber>> {
match id {
BlockHashOrNumber::Hash(hash) => self.block_number(hash),
BlockHashOrNumber::Number(num) => Ok(Some(num)),
}
}
/// Gets the block hash for the given `BlockHashOrNumber`. Returns `None` if no block with this
/// number exists. If the `BlockHashOrNumber` is a `Hash`, it is returned as is.
fn convert_number(&self, id: BlockHashOrNumber) -> Result<Option<H256>> {
match id {
BlockHashOrNumber::Hash(hash) => Ok(Some(hash)),
BlockHashOrNumber::Number(num) => self.block_hash(num),
}
}
}
/// Client trait for transforming [BlockId] into block numbers or hashes.
///
/// Types that implement this trait must be able to resolve all variants of [BlockNumberOrTag] to
/// block numbers or hashes. Automatic implementations for resolving [BlockNumberOrTag] variants
/// are provided if the type implements the `pending_block_num_hash`, `finalized_block_num`, and
/// `safe_block_num` methods.
///
/// The resulting block numbers can be converted to hashes using the underlying [BlockNumProvider]
/// methods, and vice versa.
#[auto_impl::auto_impl(&, Arc)]
pub trait BlockIdProvider: BlockNumProvider + Send + Sync {
/// Converts the `BlockNumberOrTag` variants to a block number.
fn convert_block_number(
&self,
num: BlockNumberOrTag,
@ -19,10 +55,14 @@ pub trait BlockIdProvider: BlockHashProvider + Send + Sync {
let num = match num {
BlockNumberOrTag::Latest => self.chain_info()?.best_number,
BlockNumberOrTag::Earliest => 0,
BlockNumberOrTag::Pending => return Ok(None),
BlockNumberOrTag::Pending => {
return self
.pending_block_num_hash()
.map(|res_opt| res_opt.map(|num_hash| num_hash.number))
}
BlockNumberOrTag::Number(num) => num,
BlockNumberOrTag::Finalized => return Ok(self.chain_info()?.last_finalized),
BlockNumberOrTag::Safe => return Ok(self.chain_info()?.safe_finalized),
BlockNumberOrTag::Finalized => return self.finalized_block_num(),
BlockNumberOrTag::Safe => return self.safe_block_num(),
};
Ok(Some(num))
}
@ -35,6 +75,13 @@ pub trait BlockIdProvider: BlockHashProvider + Send + Sync {
if matches!(num, BlockNumberOrTag::Latest) {
return Ok(Some(self.chain_info()?.best_hash))
}
if matches!(num, BlockNumberOrTag::Pending) {
return self
.pending_block_num_hash()
.map(|res_opt| res_opt.map(|num_hash| num_hash.hash))
}
self.convert_block_number(num)?
.map(|num| self.block_hash(num))
.transpose()
@ -54,6 +101,12 @@ pub trait BlockIdProvider: BlockHashProvider + Send + Sync {
}
}
/// Gets the `Block` for the given hash. Returns `None` if no block with this hash exists.
fn block_number(&self, hash: H256) -> Result<Option<reth_primitives::BlockNumber>>;
/// Get the current pending block number and hash.
fn pending_block_num_hash(&self) -> Result<Option<reth_primitives::BlockNumHash>>;
/// Get the safe block number.
fn safe_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>>;
/// Get the finalized block number.
fn finalized_block_num(&self) -> Result<Option<reth_primitives::BlockNumber>>;
}

View File

@ -1,5 +1,5 @@
use reth_interfaces::Result;
use reth_primitives::{BlockId, Header};
use reth_primitives::{BlockHashOrNumber, Header};
use reth_revm_primitives::primitives::{BlockEnv, CfgEnv};
/// A provider type that knows chain specific information required to configure an
@ -8,8 +8,14 @@ use reth_revm_primitives::primitives::{BlockEnv, CfgEnv};
/// This type is mainly used to provide required data to configure the EVM environment.
#[auto_impl::auto_impl(&, Arc)]
pub trait EvmEnvProvider: Send + Sync {
/// Fills the [CfgEnv] and [BlockEnv] fields with values specific to the given [BlockId].
fn fill_env_at(&self, cfg: &mut CfgEnv, block_env: &mut BlockEnv, at: BlockId) -> Result<()>;
/// Fills the [CfgEnv] and [BlockEnv] fields with values specific to the given
/// [BlockHashOrNumber].
fn fill_env_at(
&self,
cfg: &mut CfgEnv,
block_env: &mut BlockEnv,
at: BlockHashOrNumber,
) -> Result<()>;
/// Fills the default [CfgEnv] and [BlockEnv] fields with values specific to the given [Header].
fn env_with_header(&self, header: &Header) -> Result<(CfgEnv, BlockEnv)> {
@ -27,14 +33,14 @@ pub trait EvmEnvProvider: Send + Sync {
header: &Header,
) -> Result<()>;
/// Fills the [BlockEnv] fields with values specific to the given [BlockId].
fn fill_block_env_at(&self, block_env: &mut BlockEnv, at: BlockId) -> Result<()>;
/// Fills the [BlockEnv] fields with values specific to the given [BlockHashOrNumber].
fn fill_block_env_at(&self, block_env: &mut BlockEnv, at: BlockHashOrNumber) -> Result<()>;
/// Fills the [BlockEnv] fields with values specific to the given [Header].
fn fill_block_env_with_header(&self, block_env: &mut BlockEnv, header: &Header) -> Result<()>;
/// Fills the [CfgEnv] fields with values specific to the given [BlockId].
fn fill_cfg_env_at(&self, cfg: &mut CfgEnv, at: BlockId) -> Result<()>;
/// Fills the [CfgEnv] fields with values specific to the given [BlockHashOrNumber].
fn fill_cfg_env_at(&self, cfg: &mut CfgEnv, at: BlockHashOrNumber) -> Result<()>;
/// Fills the [CfgEnv] fields with values specific to the given [Header].
fn fill_cfg_env_with_header(&self, cfg: &mut CfgEnv, header: &Header) -> Result<()>;

View File

@ -4,13 +4,13 @@ mod account;
pub use account::AccountProvider;
mod block;
pub use block::{BlockProvider, BlockSource};
pub use block::{BlockProvider, BlockProviderIdExt, BlockSource};
mod block_hash;
pub use block_hash::BlockHashProvider;
mod block_id;
pub use block_id::BlockIdProvider;
pub use block_id::{BlockIdProvider, BlockNumProvider};
mod evm_env;
pub use evm_env::EvmEnvProvider;
@ -19,7 +19,7 @@ mod header;
pub use header::HeaderProvider;
mod receipts;
pub use receipts::ReceiptProvider;
pub use receipts::{ReceiptProvider, ReceiptProviderIdExt};
mod state;
pub use state::{

View File

@ -1,5 +1,7 @@
use reth_interfaces::Result;
use reth_primitives::{BlockId, Receipt, TxHash, TxNumber};
use reth_primitives::{BlockHashOrNumber, BlockId, Receipt, TxHash, TxNumber};
use crate::BlockIdProvider;
/// Client trait for fetching [Receipt] data .
#[auto_impl::auto_impl(&, Arc)]
@ -10,6 +12,37 @@ pub trait ReceiptProvider: Send + Sync {
/// Get receipt by transaction hash.
fn receipt_by_hash(&self, hash: TxHash) -> Result<Option<Receipt>>;
/// Get receipts by block id.
fn receipts_by_block(&self, block: BlockId) -> Result<Option<Vec<Receipt>>>;
/// Get receipts by block num or hash.
fn receipts_by_block(&self, block: BlockHashOrNumber) -> Result<Option<Vec<Receipt>>>;
}
/// Trait extension for `ReceiptProvider`, for types that implement `BlockId` conversion.
///
/// The `Receipt` trait should be implemented on types that can retrieve receipts from either
/// a block number or hash. However, it might be desirable to fetch receipts from a `BlockId` type,
/// which can be a number, hash, or tag such as `BlockNumberOrTag::Safe`.
///
/// Resolving tags requires keeping track of block hashes or block numbers associated with the tag,
/// so this trait can only be implemented for types that implement `BlockIdProvider`. The
/// `BlockIdProvider` methods should be used to resolve `BlockId`s to block numbers or hashes, and
/// retrieving the receipts should be done using the type's `ReceiptProvider` methods.
pub trait ReceiptProviderIdExt: ReceiptProvider + BlockIdProvider {
/// Get receipt by block id
fn receipts_by_block_id(&self, block: BlockId) -> Result<Option<Vec<Receipt>>> {
// TODO: to implement EIP-1898 at the provider level or not
let id = match block {
BlockId::Hash(hash) => BlockHashOrNumber::Hash(hash.block_hash),
BlockId::Number(num_tag) => {
if let Some(num) = self.convert_block_number(num_tag)? {
BlockHashOrNumber::Number(num)
} else {
return Ok(None)
}
}
};
self.receipts_by_block(id)
}
}
impl<T> ReceiptProviderIdExt for T where T: ReceiptProvider + BlockIdProvider {}

View File

@ -1,11 +1,13 @@
use crate::BlockIdProvider;
use crate::BlockNumProvider;
use reth_interfaces::Result;
use reth_primitives::{BlockId, BlockNumber, TransactionMeta, TransactionSigned, TxHash, TxNumber};
use reth_primitives::{
BlockHashOrNumber, BlockNumber, TransactionMeta, TransactionSigned, TxHash, TxNumber,
};
use std::ops::RangeBounds;
/// Client trait for fetching [TransactionSigned] related data.
#[auto_impl::auto_impl(&, Arc)]
pub trait TransactionsProvider: BlockIdProvider + Send + Sync {
pub trait TransactionsProvider: BlockNumProvider + Send + Sync {
/// Get internal transaction identifier by transaction hash.
///
/// This is the inverse of [TransactionsProvider::transaction_by_id].
@ -29,7 +31,10 @@ pub trait TransactionsProvider: BlockIdProvider + Send + Sync {
fn transaction_block(&self, id: TxNumber) -> Result<Option<BlockNumber>>;
/// Get transactions by block id.
fn transactions_by_block(&self, block: BlockId) -> Result<Option<Vec<TransactionSigned>>>;
fn transactions_by_block(
&self,
block: BlockHashOrNumber,
) -> Result<Option<Vec<TransactionSigned>>>;
/// Get transactions by block range.
fn transactions_by_block_range(

View File

@ -1,10 +1,14 @@
use reth_interfaces::Result;
use reth_primitives::{BlockId, Withdrawal};
use reth_primitives::{BlockHashOrNumber, Withdrawal};
/// Client trait for fetching [Withdrawal] related data.
pub trait WithdrawalsProvider: Send + Sync {
/// Get withdrawals by block id.
fn withdrawals_by_block(&self, id: BlockId, timestamp: u64) -> Result<Option<Vec<Withdrawal>>>;
fn withdrawals_by_block(
&self,
id: BlockHashOrNumber,
timestamp: u64,
) -> Result<Option<Vec<Withdrawal>>>;
/// Get latest withdrawal from this block or earlier .
fn latest_withdrawal(&self) -> Result<Option<Withdrawal>>;

View File

@ -6,7 +6,7 @@ use crate::{
};
use futures_util::{Stream, StreamExt};
use reth_primitives::{Address, BlockHash, BlockNumberOrTag, FromRecoveredTransaction};
use reth_provider::{BlockProvider, CanonStateNotification, PostState, StateProviderFactory};
use reth_provider::{BlockProviderIdExt, CanonStateNotification, PostState, StateProviderFactory};
use std::{
borrow::Borrow,
collections::HashSet,
@ -27,13 +27,13 @@ pub async fn maintain_transaction_pool<Client, V, T, St>(
pool: Pool<V, T>,
mut events: St,
) where
Client: StateProviderFactory + BlockProvider,
Client: StateProviderFactory + BlockProviderIdExt,
V: TransactionValidator,
T: TransactionOrdering<Transaction = <V as TransactionValidator>::Transaction>,
St: Stream<Item = CanonStateNotification> + Unpin,
{
// ensure the pool points to latest state
if let Ok(Some(latest)) = client.block(BlockNumberOrTag::Latest.into()) {
if let Ok(Some(latest)) = client.block_by_number_or_tag(BlockNumberOrTag::Latest) {
let latest = latest.seal_slow();
let info = BlockInfo {
last_seen_block_hash: latest.hash,