From 82e99880491b8b7a6847995bd9769cc0b12ea138 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sat, 14 Jun 2025 17:44:57 +0200 Subject: [PATCH] docs: document transaction flow into the pool (#16777) --- crates/net/network/src/transactions/mod.rs | 34 ++++++ crates/transaction-pool/src/lib.rs | 127 ++++++++++++++++++++- 2 files changed, 156 insertions(+), 5 deletions(-) diff --git a/crates/net/network/src/transactions/mod.rs b/crates/net/network/src/transactions/mod.rs index 0fdee4a915..78e55c344f 100644 --- a/crates/net/network/src/transactions/mod.rs +++ b/crates/net/network/src/transactions/mod.rs @@ -242,6 +242,40 @@ impl TransactionsHandle { /// /// It can be configured with different policies for transaction propagation and announcement /// filtering. See [`NetworkPolicies`] and [`TransactionPolicies`] for more details. +/// +/// ## Network Transaction Processing +/// +/// ### Message Types +/// +/// - **`Transactions`**: Full transaction broadcasts (rejects blob transactions) +/// - **`NewPooledTransactionHashes`**: Hash announcements +/// +/// ### Peer Tracking +/// +/// - Maintains per-peer transaction cache (default: 10,240 entries) +/// - Prevents duplicate imports and enables efficient propagation +/// +/// ### Bad Transaction Handling +/// +/// Caches and rejects transactions with consensus violations (gas, signature, chain ID). +/// Penalizes peers sending invalid transactions. +/// +/// ### Import Management +/// +/// Limits concurrent pool imports and backs off when approaching capacity. +/// +/// ### Transaction Fetching +/// +/// For announced transactions: filters known → queues unknown → fetches → imports +/// +/// ### Propagation Rules +/// +/// Based on: origin (Local/External/Private), peer capabilities, and network state. +/// Disabled during initial sync. +/// +/// ### Security +/// +/// Rate limiting via reputation, bad transaction isolation, peer scoring. #[derive(Debug)] #[must_use = "Manager does nothing unless polled."] pub struct TransactionsManager< diff --git a/crates/transaction-pool/src/lib.rs b/crates/transaction-pool/src/lib.rs index 8250a8613c..102f0140a0 100644 --- a/crates/transaction-pool/src/lib.rs +++ b/crates/transaction-pool/src/lib.rs @@ -12,6 +12,127 @@ //! - monitoring memory footprint and enforce pool size limits //! - storing blob data for transactions in a separate blobstore on insertion //! +//! ## Transaction Flow: From Network/RPC to Pool +//! +//! Transactions enter the pool through two main paths: +//! +//! ### 1. Network Path (P2P) +//! +//! ```text +//! Network Peer +//! ↓ +//! Transactions or NewPooledTransactionHashes message +//! ↓ +//! TransactionsManager (crates/net/network/src/transactions/mod.rs) +//! │ +//! ├─→ For Transactions message: +//! │ ├─→ Validates message format +//! │ ├─→ Checks if transaction already known +//! │ ├─→ Marks peer as having seen the transaction +//! │ └─→ Queues for import +//! │ +//! └─→ For NewPooledTransactionHashes message: +//! ├─→ Filters out already known transactions +//! ├─→ Queues unknown hashes for fetching +//! ├─→ Sends GetPooledTransactions request +//! ├─→ Receives PooledTransactions response +//! └─→ Queues fetched transactions for import +//! ↓ +//! pool.add_external_transactions() [Origin: External] +//! ↓ +//! Transaction Validation & Pool Addition +//! ``` +//! +//! ### 2. RPC Path (Local submission) +//! +//! ```text +//! eth_sendRawTransaction RPC call +//! ├─→ Decodes raw bytes +//! └─→ Recovers sender +//! ↓ +//! pool.add_transaction() [Origin: Local] +//! ↓ +//! Transaction Validation & Pool Addition +//! ``` +//! +//! ### Transaction Origins +//! +//! - **Local**: Transactions submitted via RPC (trusted, may have different fee requirements) +//! - **External**: Transactions from network peers (untrusted, subject to stricter validation) +//! - **Private**: Local transactions that should not be propagated to the network +//! +//! ## Validation Process +//! +//! ### Stateless Checks +//! +//! Ethereum transactions undergo several stateless checks: +//! +//! - **Transaction Type**: Fork-dependent support (Legacy always, EIP-2930/1559/4844/7702 need +//! activation) +//! - **Size**: Input data ≤ 128KB (default) +//! - **Gas**: Limit ≤ block gas limit +//! - **Fees**: Priority fee ≤ max fee; local tx fee cap; external minimum priority fee +//! - **Chain ID**: Must match current chain +//! - **Intrinsic Gas**: Sufficient for data and access lists +//! - **Blobs** (EIP-4844): Valid count, KZG proofs +//! +//! ### Stateful Checks +//! +//! 1. **Sender**: No bytecode (unless EIP-7702 delegated in Prague) +//! 2. **Nonce**: ≥ account nonce +//! 3. **Balance**: Covers value + (`gas_limit` × `max_fee_per_gas`) +//! +//! ### Common Errors +//! +//! - [`NonceNotConsistent`](reth_primitives_traits::transaction::error::InvalidTransactionError::NonceNotConsistent): Nonce too low +//! - [`InsufficientFunds`](reth_primitives_traits::transaction::error::InvalidTransactionError::InsufficientFunds): Insufficient balance +//! - [`ExceedsGasLimit`](crate::error::InvalidPoolTransactionError::ExceedsGasLimit): Gas limit too +//! high +//! - [`SignerAccountHasBytecode`](reth_primitives_traits::transaction::error::InvalidTransactionError::SignerAccountHasBytecode): EOA has code +//! - [`Underpriced`](crate::error::InvalidPoolTransactionError::Underpriced): Fee too low +//! - [`ReplacementUnderpriced`](crate::error::PoolErrorKind::ReplacementUnderpriced): Replacement +//! transaction fee too low +//! - Blob errors: +//! - [`MissingEip4844BlobSidecar`](crate::error::Eip4844PoolTransactionError::MissingEip4844BlobSidecar): Missing sidecar +//! - [`InvalidEip4844Blob`](crate::error::Eip4844PoolTransactionError::InvalidEip4844Blob): +//! Invalid blob proofs +//! - [`NoEip4844Blobs`](crate::error::Eip4844PoolTransactionError::NoEip4844Blobs): EIP-4844 +//! transaction without blobs +//! - [`TooManyEip4844Blobs`](crate::error::Eip4844PoolTransactionError::TooManyEip4844Blobs): Too +//! many blobs +//! +//! ## Subpool Design +//! +//! The pool maintains four distinct subpools, each serving a specific purpose +//! +//! ### Subpools +//! +//! 1. **Pending**: Ready for inclusion (no gaps, sufficient balance/fees) +//! 2. **Queued**: Future transactions (nonce gaps or insufficient balance) +//! 3. **`BaseFee`**: Valid but below current base fee +//! 4. **Blob**: EIP-4844 transactions not pending due to insufficient base fee or blob fee +//! +//! ### State Transitions +//! +//! Transactions move between subpools based on state changes: +//! +//! ```text +//! Queued ─────────→ BaseFee/Blob ────────→ Pending +//! ↑ ↑ │ +//! │ │ │ +//! └────────────────────┴─────────────────────┘ +//! (demotions due to state changes) +//! ``` +//! +//! **Promotions**: Nonce gaps filled, balance/fee improvements +//! **Demotions**: Nonce gaps created, balance/fee degradation +//! +//! ## Pool Maintenance +//! +//! 1. **Block Updates**: Removes mined txs, updates accounts/fees, triggers movements +//! 2. **Size Enforcement**: Discards worst transactions when limits exceeded +//! 3. **Propagation**: External (always), Local (configurable), Private (never) +//! //! ## Assumptions //! //! ### Transaction type @@ -41,11 +162,7 @@ //! //! ### State Changes //! -//! Once a new block is mined, the pool needs to be updated with a changeset in order to: -//! -//! - remove mined transactions -//! - update using account changes: balance changes -//! - base fee updates +//! New blocks trigger pool updates via changesets (see Pool Maintenance). //! //! ## Implementation details //!