From 7d3016f0f2eee2e14c9bad8d225e55c836842ea7 Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Wed, 10 May 2023 16:03:16 -0400 Subject: [PATCH] feat: use BlockHashOrNum in providers (#2627) --- bin/reth/src/args/rpc_server_args.rs | 9 +- crates/blockchain-tree/src/blockchain_tree.rs | 4 +- crates/consensus/common/src/validation.rs | 9 +- crates/payload/basic/src/lib.rs | 6 +- crates/primitives/src/chain/info.rs | 20 +-- crates/rpc/rpc-builder/src/auth.rs | 9 +- crates/rpc/rpc-builder/src/lib.rs | 22 +-- crates/rpc/rpc-engine-api/src/engine_api.rs | 6 +- crates/rpc/rpc/src/debug.rs | 11 +- crates/rpc/rpc/src/eth/api/block.rs | 8 +- crates/rpc/rpc/src/eth/api/call.rs | 4 +- crates/rpc/rpc/src/eth/api/fees.rs | 4 +- crates/rpc/rpc/src/eth/api/mod.rs | 6 +- crates/rpc/rpc/src/eth/api/server.rs | 13 +- crates/rpc/rpc/src/eth/api/state.rs | 4 +- crates/rpc/rpc/src/eth/api/transactions.rs | 6 +- crates/rpc/rpc/src/eth/filter.rs | 30 +++- crates/rpc/rpc/src/eth/logs_utils.rs | 30 ++-- crates/storage/provider/src/lib.rs | 9 +- .../provider/src/providers/database.rs | 61 +++++---- crates/storage/provider/src/providers/mod.rs | 128 +++++++++++------- .../storage/provider/src/test_utils/mock.rs | 73 ++++++---- .../storage/provider/src/test_utils/noop.rs | 55 ++++++-- crates/storage/provider/src/traits/block.rs | 56 ++++++-- .../storage/provider/src/traits/block_id.rs | 71 ++++++++-- crates/storage/provider/src/traits/evm_env.rs | 20 ++- crates/storage/provider/src/traits/mod.rs | 6 +- .../storage/provider/src/traits/receipts.rs | 39 +++++- .../provider/src/traits/transactions.rs | 13 +- .../provider/src/traits/withdrawals.rs | 8 +- crates/transaction-pool/src/maintain.rs | 6 +- 31 files changed, 498 insertions(+), 248 deletions(-) diff --git a/bin/reth/src/args/rpc_server_args.rs b/bin/reth/src/args/rpc_server_args.rs index 0783ba643..ac93fb8d7 100644 --- a/bin/reth/src/args/rpc_server_args.rs +++ b/bin/reth/src/args/rpc_server_args.rs @@ -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 where - Client: BlockProvider + Client: BlockProviderIdExt + HeaderProvider + StateProviderFactory + EvmEnvProvider @@ -228,7 +229,7 @@ impl RpcServerArgs { jwt_secret: JwtSecret, ) -> Result where - Client: BlockProvider + Client: BlockProviderIdExt + HeaderProvider + StateProviderFactory + EvmEnvProvider diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index 678d5dc95..ce1cb0956 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -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}, diff --git a/crates/consensus/common/src/validation.rs b/crates/consensus/common/src/validation.rs index bea26aa5d..85abcf004 100644 --- a/crates/consensus/common/src/validation.rs +++ b/crates/consensus/common/src/validation.rs @@ -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>> ; } @@ -475,7 +476,7 @@ mod tests { fn withdrawals_by_block( &self, - _id: BlockId, + _id: BlockHashOrNumber, _timestamp: u64, ) -> RethResult>> { self.withdrawals_provider.withdrawals_by_block(_id, _timestamp) diff --git a/crates/payload/basic/src/lib.rs b/crates/payload/basic/src/lib.rs index 407520ae1..078779b49 100644 --- a/crates/payload/basic/src/lib.rs +++ b/crates/payload/basic/src/lib.rs @@ -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 BasicPayloadJobGenerator {} impl PayloadJobGenerator for BasicPayloadJobGenerator 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 { diff --git a/crates/primitives/src/chain/info.rs b/crates/primitives/src/chain/info.rs index 557e981d6..7a7d4b0ee 100644 --- a/crates/primitives/src/chain/info.rs +++ b/crates/primitives/src/chain/info.rs @@ -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, - /// Safe block - pub safe_finalized: Option, -} - -impl ChainInfo { - /// Attempts to convert a [BlockNumber](crate::rpc::BlockNumber) enum to a numeric value - pub fn convert_block_number(&self, number: BlockNumberOrTag) -> Option { - 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), - } - } } diff --git a/crates/rpc/rpc-builder/src/auth.rs b/crates/rpc/rpc-builder/src/auth.rs index 8f8e56d97..92e761745 100644 --- a/crates/rpc/rpc-builder/src/auth.rs +++ b/crates/rpc/rpc-builder/src/auth.rs @@ -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( secret: JwtSecret, ) -> Result where - Client: BlockProvider + Client: BlockProviderIdExt + + ReceiptProviderIdExt + HeaderProvider + StateProviderFactory + EvmEnvProvider @@ -63,7 +66,7 @@ pub async fn launch_with_eth_api( secret: JwtSecret, ) -> Result where - Client: BlockProvider + Client: BlockProviderIdExt + HeaderProvider + StateProviderFactory + EvmEnvProvider diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index eb95dda99..d95d9fb09 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -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: 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: 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( events: Events, ) -> Result 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 RpcModuleBuilder RpcModuleBuilder 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 RethModuleRegistry 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, diff --git a/crates/rpc/rpc-engine-api/src/engine_api.rs b/crates/rpc/rpc-engine-api/src/engine_api.rs index 26bb05641..0e4617fb9 100644 --- a/crates/rpc/rpc-engine-api/src/engine_api.rs +++ b/crates/rpc/rpc-engine-api/src/engine_api.rs @@ -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)); } diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index f70c09831..f8dce423b 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -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 DebugApi { impl DebugApi 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 DebugApiServer for DebugApi 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 { - 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> { - 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 { diff --git a/crates/rpc/rpc/src/eth/api/block.rs b/crates/rpc/rpc/src/eth/api/block.rs index 0c8b3ea3f..218e180fa 100644 --- a/crates/rpc/rpc/src/eth/api/block.rs +++ b/crates/rpc/rpc/src/eth/api/block.rs @@ -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 EthApi 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, ) -> EthResult>> { 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(); diff --git a/crates/rpc/rpc/src/eth/api/call.rs b/crates/rpc/rpc/src/eth/api/call.rs index 7ec43d2a1..b1ff1a296 100644 --- a/crates/rpc/rpc/src/eth/api/call.rs +++ b/crates/rpc/rpc/src/eth/api/call.rs @@ -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 EthApi 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]. diff --git a/crates/rpc/rpc/src/eth/api/fees.rs b/crates/rpc/rpc/src/eth/api/fees.rs index ac5174e91..7518dc4a8 100644 --- a/crates/rpc/rpc/src/eth/api/fees.rs +++ b/crates/rpc/rpc/src/eth/api/fees.rs @@ -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 EthApi 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. diff --git a/crates/rpc/rpc/src/eth/api/mod.rs b/crates/rpc/rpc/src/eth/api/mod.rs index 6e37e9480..f0b963284 100644 --- a/crates/rpc/rpc/src/eth/api/mod.rs +++ b/crates/rpc/rpc/src/eth/api/mod.rs @@ -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 EthApi { impl EthApi where - Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static, + Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + 'static, { fn convert_block_number(&self, num: BlockNumberOrTag) -> Result> { self.client().convert_block_number(num) @@ -177,7 +177,7 @@ impl std::fmt::Debug for EthApi { impl EthApiSpec for EthApi where Pool: TransactionPool + Clone + 'static, - Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static, + Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + 'static, Network: NetworkInfo + 'static, { /// Returns the current ethereum protocol version. diff --git a/crates/rpc/rpc/src/eth/api/server.rs b/crates/rpc/rpc/src/eth/api/server.rs index 704796886..b3397849e 100644 --- a/crates/rpc/rpc/src/eth/api/server.rs +++ b/crates/rpc/rpc/src/eth/api/server.rs @@ -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 EthApiServer for EthApi 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` diff --git a/crates/rpc/rpc/src/eth/api/state.rs b/crates/rpc/rpc/src/eth/api/state.rs index ff4a7f7b3..0ed49530e 100644 --- a/crates/rpc/rpc/src/eth/api/state.rs +++ b/crates/rpc/rpc/src/eth/api/state.rs @@ -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 EthApi 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) -> EthResult { diff --git a/crates/rpc/rpc/src/eth/api/transactions.rs b/crates/rpc/rpc/src/eth/api/transactions.rs index dc49c9296..267f9faa4 100644 --- a/crates/rpc/rpc/src/eth/api/transactions.rs +++ b/crates/rpc/rpc/src/eth/api/transactions.rs @@ -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 EthTransactions for EthApi 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> { @@ -534,7 +534,7 @@ where impl EthApi where Pool: TransactionPool + 'static, - Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static, + Client: BlockProviderIdExt + StateProviderFactory + EvmEnvProvider + 'static, Network: 'static, { pub(crate) fn sign_request( diff --git a/crates/rpc/rpc/src/eth/filter.rs b/crates/rpc/rpc/src/eth/filter.rs index 4aff2cb3f..383795ad1 100644 --- a/crates/rpc/rpc/src/eth/filter.rs +++ b/crates/rpc/rpc/src/eth/filter.rs @@ -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 EthFilter { #[async_trait] impl EthFilterApiServer for EthFilter 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 { impl EthFilterInner 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?) diff --git a/crates/rpc/rpc/src/eth/logs_utils.rs b/crates/rpc/rpc/src/eth/logs_utils.rs index 107209b3c..671d5428d 100644 --- a/crates/rpc/rpc/src/eth/logs_utils.rs +++ b/crates/rpc/rpc/src/eth/logs_utils.rs @@ -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, - to_block: Option, + from_block: Option, + to_block: Option, 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] diff --git a/crates/storage/provider/src/lib.rs b/crates/storage/provider/src/lib.rs index 32895c2b6..406376383 100644 --- a/crates/storage/provider/src/lib.rs +++ b/crates/storage/provider/src/lib.rs @@ -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, }; diff --git a/crates/storage/provider/src/providers/database.rs b/crates/storage/provider/src/providers/database.rs index dd611659e..535b490b7 100644 --- a/crates/storage/provider/src/providers/database.rs +++ b/crates/storage/provider/src/providers/database.rs @@ -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 BlockHashProvider for ShareableDatabase { } } -impl BlockIdProvider for ShareableDatabase { +impl BlockNumProvider for ShareableDatabase { fn chain_info(&self) -> Result { 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 { @@ -174,10 +175,10 @@ impl BlockProvider for ShareableDatabase { } } - fn block(&self, id: BlockId) -> Result> { - if let Some(number) = self.block_number_for_id(id)? { + fn block(&self, id: BlockHashOrNumber) -> Result> { + 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 BlockProvider for ShareableDatabase { Ok(None) } - fn ommers(&self, id: BlockId) -> Result>> { - if let Some(number) = self.block_number_for_id(id)? { + fn ommers(&self, id: BlockHashOrNumber) -> Result>> { + 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::(number)?.map(|o| o.ommers); @@ -293,8 +294,11 @@ impl TransactionsProvider for ShareableDatabase { .map_err(Into::into) } - fn transactions_by_block(&self, id: BlockId) -> Result>> { - if let Some(number) = self.block_number_for_id(id)? { + fn transactions_by_block( + &self, + id: BlockHashOrNumber, + ) -> Result>> { + if let Some(number) = self.convert_hash(id)? { let tx = self.db.tx()?; if let Some(body) = tx.get::(number)? { let tx_range = body.tx_num_range(); @@ -356,8 +360,8 @@ impl ReceiptProvider for ShareableDatabase { .map_err(Into::into) } - fn receipts_by_block(&self, block: BlockId) -> Result>> { - if let Some(number) = self.block_number_for_id(block)? { + fn receipts_by_block(&self, block: BlockHashOrNumber) -> Result>> { + if let Some(number) = self.convert_hash(block)? { let tx = self.db.tx()?; if let Some(body) = tx.get::(number)? { let tx_range = body.tx_num_range(); @@ -378,9 +382,13 @@ impl ReceiptProvider for ShareableDatabase { } impl WithdrawalsProvider for ShareableDatabase { - fn withdrawals_by_block(&self, id: BlockId, timestamp: u64) -> Result>> { + fn withdrawals_by_block( + &self, + id: BlockHashOrNumber, + timestamp: u64, + ) -> Result>> { 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 WithdrawalsProvider for ShareableDatabase { } impl EvmEnvProvider for ShareableDatabase { - 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 EvmEnvProvider for ShareableDatabase { 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 EvmEnvProvider for ShareableDatabase { 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); } } diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index b7f0a68a4..e6af92754 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -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 BlockIdProvider for BlockchainProvider +impl BlockNumProvider for BlockchainProvider 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> { - 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> { - 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> { self.database.block_number(hash) } } +impl BlockIdProvider for BlockchainProvider +where + DB: Database, + Tree: BlockchainTreeViewer + Send + Sync, +{ + fn safe_block_num(&self) -> Result> { + todo!() + } + + fn finalized_block_num(&self) -> Result> { + todo!() + } + + fn pending_block_num_hash(&self) -> Result> { + Ok(self.tree.pending_block_num_hash()) + } +} + impl BlockProvider for BlockchainProvider where DB: Database, @@ -163,18 +152,18 @@ where Ok(block) } - fn block(&self, id: BlockId) -> Result> { - if id.is_pending() { - return Ok(self.tree.pending_block().map(SealedBlock::unseal)) + fn block(&self, id: BlockHashOrNumber) -> Result> { + 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> { Ok(self.tree.pending_block()) } - fn ommers(&self, id: BlockId) -> Result>> { + fn ommers(&self, id: BlockHashOrNumber) -> Result>> { self.database.ommers(id) } } @@ -207,7 +196,10 @@ where self.database.transaction_block(id) } - fn transactions_by_block(&self, id: BlockId) -> Result>> { + fn transactions_by_block( + &self, + id: BlockHashOrNumber, + ) -> Result>> { 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>> { + fn receipts_by_block(&self, block: BlockHashOrNumber) -> Result>> { 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>> { + fn withdrawals_by_block( + &self, + id: BlockHashOrNumber, + timestamp: u64, + ) -> Result>> { 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 BlockProviderIdExt for BlockchainProvider +where + Self: BlockProvider + BlockIdProvider, + Tree: BlockchainTreeEngine, +{ + fn block_by_id(&self, id: BlockId) -> Result> { + 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>> { + 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 BlockchainTreePendingStateProvider for BlockchainProvider where DB: Send + Sync, diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index b4a7d1ec5..e98556e60 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -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>> { + fn transactions_by_block( + &self, + id: BlockHashOrNumber, + ) -> Result>> { 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>> { + fn receipts_by_block(&self, _block: BlockHashOrNumber) -> Result>> { Ok(None) } } @@ -231,7 +234,7 @@ impl BlockHashProvider for MockEthProvider { } } -impl BlockIdProvider for MockEthProvider { +impl BlockNumProvider for MockEthProvider { fn chain_info(&self) -> Result { 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> { + Ok(None) + } + + fn pending_block_num_hash(&self) -> Result> { + Ok(None) + } + + fn finalized_block_num(&self) -> Result> { + Ok(None) + } +} + impl BlockProvider for MockEthProvider { fn find_block_by_hash(&self, hash: H256, _source: BlockSource) -> Result> { self.block(hash.into()) } - fn block(&self, id: BlockId) -> Result> { + fn block(&self, id: BlockHashOrNumber) -> Result> { 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>> { + fn ommers(&self, _id: BlockHashOrNumber) -> Result>> { Ok(None) } } +impl BlockProviderIdExt for MockEthProvider { + fn block_by_id(&self, id: BlockId) -> Result> { + 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>> { + 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> { 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!() } diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index b208b4223..9d614ba2a 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -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 { Ok(ChainInfo::default()) } @@ -48,7 +48,7 @@ impl BlockProvider for NoopProvider { self.block(hash.into()) } - fn block(&self, _id: BlockId) -> Result> { + fn block(&self, _id: BlockHashOrNumber) -> Result> { Ok(None) } @@ -56,7 +56,31 @@ impl BlockProvider for NoopProvider { Ok(None) } - fn ommers(&self, _id: BlockId) -> Result>> { + fn ommers(&self, _id: BlockHashOrNumber) -> Result>> { + Ok(None) + } +} + +impl BlockProviderIdExt for NoopProvider { + fn block_by_id(&self, _id: BlockId) -> Result> { + Ok(None) + } + + fn ommers_by_id(&self, _id: BlockId) -> Result>> { + Ok(None) + } +} + +impl BlockIdProvider for NoopProvider { + fn pending_block_num_hash(&self) -> Result> { + Ok(None) + } + + fn safe_block_num(&self) -> Result> { + Ok(None) + } + + fn finalized_block_num(&self) -> Result> { Ok(None) } } @@ -85,7 +109,10 @@ impl TransactionsProvider for NoopProvider { todo!() } - fn transactions_by_block(&self, _block_id: BlockId) -> Result>> { + fn transactions_by_block( + &self, + _block_id: BlockHashOrNumber, + ) -> Result>> { Ok(None) } @@ -106,7 +133,7 @@ impl ReceiptProvider for NoopProvider { Ok(None) } - fn receipts_by_block(&self, _block: BlockId) -> Result>> { + fn receipts_by_block(&self, _block: BlockHashOrNumber) -> Result>> { 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(()) } diff --git a/crates/storage/provider/src/traits/block.rs b/crates/storage/provider/src/traits/block.rs index 8309df6f4..ec0699735 100644 --- a/crates/storage/provider/src/traits/block.rs +++ b/crates/storage/provider/src/traits/block.rs @@ -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>; + fn block(&self, id: BlockHashOrNumber) -> Result>; /// 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>>; + fn ommers(&self, id: BlockHashOrNumber) -> Result>>; /// 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> { - 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> { + 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>; + + /// Returns the ommers with the matching tag from the database. + fn ommers_by_number_or_tag(&self, id: BlockNumberOrTag) -> Result>> { + 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>>; +} diff --git a/crates/storage/provider/src/traits/block_id.rs b/crates/storage/provider/src/traits/block_id.rs index 7ee5c4398..9376ddc68 100644 --- a/crates/storage/provider/src/traits/block_id.rs +++ b/crates/storage/provider/src/traits/block_id.rs @@ -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; /// Returns the best block number in the chain. fn best_block_number(&self) -> Result; - /// 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>; + + /// 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> { + 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> { + 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>; + /// Get the current pending block number and hash. + fn pending_block_num_hash(&self) -> Result>; + + /// Get the safe block number. + fn safe_block_num(&self) -> Result>; + + /// Get the finalized block number. + fn finalized_block_num(&self) -> Result>; } diff --git a/crates/storage/provider/src/traits/evm_env.rs b/crates/storage/provider/src/traits/evm_env.rs index 60ae94f89..b90315e40 100644 --- a/crates/storage/provider/src/traits/evm_env.rs +++ b/crates/storage/provider/src/traits/evm_env.rs @@ -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<()>; diff --git a/crates/storage/provider/src/traits/mod.rs b/crates/storage/provider/src/traits/mod.rs index f0adfdd2e..ebaf060e5 100644 --- a/crates/storage/provider/src/traits/mod.rs +++ b/crates/storage/provider/src/traits/mod.rs @@ -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::{ diff --git a/crates/storage/provider/src/traits/receipts.rs b/crates/storage/provider/src/traits/receipts.rs index fa5604b28..46cf992c7 100644 --- a/crates/storage/provider/src/traits/receipts.rs +++ b/crates/storage/provider/src/traits/receipts.rs @@ -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>; - /// Get receipts by block id. - fn receipts_by_block(&self, block: BlockId) -> Result>>; + /// Get receipts by block num or hash. + fn receipts_by_block(&self, block: BlockHashOrNumber) -> Result>>; } + +/// 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>> { + // 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 ReceiptProviderIdExt for T where T: ReceiptProvider + BlockIdProvider {} diff --git a/crates/storage/provider/src/traits/transactions.rs b/crates/storage/provider/src/traits/transactions.rs index b960b9010..f80bf9db5 100644 --- a/crates/storage/provider/src/traits/transactions.rs +++ b/crates/storage/provider/src/traits/transactions.rs @@ -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>; /// Get transactions by block id. - fn transactions_by_block(&self, block: BlockId) -> Result>>; + fn transactions_by_block( + &self, + block: BlockHashOrNumber, + ) -> Result>>; /// Get transactions by block range. fn transactions_by_block_range( diff --git a/crates/storage/provider/src/traits/withdrawals.rs b/crates/storage/provider/src/traits/withdrawals.rs index 9a6fe8045..ffa33feba 100644 --- a/crates/storage/provider/src/traits/withdrawals.rs +++ b/crates/storage/provider/src/traits/withdrawals.rs @@ -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>>; + fn withdrawals_by_block( + &self, + id: BlockHashOrNumber, + timestamp: u64, + ) -> Result>>; /// Get latest withdrawal from this block or earlier . fn latest_withdrawal(&self) -> Result>; diff --git a/crates/transaction-pool/src/maintain.rs b/crates/transaction-pool/src/maintain.rs index 57add620b..d7ee2279b 100644 --- a/crates/transaction-pool/src/maintain.rs +++ b/crates/transaction-pool/src/maintain.rs @@ -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( pool: Pool, mut events: St, ) where - Client: StateProviderFactory + BlockProvider, + Client: StateProviderFactory + BlockProviderIdExt, V: TransactionValidator, T: TransactionOrdering::Transaction>, St: Stream + 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,