mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-02-04 03:55:22 -05:00
docs: document transaction flow into the pool (#16777)
This commit is contained in:
@@ -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<
|
||||
|
||||
@@ -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
|
||||
//!
|
||||
|
||||
Reference in New Issue
Block a user