mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-29 17:18:08 -05:00
perf(rpc): improve gas price perf by skipping hash (#2657)
This commit is contained in:
@@ -7,7 +7,9 @@ use reth_interfaces::{
|
||||
consensus::Consensus,
|
||||
Error,
|
||||
};
|
||||
use reth_primitives::{BlockHash, BlockNumHash, BlockNumber, SealedBlock, SealedBlockWithSenders};
|
||||
use reth_primitives::{
|
||||
BlockHash, BlockNumHash, BlockNumber, SealedBlock, SealedBlockWithSenders, SealedHeader,
|
||||
};
|
||||
use reth_provider::{
|
||||
BlockchainTreePendingStateProvider, CanonStateSubscriptions, ExecutorFactory,
|
||||
PostStateDataProvider,
|
||||
@@ -85,6 +87,11 @@ impl<DB: Database, C: Consensus, EF: ExecutorFactory> BlockchainTreeViewer
|
||||
self.tree.read().block_indices().block_number_to_block_hashes().clone()
|
||||
}
|
||||
|
||||
fn header_by_hash(&self, hash: BlockHash) -> Option<SealedHeader> {
|
||||
trace!(target: "blockchain_tree", ?hash, "Returning header by hash");
|
||||
self.tree.read().block_by_hash(hash).map(|b| b.header.clone())
|
||||
}
|
||||
|
||||
fn block_by_hash(&self, block_hash: BlockHash) -> Option<SealedBlock> {
|
||||
trace!(target: "blockchain_tree", ?block_hash, "Returning block by hash");
|
||||
self.tree.read().block_by_hash(block_hash).cloned()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use crate::{executor::Error as ExecutionError, Error};
|
||||
use reth_primitives::{BlockHash, BlockNumHash, BlockNumber, SealedBlock, SealedBlockWithSenders};
|
||||
use reth_primitives::{
|
||||
BlockHash, BlockNumHash, BlockNumber, SealedBlock, SealedBlockWithSenders, SealedHeader,
|
||||
};
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
|
||||
/// * [BlockchainTreeEngine::insert_block]: Connect block to chain, execute it and if valid insert
|
||||
@@ -90,6 +92,11 @@ pub trait BlockchainTreeViewer: Send + Sync {
|
||||
/// Caution: This will not return blocks from the canonical chain.
|
||||
fn blocks(&self) -> BTreeMap<BlockNumber, HashSet<BlockHash>>;
|
||||
|
||||
/// Returns the header with matching hash from the tree, if it exists.
|
||||
///
|
||||
/// Caution: This will not return headers from the canonical chain.
|
||||
fn header_by_hash(&self, hash: BlockHash) -> Option<SealedHeader>;
|
||||
|
||||
/// Returns the block with matching hash from the tree, if it exists.
|
||||
///
|
||||
/// Caution: This will not return blocks from the canonical chain.
|
||||
@@ -124,4 +131,9 @@ pub trait BlockchainTreeViewer: Send + Sync {
|
||||
fn pending_block(&self) -> Option<SealedBlock> {
|
||||
self.block_by_hash(self.pending_block_num_hash()?.hash)
|
||||
}
|
||||
|
||||
/// Returns the pending block if there is one.
|
||||
fn pending_header(&self) -> Option<SealedHeader> {
|
||||
self.header_by_hash(self.pending_block_num_hash()?.hash)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::eth::{
|
||||
cache::EthStateCache,
|
||||
error::{EthApiError, EthResult, InvalidTransactionError},
|
||||
};
|
||||
use reth_primitives::{constants::GWEI_TO_WEI, BlockId, BlockNumberOrTag, H256, U256};
|
||||
use reth_primitives::{constants::GWEI_TO_WEI, BlockNumberOrTag, H256, U256};
|
||||
use reth_provider::BlockProviderIdExt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::sync::Mutex;
|
||||
@@ -82,7 +82,7 @@ where
|
||||
mut oracle_config: GasPriceOracleConfig,
|
||||
cache: EthStateCache,
|
||||
) -> Self {
|
||||
// sanitize the perentile to be less than 100
|
||||
// sanitize the percentile to be less than 100
|
||||
if oracle_config.percentile > 100 {
|
||||
warn!(prev_percentile=?oracle_config.percentile, "Invalid configured gas price percentile, using 100 instead");
|
||||
oracle_config.percentile = 100;
|
||||
@@ -93,14 +93,11 @@ where
|
||||
|
||||
/// Suggests a gas price estimate based on recent blocks, using the configured percentile.
|
||||
pub async fn suggest_tip_cap(&self) -> EthResult<U256> {
|
||||
let block = self
|
||||
let header = self
|
||||
.client
|
||||
.block_by_id(BlockId::Number(BlockNumberOrTag::Latest))?
|
||||
.sealed_header_by_number_or_tag(BlockNumberOrTag::Latest)?
|
||||
.ok_or(EthApiError::UnknownBlockNumber)?;
|
||||
|
||||
// seal for the block hash
|
||||
let header = block.header.seal_slow();
|
||||
|
||||
let mut last_price = self.last_price.lock().await;
|
||||
|
||||
// if we have stored a last price, then we check whether or not it was for the same head
|
||||
|
||||
@@ -12,9 +12,9 @@ use reth_interfaces::{
|
||||
Error, Result,
|
||||
};
|
||||
use reth_primitives::{
|
||||
Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumber, ChainInfo, Header,
|
||||
Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, TransactionMeta, TransactionSigned,
|
||||
TxHash, TxNumber, Withdrawal, H256, U256,
|
||||
Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumHash, BlockNumber, BlockNumberOrTag,
|
||||
ChainInfo, Header, Receipt, SealedBlock, SealedBlockWithSenders, SealedHeader, TransactionMeta,
|
||||
TransactionSigned, TxHash, TxNumber, Withdrawal, H256, U256,
|
||||
};
|
||||
use reth_revm_primitives::primitives::{BlockEnv, CfgEnv};
|
||||
pub use state::{
|
||||
@@ -405,6 +405,10 @@ where
|
||||
self.tree.blocks()
|
||||
}
|
||||
|
||||
fn header_by_hash(&self, hash: BlockHash) -> Option<SealedHeader> {
|
||||
self.tree.header_by_hash(hash)
|
||||
}
|
||||
|
||||
fn block_by_hash(&self, block_hash: BlockHash) -> Option<SealedBlock> {
|
||||
self.tree.block_by_hash(block_hash)
|
||||
}
|
||||
@@ -441,20 +445,20 @@ where
|
||||
self.chain_info.on_forkchoice_update_received();
|
||||
}
|
||||
|
||||
fn set_finalized(&self, header: SealedHeader) {
|
||||
self.chain_info.set_finalized(header);
|
||||
}
|
||||
|
||||
fn set_safe(&self, header: SealedHeader) {
|
||||
self.chain_info.set_safe(header);
|
||||
fn last_received_update_timestamp(&self) -> Option<Instant> {
|
||||
self.chain_info.last_forkchoice_update_received_at()
|
||||
}
|
||||
|
||||
fn set_canonical_head(&self, header: SealedHeader) {
|
||||
self.chain_info.set_canonical_head(header);
|
||||
}
|
||||
|
||||
fn last_received_update_timestamp(&self) -> Option<Instant> {
|
||||
self.chain_info.last_forkchoice_update_received_at()
|
||||
fn set_safe(&self, header: SealedHeader) {
|
||||
self.chain_info.set_safe(header);
|
||||
}
|
||||
|
||||
fn set_finalized(&self, header: SealedHeader) {
|
||||
self.chain_info.set_finalized(header);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,6 +485,50 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn header_by_number_or_tag(&self, id: BlockNumberOrTag) -> Result<Option<Header>> {
|
||||
match id {
|
||||
BlockNumberOrTag::Latest => Ok(Some(self.chain_info.get_canonical_head().unseal())),
|
||||
BlockNumberOrTag::Finalized => {
|
||||
Ok(self.chain_info.get_finalized_header().map(|h| h.unseal()))
|
||||
}
|
||||
BlockNumberOrTag::Safe => Ok(self.chain_info.get_safe_header().map(|h| h.unseal())),
|
||||
BlockNumberOrTag::Earliest => self.header_by_number(0),
|
||||
BlockNumberOrTag::Pending => Ok(self.tree.pending_header().map(|h| h.unseal())),
|
||||
BlockNumberOrTag::Number(num) => self.header_by_number(num),
|
||||
}
|
||||
}
|
||||
|
||||
fn sealed_header_by_number_or_tag(&self, id: BlockNumberOrTag) -> Result<Option<SealedHeader>> {
|
||||
match id {
|
||||
BlockNumberOrTag::Latest => Ok(Some(self.chain_info.get_canonical_head())),
|
||||
BlockNumberOrTag::Finalized => Ok(self.chain_info.get_finalized_header()),
|
||||
BlockNumberOrTag::Safe => Ok(self.chain_info.get_safe_header()),
|
||||
BlockNumberOrTag::Earliest => {
|
||||
self.header_by_number(0)?.map_or_else(|| Ok(None), |h| Ok(Some(h.seal_slow())))
|
||||
}
|
||||
BlockNumberOrTag::Pending => Ok(self.tree.pending_header()),
|
||||
BlockNumberOrTag::Number(num) => {
|
||||
self.header_by_number(num)?.map_or_else(|| Ok(None), |h| Ok(Some(h.seal_slow())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sealed_header_by_id(&self, id: BlockId) -> Result<Option<SealedHeader>> {
|
||||
match id {
|
||||
BlockId::Number(num) => self.sealed_header_by_number_or_tag(num),
|
||||
BlockId::Hash(hash) => {
|
||||
self.header(&hash.block_hash)?.map_or_else(|| Ok(None), |h| Ok(Some(h.seal_slow())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn header_by_id(&self, id: BlockId) -> Result<Option<Header>> {
|
||||
match id {
|
||||
BlockId::Number(num) => self.header_by_number_or_tag(num),
|
||||
BlockId::Hash(hash) => self.header(&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),
|
||||
|
||||
@@ -8,8 +8,8 @@ use parking_lot::Mutex;
|
||||
use reth_interfaces::Result;
|
||||
use reth_primitives::{
|
||||
keccak256, Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber,
|
||||
Bytecode, Bytes, ChainInfo, Header, Receipt, SealedBlock, StorageKey, StorageValue,
|
||||
TransactionMeta, TransactionSigned, TxHash, TxNumber, H256, U256,
|
||||
Bytecode, Bytes, ChainInfo, Header, Receipt, SealedBlock, SealedHeader, StorageKey,
|
||||
StorageValue, TransactionMeta, TransactionSigned, TxHash, TxNumber, H256, U256,
|
||||
};
|
||||
use reth_revm_primitives::primitives::{BlockEnv, CfgEnv};
|
||||
use std::{
|
||||
@@ -306,6 +306,17 @@ impl BlockProviderIdExt for MockEthProvider {
|
||||
}
|
||||
}
|
||||
|
||||
fn sealed_header_by_id(&self, id: BlockId) -> Result<Option<SealedHeader>> {
|
||||
self.header_by_id(id)?.map_or_else(|| Ok(None), |h| Ok(Some(h.seal_slow())))
|
||||
}
|
||||
|
||||
fn header_by_id(&self, id: BlockId) -> Result<Option<Header>> {
|
||||
match self.block_by_id(id)? {
|
||||
None => Ok(None),
|
||||
Some(block) => Ok(Some(block.header)),
|
||||
}
|
||||
}
|
||||
|
||||
fn ommers_by_id(&self, id: BlockId) -> Result<Option<Vec<Header>>> {
|
||||
match id {
|
||||
BlockId::Number(num) => self.ommers_by_number_or_tag(num),
|
||||
|
||||
@@ -7,8 +7,8 @@ use crate::{
|
||||
use reth_interfaces::Result;
|
||||
use reth_primitives::{
|
||||
Account, Address, Block, BlockHash, BlockHashOrNumber, BlockId, BlockNumber, Bytecode, Bytes,
|
||||
ChainInfo, Header, Receipt, SealedBlock, StorageKey, StorageValue, TransactionMeta,
|
||||
TransactionSigned, TxHash, TxNumber, H256, KECCAK_EMPTY, U256,
|
||||
ChainInfo, Header, Receipt, SealedBlock, SealedHeader, StorageKey, StorageValue,
|
||||
TransactionMeta, TransactionSigned, TxHash, TxNumber, H256, KECCAK_EMPTY, U256,
|
||||
};
|
||||
use reth_revm_primitives::primitives::{BlockEnv, CfgEnv};
|
||||
use std::ops::RangeBounds;
|
||||
@@ -66,6 +66,14 @@ impl BlockProviderIdExt for NoopProvider {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn sealed_header_by_id(&self, _id: BlockId) -> Result<Option<SealedHeader>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn header_by_id(&self, _id: BlockId) -> Result<Option<Header>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn ommers_by_id(&self, _id: BlockId) -> Result<Option<Vec<Header>>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
};
|
||||
use reth_interfaces::Result;
|
||||
use reth_primitives::{
|
||||
Block, BlockHashOrNumber, BlockId, BlockNumberOrTag, Header, SealedBlock, H256,
|
||||
Block, BlockHashOrNumber, BlockId, BlockNumberOrTag, Header, SealedBlock, SealedHeader, H256,
|
||||
};
|
||||
|
||||
/// A helper enum that represents the origin of the requested block.
|
||||
@@ -107,6 +107,33 @@ pub trait BlockProviderIdExt: BlockProvider + BlockIdProvider {
|
||||
/// Returns `None` if block is not found.
|
||||
fn block_by_id(&self, id: BlockId) -> Result<Option<Block>>;
|
||||
|
||||
/// Returns the header with matching tag from the database
|
||||
///
|
||||
/// Returns `None` if header is not found.
|
||||
fn header_by_number_or_tag(&self, id: BlockNumberOrTag) -> Result<Option<Header>> {
|
||||
self.convert_block_number(id)?
|
||||
.map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))
|
||||
}
|
||||
|
||||
/// Returns the header with matching tag from the database
|
||||
///
|
||||
/// Returns `None` if header is not found.
|
||||
fn sealed_header_by_number_or_tag(&self, id: BlockNumberOrTag) -> Result<Option<SealedHeader>> {
|
||||
self.convert_block_number(id)?
|
||||
.map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))?
|
||||
.map_or_else(|| Ok(None), |h| Ok(Some(h.seal_slow())))
|
||||
}
|
||||
|
||||
/// Returns the sealed header with the matching `BlockId` from the database.
|
||||
///
|
||||
/// Returns `None` if header is not found.
|
||||
fn sealed_header_by_id(&self, id: BlockId) -> Result<Option<SealedHeader>>;
|
||||
|
||||
/// Returns the header with the matching `BlockId` from the database.
|
||||
///
|
||||
/// Returns `None` if header is not found.
|
||||
fn header_by_id(&self, id: BlockId) -> Result<Option<Header>>;
|
||||
|
||||
/// 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()))
|
||||
|
||||
Reference in New Issue
Block a user