reth_node_core/args/
txpool.rs

1//! Transaction pool arguments
2
3use crate::cli::config::RethTransactionPoolConfig;
4use alloy_eips::eip1559::{ETHEREUM_BLOCK_GAS_LIMIT, MIN_PROTOCOL_BASE_FEE};
5use alloy_primitives::Address;
6use clap::Args;
7use reth_transaction_pool::{
8    blobstore::disk::DEFAULT_MAX_CACHED_BLOBS,
9    pool::{NEW_TX_LISTENER_BUFFER_SIZE, PENDING_TX_LISTENER_BUFFER_SIZE},
10    validate::DEFAULT_MAX_TX_INPUT_BYTES,
11    LocalTransactionConfig, PoolConfig, PriceBumpConfig, SubPoolLimit, DEFAULT_PRICE_BUMP,
12    DEFAULT_TXPOOL_ADDITIONAL_VALIDATION_TASKS, MAX_NEW_PENDING_TXS_NOTIFICATIONS,
13    REPLACE_BLOB_PRICE_BUMP, TXPOOL_MAX_ACCOUNT_SLOTS_PER_SENDER,
14    TXPOOL_SUBPOOL_MAX_SIZE_MB_DEFAULT, TXPOOL_SUBPOOL_MAX_TXS_DEFAULT,
15};
16/// Parameters for debugging purposes
17#[derive(Debug, Clone, Args, PartialEq, Eq)]
18#[command(next_help_heading = "TxPool")]
19pub struct TxPoolArgs {
20    /// Max number of transaction in the pending sub-pool.
21    #[arg(long = "txpool.pending-max-count", alias = "txpool.pending_max_count", default_value_t = TXPOOL_SUBPOOL_MAX_TXS_DEFAULT)]
22    pub pending_max_count: usize,
23    /// Max size of the pending sub-pool in megabytes.
24    #[arg(long = "txpool.pending-max-size", alias = "txpool.pending_max_size", default_value_t = TXPOOL_SUBPOOL_MAX_SIZE_MB_DEFAULT)]
25    pub pending_max_size: usize,
26
27    /// Max number of transaction in the basefee sub-pool
28    #[arg(long = "txpool.basefee-max-count", alias = "txpool.basefee_max_count", default_value_t = TXPOOL_SUBPOOL_MAX_TXS_DEFAULT)]
29    pub basefee_max_count: usize,
30    /// Max size of the basefee sub-pool in megabytes.
31    #[arg(long = "txpool.basefee-max-size", alias = "txpool.basefee_max_size", default_value_t = TXPOOL_SUBPOOL_MAX_SIZE_MB_DEFAULT)]
32    pub basefee_max_size: usize,
33
34    /// Max number of transaction in the queued sub-pool
35    #[arg(long = "txpool.queued-max-count", alias = "txpool.queued_max_count", default_value_t = TXPOOL_SUBPOOL_MAX_TXS_DEFAULT)]
36    pub queued_max_count: usize,
37    /// Max size of the queued sub-pool in megabytes.
38    #[arg(long = "txpool.queued-max-size", alias = "txpool.queued_max_size", default_value_t = TXPOOL_SUBPOOL_MAX_SIZE_MB_DEFAULT)]
39    pub queued_max_size: usize,
40
41    /// Max number of executable transaction slots guaranteed per account
42    #[arg(long = "txpool.max-account-slots", alias = "txpool.max_account_slots", default_value_t = TXPOOL_MAX_ACCOUNT_SLOTS_PER_SENDER)]
43    pub max_account_slots: usize,
44
45    /// Price bump (in %) for the transaction pool underpriced check.
46    #[arg(long = "txpool.pricebump", default_value_t = DEFAULT_PRICE_BUMP)]
47    pub price_bump: u128,
48
49    /// Minimum base fee required by the protocol.
50    #[arg(long = "txpool.minimal-protocol-fee", default_value_t = MIN_PROTOCOL_BASE_FEE)]
51    pub minimal_protocol_basefee: u64,
52
53    /// The default enforced gas limit for transactions entering the pool
54    #[arg(long = "txpool.gas-limit", default_value_t = ETHEREUM_BLOCK_GAS_LIMIT)]
55    pub enforced_gas_limit: u64,
56
57    /// Price bump percentage to replace an already existing blob transaction
58    #[arg(long = "blobpool.pricebump", default_value_t = REPLACE_BLOB_PRICE_BUMP)]
59    pub blob_transaction_price_bump: u128,
60
61    /// Max size in bytes of a single transaction allowed to enter the pool
62    #[arg(long = "txpool.max-tx-input-bytes", alias = "txpool.max_tx_input_bytes", default_value_t = DEFAULT_MAX_TX_INPUT_BYTES)]
63    pub max_tx_input_bytes: usize,
64
65    /// The maximum number of blobs to keep in the in memory blob cache.
66    #[arg(long = "txpool.max-cached-entries", alias = "txpool.max_cached_entries", default_value_t = DEFAULT_MAX_CACHED_BLOBS)]
67    pub max_cached_entries: u32,
68
69    /// Flag to disable local transaction exemptions.
70    #[arg(long = "txpool.nolocals")]
71    pub no_locals: bool,
72    /// Flag to allow certain addresses as local.
73    #[arg(long = "txpool.locals")]
74    pub locals: Vec<Address>,
75    /// Flag to toggle local transaction propagation.
76    #[arg(long = "txpool.no-local-transactions-propagation")]
77    pub no_local_transactions_propagation: bool,
78    /// Number of additional transaction validation tasks to spawn.
79    #[arg(long = "txpool.additional-validation-tasks", alias = "txpool.additional_validation_tasks", default_value_t = DEFAULT_TXPOOL_ADDITIONAL_VALIDATION_TASKS)]
80    pub additional_validation_tasks: usize,
81
82    /// Maximum number of pending transactions from the network to buffer
83    #[arg(long = "txpool.max-pending-txns", alias = "txpool.max_pending_txns", default_value_t = PENDING_TX_LISTENER_BUFFER_SIZE)]
84    pub pending_tx_listener_buffer_size: usize,
85
86    /// Maximum number of new transactions to buffer
87    #[arg(long = "txpool.max-new-txns", alias = "txpool.max_new_txns", default_value_t = NEW_TX_LISTENER_BUFFER_SIZE)]
88    pub new_tx_listener_buffer_size: usize,
89
90    /// How many new pending transactions to buffer and send to in progress pending transaction
91    /// iterators.
92    #[arg(long = "txpool.max-new-pending-txs-notifications", alias = "txpool.max-new-pending-txs-notifications", default_value_t = MAX_NEW_PENDING_TXS_NOTIFICATIONS)]
93    pub max_new_pending_txs_notifications: usize,
94}
95
96impl Default for TxPoolArgs {
97    fn default() -> Self {
98        Self {
99            pending_max_count: TXPOOL_SUBPOOL_MAX_TXS_DEFAULT,
100            pending_max_size: TXPOOL_SUBPOOL_MAX_SIZE_MB_DEFAULT,
101            basefee_max_count: TXPOOL_SUBPOOL_MAX_TXS_DEFAULT,
102            basefee_max_size: TXPOOL_SUBPOOL_MAX_SIZE_MB_DEFAULT,
103            queued_max_count: TXPOOL_SUBPOOL_MAX_TXS_DEFAULT,
104            queued_max_size: TXPOOL_SUBPOOL_MAX_SIZE_MB_DEFAULT,
105            max_account_slots: TXPOOL_MAX_ACCOUNT_SLOTS_PER_SENDER,
106            price_bump: DEFAULT_PRICE_BUMP,
107            minimal_protocol_basefee: MIN_PROTOCOL_BASE_FEE,
108            enforced_gas_limit: ETHEREUM_BLOCK_GAS_LIMIT,
109            blob_transaction_price_bump: REPLACE_BLOB_PRICE_BUMP,
110            max_tx_input_bytes: DEFAULT_MAX_TX_INPUT_BYTES,
111            max_cached_entries: DEFAULT_MAX_CACHED_BLOBS,
112            no_locals: false,
113            locals: Default::default(),
114            no_local_transactions_propagation: false,
115            additional_validation_tasks: DEFAULT_TXPOOL_ADDITIONAL_VALIDATION_TASKS,
116            pending_tx_listener_buffer_size: PENDING_TX_LISTENER_BUFFER_SIZE,
117            new_tx_listener_buffer_size: NEW_TX_LISTENER_BUFFER_SIZE,
118            max_new_pending_txs_notifications: MAX_NEW_PENDING_TXS_NOTIFICATIONS,
119        }
120    }
121}
122
123impl RethTransactionPoolConfig for TxPoolArgs {
124    /// Returns transaction pool configuration.
125    fn pool_config(&self) -> PoolConfig {
126        PoolConfig {
127            local_transactions_config: LocalTransactionConfig {
128                no_exemptions: self.no_locals,
129                local_addresses: self.locals.clone().into_iter().collect(),
130                propagate_local_transactions: !self.no_local_transactions_propagation,
131            },
132            pending_limit: SubPoolLimit {
133                max_txs: self.pending_max_count,
134                max_size: self.pending_max_size.saturating_mul(1024 * 1024),
135            },
136            basefee_limit: SubPoolLimit {
137                max_txs: self.basefee_max_count,
138                max_size: self.basefee_max_size.saturating_mul(1024 * 1024),
139            },
140            queued_limit: SubPoolLimit {
141                max_txs: self.queued_max_count,
142                max_size: self.queued_max_size.saturating_mul(1024 * 1024),
143            },
144            blob_limit: SubPoolLimit {
145                max_txs: self.queued_max_count,
146                max_size: self.queued_max_size.saturating_mul(1024 * 1024),
147            },
148            max_account_slots: self.max_account_slots,
149            price_bumps: PriceBumpConfig {
150                default_price_bump: self.price_bump,
151                replace_blob_tx_price_bump: self.blob_transaction_price_bump,
152            },
153            minimal_protocol_basefee: self.minimal_protocol_basefee,
154            gas_limit: self.enforced_gas_limit,
155            pending_tx_listener_buffer_size: self.pending_tx_listener_buffer_size,
156            new_tx_listener_buffer_size: self.new_tx_listener_buffer_size,
157            max_new_pending_txs_notifications: self.max_new_pending_txs_notifications,
158        }
159    }
160}
161
162#[cfg(test)]
163mod tests {
164    use super::*;
165    use clap::Parser;
166
167    /// A helper type to parse Args more easily
168    #[derive(Parser)]
169    struct CommandParser<T: Args> {
170        #[command(flatten)]
171        args: T,
172    }
173
174    #[test]
175    fn txpool_args_default_sanity_test() {
176        let default_args = TxPoolArgs::default();
177        let args = CommandParser::<TxPoolArgs>::parse_from(["reth"]).args;
178        assert_eq!(args, default_args);
179    }
180
181    #[test]
182    fn txpool_parse_locals() {
183        let args = CommandParser::<TxPoolArgs>::parse_from([
184            "reth",
185            "--txpool.locals",
186            "0x0000000000000000000000000000000000000000",
187        ])
188        .args;
189        assert_eq!(args.locals, vec![Address::ZERO]);
190    }
191}