mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
perf: improve gas price calc (#5050)
Co-authored-by: Roman Krasiuk <rokrassyuk@gmail.com>
This commit is contained in:
@ -11,7 +11,7 @@ use tokio::sync::Mutex;
|
|||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
/// The number of transactions sampled in a block
|
/// The number of transactions sampled in a block
|
||||||
pub const SAMPLE_NUMBER: u32 = 3;
|
pub const SAMPLE_NUMBER: usize = 3_usize;
|
||||||
|
|
||||||
/// The default maximum gas price to use for the estimate
|
/// The default maximum gas price to use for the estimate
|
||||||
pub const DEFAULT_MAX_PRICE: U256 = U256::from_limbs([500_000_000_000u64, 0, 0, 0]);
|
pub const DEFAULT_MAX_PRICE: U256 = U256::from_limbs([500_000_000_000u64, 0, 0, 0]);
|
||||||
@ -88,6 +88,8 @@ pub struct GasPriceOracle<Provider> {
|
|||||||
cache: EthStateCache,
|
cache: EthStateCache,
|
||||||
/// The config for the oracle
|
/// The config for the oracle
|
||||||
oracle_config: GasPriceOracleConfig,
|
oracle_config: GasPriceOracleConfig,
|
||||||
|
/// The price under which the sample will be ignored.
|
||||||
|
ignore_price: Option<u128>,
|
||||||
/// The latest calculated price and its block hash
|
/// The latest calculated price and its block hash
|
||||||
last_price: Mutex<GasPriceOracleResult>,
|
last_price: Mutex<GasPriceOracleResult>,
|
||||||
}
|
}
|
||||||
@ -107,8 +109,9 @@ where
|
|||||||
warn!(prev_percentile = ?oracle_config.percentile, "Invalid configured gas price percentile, assuming 100.");
|
warn!(prev_percentile = ?oracle_config.percentile, "Invalid configured gas price percentile, assuming 100.");
|
||||||
oracle_config.percentile = 100;
|
oracle_config.percentile = 100;
|
||||||
}
|
}
|
||||||
|
let ignore_price = oracle_config.ignore_price.map(|price| price.saturating_to());
|
||||||
|
|
||||||
Self { provider, oracle_config, last_price: Default::default(), cache }
|
Self { provider, oracle_config, last_price: Default::default(), cache, ignore_price }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the configuration of the gas price oracle.
|
/// Returns the configuration of the gas price oracle.
|
||||||
@ -148,7 +151,7 @@ where
|
|||||||
|
|
||||||
for _ in 0..max_blocks {
|
for _ in 0..max_blocks {
|
||||||
let (parent_hash, block_values) = self
|
let (parent_hash, block_values) = self
|
||||||
.get_block_values(current_hash, SAMPLE_NUMBER as usize)
|
.get_block_values(current_hash, SAMPLE_NUMBER)
|
||||||
.await?
|
.await?
|
||||||
.ok_or(EthApiError::UnknownBlockNumber)?;
|
.ok_or(EthApiError::UnknownBlockNumber)?;
|
||||||
|
|
||||||
@ -201,51 +204,52 @@ where
|
|||||||
limit: usize,
|
limit: usize,
|
||||||
) -> EthResult<Option<(B256, Vec<U256>)>> {
|
) -> EthResult<Option<(B256, Vec<U256>)>> {
|
||||||
// check the cache (this will hit the disk if the block is not cached)
|
// check the cache (this will hit the disk if the block is not cached)
|
||||||
let block = match self.cache.get_block(block_hash).await? {
|
let mut block = match self.cache.get_block(block_hash).await? {
|
||||||
Some(block) => block,
|
Some(block) => block,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
// sort the transactions by effective tip
|
let base_fee_per_gas = block.base_fee_per_gas;
|
||||||
// but first filter those that should be ignored
|
let parent_hash = block.parent_hash;
|
||||||
let txs = block.body.iter();
|
|
||||||
let mut txs = txs
|
// sort the functions by ascending effective tip first
|
||||||
.filter(|tx| {
|
block.body.sort_by_cached_key(|tx| tx.effective_gas_tip(base_fee_per_gas));
|
||||||
if let Some(ignore_under) = self.oracle_config.ignore_price {
|
|
||||||
if tx.effective_gas_tip(block.base_fee_per_gas).map(U256::from) <
|
let mut prices = Vec::with_capacity(limit);
|
||||||
Some(ignore_under)
|
|
||||||
{
|
for tx in block.body.iter() {
|
||||||
return false
|
let mut effective_gas_tip = None;
|
||||||
}
|
// ignore transactions with a tip under the configured threshold
|
||||||
|
if let Some(ignore_under) = self.ignore_price {
|
||||||
|
let tip = tx.effective_gas_tip(base_fee_per_gas);
|
||||||
|
effective_gas_tip = Some(tip);
|
||||||
|
if tip < Some(ignore_under) {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// recover sender, check if coinbase
|
// check if the sender was the coinbase, if so, ignore
|
||||||
let sender = tx.recover_signer();
|
if let Some(sender) = tx.recover_signer() {
|
||||||
match sender {
|
if sender == block.beneficiary {
|
||||||
// transactions will be filtered if this is false
|
continue
|
||||||
Some(addr) => addr != block.beneficiary,
|
|
||||||
// TODO: figure out an error for this case or ignore
|
|
||||||
None => false,
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
// map all values to effective_gas_tip because we will be returning those values
|
|
||||||
// anyways
|
|
||||||
.map(|tx| tx.effective_gas_tip(block.base_fee_per_gas))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// now do the sort
|
|
||||||
txs.sort_unstable();
|
|
||||||
|
|
||||||
// fill result with the top `limit` transactions
|
|
||||||
let mut final_result = Vec::with_capacity(limit);
|
|
||||||
for tx in txs.iter().take(limit) {
|
|
||||||
// a `None` effective_gas_tip represents a transaction where the max_fee_per_gas is
|
// a `None` effective_gas_tip represents a transaction where the max_fee_per_gas is
|
||||||
// less than the base fee
|
// less than the base fee which would be invalid
|
||||||
let effective_tip = tx.ok_or(RpcInvalidTransactionError::FeeCapTooLow)?;
|
let effective_gas_tip = effective_gas_tip
|
||||||
final_result.push(U256::from(effective_tip));
|
.unwrap_or_else(|| tx.effective_gas_tip(base_fee_per_gas))
|
||||||
|
.ok_or(RpcInvalidTransactionError::FeeCapTooLow)?;
|
||||||
|
|
||||||
|
prices.push(U256::from(effective_gas_tip));
|
||||||
|
|
||||||
|
// we have enough entries
|
||||||
|
if prices.len() >= limit {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some((block.parent_hash, final_result)))
|
Ok(Some((parent_hash, prices)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user