From e848dcd67567bebaae357d81ba1f797d58fc68cc Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Mon, 29 May 2023 16:11:37 +0200 Subject: [PATCH] perf(rpc): use block hash or number (#2892) --- crates/rpc/rpc/src/eth/filter.rs | 17 ++++++++++++----- .../storage/provider/src/traits/block_hash.rs | 11 ++++++++++- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/crates/rpc/rpc/src/eth/filter.rs b/crates/rpc/rpc/src/eth/filter.rs index 981e9a4273..cfd61e0f05 100644 --- a/crates/rpc/rpc/src/eth/filter.rs +++ b/crates/rpc/rpc/src/eth/filter.rs @@ -9,7 +9,7 @@ use crate::{ }; use async_trait::async_trait; use jsonrpsee::{core::RpcResult, server::IdProvider}; -use reth_primitives::{Receipt, SealedBlock, H256}; +use reth_primitives::{BlockHashOrNumber, Receipt, SealedBlock, H256}; use reth_provider::{BlockIdProvider, BlockProvider, EvmEnvProvider}; use reth_rpc_api::EthFilterApiServer; use reth_rpc_types::{Filter, FilterBlockOption, FilterChanges, FilterId, FilteredParams, Log}; @@ -336,9 +336,9 @@ where /// Fetches both receipts and block for the given block number. async fn block_and_receipts_by_number( &self, - block_number: u64, + hash_or_number: BlockHashOrNumber, ) -> EthResult)>> { - let block_hash = match self.client.block_hash(block_number)? { + let block_hash = match self.client.convert_block_hash(hash_or_number)? { Some(hash) => hash, None => return Ok(None), }; @@ -388,13 +388,20 @@ where { let headers = self.client.headers_range(from..=to)?; - for header in headers { + for (idx, header) in headers.iter().enumerate() { + // these are consecutive headers, so we can use the parent hash of the next block to + // get the current header's hash + let num_hash: BlockHashOrNumber = headers + .get(idx + 1) + .map(|h| h.parent_hash.into()) + .unwrap_or_else(|| header.number.into()); + // only if filter matches if FilteredParams::matches_address(header.logs_bloom, &address_filter) && FilteredParams::matches_topics(header.logs_bloom, &topics_filter) { if let Some((block, receipts)) = - self.block_and_receipts_by_number(header.number).await? + self.block_and_receipts_by_number(num_hash).await? { let block_hash = block.hash; diff --git a/crates/storage/provider/src/traits/block_hash.rs b/crates/storage/provider/src/traits/block_hash.rs index 855c77a615..ed8249cdd5 100644 --- a/crates/storage/provider/src/traits/block_hash.rs +++ b/crates/storage/provider/src/traits/block_hash.rs @@ -1,6 +1,6 @@ use auto_impl::auto_impl; use reth_interfaces::Result; -use reth_primitives::{BlockNumber, H256}; +use reth_primitives::{BlockHashOrNumber, BlockNumber, H256}; /// Client trait for fetching block hashes by number. #[auto_impl(&, Arc, Box)] @@ -9,6 +9,15 @@ pub trait BlockHashProvider: Send + Sync { /// exists. fn block_hash(&self, number: BlockNumber) -> Result>; + /// Get the hash of the block with the given number. Returns `None` if no block with this number + /// exists. + fn convert_block_hash(&self, hash_or_number: BlockHashOrNumber) -> Result> { + match hash_or_number { + BlockHashOrNumber::Hash(hash) => Ok(Some(hash)), + BlockHashOrNumber::Number(num) => self.block_hash(num), + } + } + /// Get headers in range of block hashes or numbers fn canonical_hashes_range(&self, start: BlockNumber, end: BlockNumber) -> Result>; }