docs: document transaction flow into the pool (#16777)

This commit is contained in:
Matthias Seitz
2025-06-14 17:44:57 +02:00
committed by GitHub
parent 4e97f48182
commit 82e9988049
2 changed files with 156 additions and 5 deletions

View File

@@ -242,6 +242,40 @@ impl<N: NetworkPrimitives> TransactionsHandle<N> {
///
/// 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<

View File

@@ -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
//!