mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: integrate price bump (#4398)
This commit is contained in:
@ -5,9 +5,16 @@ use crate::{
|
||||
pub use access_list::{AccessList, AccessListItem, AccessListWithGasUsed};
|
||||
use bytes::{Buf, BytesMut};
|
||||
use derive_more::{AsRef, Deref};
|
||||
pub use eip1559::TxEip1559;
|
||||
pub use eip2930::TxEip2930;
|
||||
pub use eip4844::{
|
||||
BlobTransaction, BlobTransactionSidecar, BlobTransactionValidationError, TxEip4844,
|
||||
};
|
||||
pub use error::InvalidTransactionError;
|
||||
pub use legacy::TxLegacy;
|
||||
pub use meta::TransactionMeta;
|
||||
use once_cell::sync::Lazy;
|
||||
pub use pooled::{PooledTransactionsElement, PooledTransactionsElementEcRecovered};
|
||||
use rayon::prelude::{IntoParallelIterator, ParallelIterator};
|
||||
use reth_codecs::{add_arbitrary_tests, derive_arbitrary, Compact};
|
||||
use reth_rlp::{Decodable, DecodeError, Encodable, Header, EMPTY_LIST_CODE, EMPTY_STRING_CODE};
|
||||
@ -18,14 +25,6 @@ pub use tx_type::{
|
||||
TxType, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, EIP4844_TX_TYPE_ID, LEGACY_TX_TYPE_ID,
|
||||
};
|
||||
|
||||
pub use eip1559::TxEip1559;
|
||||
pub use eip2930::TxEip2930;
|
||||
pub use eip4844::{
|
||||
BlobTransaction, BlobTransactionSidecar, BlobTransactionValidationError, TxEip4844,
|
||||
};
|
||||
pub use legacy::TxLegacy;
|
||||
pub use pooled::{PooledTransactionsElement, PooledTransactionsElementEcRecovered};
|
||||
|
||||
mod access_list;
|
||||
mod eip1559;
|
||||
mod eip2930;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use reth_primitives::EIP4844_TX_TYPE_ID;
|
||||
|
||||
/// Guarantees max transactions for one sender, compatible with geth/erigon
|
||||
pub const TXPOOL_MAX_ACCOUNT_SLOTS_PER_SENDER: usize = 16;
|
||||
|
||||
@ -11,6 +13,8 @@ pub const TXPOOL_SUBPOOL_MAX_SIZE_MB_DEFAULT: usize = 20;
|
||||
pub const DEFAULT_PRICE_BUMP: u128 = 10;
|
||||
|
||||
/// Replace blob price bump (in %) for the transaction pool underpriced check.
|
||||
///
|
||||
/// This enforces that a blob transaction requires a 100% price bump to be replaced
|
||||
pub const REPLACE_BLOB_PRICE_BUMP: u128 = 100;
|
||||
|
||||
/// Configuration options for the Transaction pool.
|
||||
@ -25,7 +29,7 @@ pub struct PoolConfig {
|
||||
/// Max number of executable transaction slots guaranteed per account
|
||||
pub max_account_slots: usize,
|
||||
/// Price bump (in %) for the transaction pool underpriced check.
|
||||
pub price_bump: u128,
|
||||
pub price_bumps: PriceBumpConfig,
|
||||
}
|
||||
|
||||
impl Default for PoolConfig {
|
||||
@ -35,7 +39,7 @@ impl Default for PoolConfig {
|
||||
basefee_limit: Default::default(),
|
||||
queued_limit: Default::default(),
|
||||
max_account_slots: TXPOOL_MAX_ACCOUNT_SLOTS_PER_SENDER,
|
||||
price_bump: PriceBumpConfig::default().default_price_bump,
|
||||
price_bumps: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,7 +72,7 @@ impl Default for SubPoolLimit {
|
||||
}
|
||||
|
||||
/// Price bump config (in %) for the transaction pool underpriced check.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub struct PriceBumpConfig {
|
||||
/// Default price bump (in %) for the transaction pool underpriced check.
|
||||
pub default_price_bump: u128,
|
||||
@ -76,6 +80,17 @@ pub struct PriceBumpConfig {
|
||||
pub replace_blob_tx_price_bump: u128,
|
||||
}
|
||||
|
||||
impl PriceBumpConfig {
|
||||
/// Returns the price bump required to replace the given transaction type.
|
||||
#[inline]
|
||||
pub(crate) fn price_bump(&self, tx_type: u8) -> u128 {
|
||||
if tx_type == EIP4844_TX_TYPE_ID {
|
||||
return self.replace_blob_tx_price_bump
|
||||
}
|
||||
self.default_price_bump
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PriceBumpConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
||||
@ -13,7 +13,8 @@ use crate::{
|
||||
AddedPendingTransaction, AddedTransaction, OnNewCanonicalStateOutcome,
|
||||
},
|
||||
traits::{BlockInfo, PoolSize},
|
||||
PoolConfig, PoolResult, PoolTransaction, TransactionOrdering, ValidPoolTransaction, U256,
|
||||
PoolConfig, PoolResult, PoolTransaction, PriceBumpConfig, TransactionOrdering,
|
||||
ValidPoolTransaction, U256,
|
||||
};
|
||||
use fnv::FnvHashMap;
|
||||
use reth_primitives::{
|
||||
@ -99,7 +100,7 @@ impl<T: TransactionOrdering> TxPool<T> {
|
||||
pending_pool: PendingPool::new(ordering),
|
||||
queued_pool: Default::default(),
|
||||
basefee_pool: Default::default(),
|
||||
all_transactions: AllTransactions::new(config.max_account_slots),
|
||||
all_transactions: AllTransactions::new(&config),
|
||||
config,
|
||||
metrics: Default::default(),
|
||||
}
|
||||
@ -682,12 +683,18 @@ pub(crate) struct AllTransactions<T: PoolTransaction> {
|
||||
last_seen_block_hash: H256,
|
||||
/// Expected base fee for the pending block.
|
||||
pending_basefee: u64,
|
||||
/// Configured price bump settings for replacements
|
||||
price_bumps: PriceBumpConfig,
|
||||
}
|
||||
|
||||
impl<T: PoolTransaction> AllTransactions<T> {
|
||||
/// Create a new instance
|
||||
fn new(max_account_slots: usize) -> Self {
|
||||
Self { max_account_slots, ..Default::default() }
|
||||
fn new(config: &PoolConfig) -> Self {
|
||||
Self {
|
||||
max_account_slots: config.max_account_slots,
|
||||
price_bumps: config.price_bumps,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over all _unique_ hashes in the pool
|
||||
@ -1031,23 +1038,26 @@ impl<T: PoolTransaction> AllTransactions<T> {
|
||||
Ok(transaction)
|
||||
}
|
||||
|
||||
/// Returns true if `transaction_a` is underpriced compared to `transaction_B`.
|
||||
/// Returns true if the replacement candidate is underpriced and can't replace the existing
|
||||
/// transaction.
|
||||
fn is_underpriced(
|
||||
transaction_a: &ValidPoolTransaction<T>,
|
||||
transaction_b: &ValidPoolTransaction<T>,
|
||||
price_bump: u128,
|
||||
existing_transaction: &ValidPoolTransaction<T>,
|
||||
maybe_replacement: &ValidPoolTransaction<T>,
|
||||
price_bumps: &PriceBumpConfig,
|
||||
) -> bool {
|
||||
let tx_a_max_priority_fee_per_gas =
|
||||
transaction_a.transaction.max_priority_fee_per_gas().unwrap_or(0);
|
||||
let tx_b_max_priority_fee_per_gas =
|
||||
transaction_b.transaction.max_priority_fee_per_gas().unwrap_or(0);
|
||||
let price_bump = price_bumps.price_bump(existing_transaction.tx_type());
|
||||
|
||||
transaction_a.max_fee_per_gas() <=
|
||||
transaction_b.max_fee_per_gas() * (100 + price_bump) / 100 ||
|
||||
(tx_a_max_priority_fee_per_gas <=
|
||||
tx_b_max_priority_fee_per_gas * (100 + price_bump) / 100 &&
|
||||
tx_a_max_priority_fee_per_gas != 0 &&
|
||||
tx_b_max_priority_fee_per_gas != 0)
|
||||
let existing_max_priority_fee_per_gas =
|
||||
maybe_replacement.transaction.max_priority_fee_per_gas().unwrap_or(0);
|
||||
let replacement_max_priority_fee_per_gas =
|
||||
existing_transaction.transaction.max_priority_fee_per_gas().unwrap_or(0);
|
||||
|
||||
maybe_replacement.max_fee_per_gas() <=
|
||||
existing_transaction.max_fee_per_gas() * (100 + price_bump) / 100 ||
|
||||
(existing_max_priority_fee_per_gas <=
|
||||
replacement_max_priority_fee_per_gas * (100 + price_bump) / 100 &&
|
||||
existing_max_priority_fee_per_gas != 0 &&
|
||||
replacement_max_priority_fee_per_gas != 0)
|
||||
}
|
||||
|
||||
/// Inserts a new transaction into the pool.
|
||||
@ -1117,11 +1127,10 @@ impl<T: PoolTransaction> AllTransactions<T> {
|
||||
Entry::Occupied(mut entry) => {
|
||||
// Transaction already exists
|
||||
// Ensure the new transaction is not underpriced
|
||||
|
||||
if Self::is_underpriced(
|
||||
transaction.as_ref(),
|
||||
entry.get().transaction.as_ref(),
|
||||
PoolConfig::default().price_bump,
|
||||
transaction.as_ref(),
|
||||
&self.price_bumps,
|
||||
) {
|
||||
return Err(InsertErr::Underpriced {
|
||||
transaction: pool_tx.transaction,
|
||||
@ -1257,6 +1266,7 @@ impl<T: PoolTransaction> Default for AllTransactions<T> {
|
||||
last_seen_block_number: 0,
|
||||
last_seen_block_hash: Default::default(),
|
||||
pending_basefee: Default::default(),
|
||||
price_bumps: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user