Skip to content
This repository was archived by the owner on Jan 9, 2026. It is now read-only.

Commit 0bd1bb2

Browse files
authored
feat: introduce setting for delegated txs slots (paradigmxyz#18298)
1 parent e93e1fc commit 0bd1bb2

File tree

4 files changed

+38
-9
lines changed

4 files changed

+38
-9
lines changed

crates/node/core/src/args/txpool.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ impl RethTransactionPoolConfig for TxPoolArgs {
230230
new_tx_listener_buffer_size: self.new_tx_listener_buffer_size,
231231
max_new_pending_txs_notifications: self.max_new_pending_txs_notifications,
232232
max_queued_lifetime: self.max_queued_lifetime,
233+
..Default::default()
233234
}
234235
}
235236

crates/transaction-pool/src/config.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ pub const REPLACE_BLOB_PRICE_BUMP: u128 = 100;
3131
/// Default maximum new transactions for broadcasting.
3232
pub const MAX_NEW_PENDING_TXS_NOTIFICATIONS: usize = 200;
3333

34+
/// Default maximum allowed in flight delegated transactions per account.
35+
pub const DEFAULT_MAX_INFLIGHT_DELEGATED_SLOTS: usize = 1;
36+
3437
/// Configuration options for the Transaction pool.
3538
#[derive(Debug, Clone)]
3639
pub struct PoolConfig {
@@ -65,6 +68,10 @@ pub struct PoolConfig {
6568
pub max_new_pending_txs_notifications: usize,
6669
/// Maximum lifetime for transactions in the pool
6770
pub max_queued_lifetime: Duration,
71+
/// The maximum allowed inflight transactions a delegated sender can have.
72+
///
73+
/// This restricts how many executable transaction a delegated sender can stack.
74+
pub max_inflight_delegated_slot_limit: usize,
6875
}
6976

7077
impl PoolConfig {
@@ -84,6 +91,15 @@ impl PoolConfig {
8491
self
8592
}
8693

94+
/// Configures how many slots are available for a delegated sender.
95+
pub const fn with_max_inflight_delegated_slots(
96+
mut self,
97+
max_inflight_delegation_limit: usize,
98+
) -> Self {
99+
self.max_inflight_delegated_slot_limit = max_inflight_delegation_limit;
100+
self
101+
}
102+
87103
/// Returns whether the size and amount constraints in any sub-pools are exceeded.
88104
#[inline]
89105
pub const fn is_exceeded(&self, pool_size: PoolSize) -> bool {
@@ -112,6 +128,7 @@ impl Default for PoolConfig {
112128
new_tx_listener_buffer_size: NEW_TX_LISTENER_BUFFER_SIZE,
113129
max_new_pending_txs_notifications: MAX_NEW_PENDING_TXS_NOTIFICATIONS,
114130
max_queued_lifetime: MAX_QUEUED_TRANSACTION_LIFETIME,
131+
max_inflight_delegated_slot_limit: DEFAULT_MAX_INFLIGHT_DELEGATED_SLOTS,
115132
}
116133
}
117134
}

crates/transaction-pool/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ pub use crate::{
274274
batcher::{BatchTxProcessor, BatchTxRequest},
275275
blobstore::{BlobStore, BlobStoreError},
276276
config::{
277-
LocalTransactionConfig, PoolConfig, PriceBumpConfig, SubPoolLimit, DEFAULT_PRICE_BUMP,
277+
LocalTransactionConfig, PoolConfig, PriceBumpConfig, SubPoolLimit,
278+
DEFAULT_MAX_INFLIGHT_DELEGATED_SLOTS, DEFAULT_PRICE_BUMP,
278279
DEFAULT_TXPOOL_ADDITIONAL_VALIDATION_TASKS, MAX_NEW_PENDING_TXS_NOTIFICATIONS,
279280
REPLACE_BLOB_PRICE_BUMP, TXPOOL_MAX_ACCOUNT_SLOTS_PER_SENDER,
280281
TXPOOL_SUBPOOL_MAX_SIZE_MB_DEFAULT, TXPOOL_SUBPOOL_MAX_TXS_DEFAULT,

crates/transaction-pool/src/pool/txpool.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -771,8 +771,8 @@ impl<T: TransactionOrdering> TxPool<T> {
771771
}
772772

773773
/// Determines if the tx sender is delegated or has a pending delegation, and if so, ensures
774-
/// they have at most one in-flight **executable** transaction, e.g. disallow stacked and
775-
/// nonce-gapped transactions from the account.
774+
/// they have at most one configured amount of in-flight **executable** transactions (default at
775+
/// most one), e.g. disallow stacked and nonce-gapped transactions from the account.
776776
fn check_delegation_limit(
777777
&self,
778778
transaction: &ValidPoolTransaction<T::Transaction>,
@@ -802,8 +802,17 @@ impl<T: TransactionOrdering> TxPool<T> {
802802
return Ok(())
803803
}
804804

805-
if txs_by_sender.any(|id| id == &transaction.transaction_id) {
806-
// Transaction replacement is supported
805+
let mut count = 0;
806+
for id in txs_by_sender {
807+
if id == &transaction.transaction_id {
808+
// Transaction replacement is supported
809+
return Ok(())
810+
}
811+
count += 1;
812+
}
813+
814+
if count < self.config.max_inflight_delegated_slot_limit {
815+
// account still has an available slot
807816
return Ok(())
808817
}
809818

@@ -818,8 +827,9 @@ impl<T: TransactionOrdering> TxPool<T> {
818827
/// This verifies that the transaction complies with code authorization
819828
/// restrictions brought by EIP-7702 transaction type:
820829
/// 1. Any account with a deployed delegation or an in-flight authorization to deploy a
821-
/// delegation will only be allowed a single transaction slot instead of the standard limit.
822-
/// This is due to the possibility of the account being sweeped by an unrelated account.
830+
/// delegation will only be allowed a certain amount of transaction slots (default 1) instead
831+
/// of the standard limit. This is due to the possibility of the account being sweeped by an
832+
/// unrelated account.
823833
/// 2. In case the pool is tracking a pending / queued transaction from a specific account, at
824834
/// most one in-flight transaction is allowed; any additional delegated transactions from
825835
/// that account will be rejected.
@@ -829,12 +839,12 @@ impl<T: TransactionOrdering> TxPool<T> {
829839
on_chain_nonce: u64,
830840
on_chain_code_hash: Option<B256>,
831841
) -> Result<(), PoolError> {
832-
// Allow at most one in-flight tx for delegated accounts or those with a
833-
// pending authorization.
842+
// Ensure in-flight limit for delegated accounts or those with a pending authorization.
834843
self.check_delegation_limit(transaction, on_chain_nonce, on_chain_code_hash)?;
835844

836845
if let Some(authority_list) = &transaction.authority_ids {
837846
for sender_id in authority_list {
847+
// Ensure authority has at most 1 inflight transaction.
838848
if self.all_transactions.txs_iter(*sender_id).nth(1).is_some() {
839849
return Err(PoolError::new(
840850
*transaction.hash(),

0 commit comments

Comments
 (0)