This document describes the complete transaction management system in fuel-core, covering how transactions are submitted, validated, stored, tracked, and ultimately included in blocks. Transaction management encompasses the transaction pool (mempool), status tracking, validation, and the pre-confirmation system.
For information about transaction execution within blocks, see Transaction Execution. For details about block production that consumes transactions from the pool, see Block Production Pipeline.
Transaction management in fuel-core handles the complete lifecycle of transactions from submission through execution to finalization. The system coordinates several services:
This page documents the high-level architecture and component interactions. Implementation details are covered in child pages: Transaction Lifecycle, Transaction Pool Architecture, Transaction Validation and Assembly, Transaction Status Tracking, and Pre-confirmations System.
The transaction management system consists of several cooperating services orchestrated by FuelService:
Sources:
Transactions enter the system through three primary paths:
Clients submit transactions via GraphQL mutations using the FuelClient SDK or direct API calls:
GraphQL Mutation and Subscription Methods:
submit(tx: HexString!, estimatePredicates: Boolean) - Basic submission returning Transaction! at crates/fuel-core/src/schema/tx.rs647-675submitAndAwait(tx, estimatePredicates) - Subscription returning final status at crates/client/assets/schema.sdl1362submitAndAwaitStatus(tx, estimatePredicates, includePreconfirmation) - Subscription streaming all six states at crates/client/assets/schema.sdl1368Sources:
Transactions received from peer nodes are validated and inserted into the pool:
Sources:
The relayer service processes forced transactions from Ethereum L1. These bypass the transaction pool and are directly included in block production:
Sources:
Transactions progress through six distinct states from submission to finalization:
Transaction Lifecycle: Six States
Six Transaction Status States:
| State # | GraphQL Type | Rust Struct | Key Fields |
|---|---|---|---|
| 1 | SubmittedStatus | transaction_status::statuses::Submitted | timestamp: Tai64 |
| 2 | PreconfirmationSuccessStatus | transaction_status::statuses::PreConfirmationSuccess | tx_pointer: TxPointer, receipts: Option<Arc<Vec<Receipt>>>, resolved_outputs: Option<Arc<Vec<(UtxoId, Output)>>>, total_gas: u64, total_fee: u64 |
| 3 | PreconfirmationFailureStatus | transaction_status::statuses::PreConfirmationFailure | tx_pointer: TxPointer, reason: String, receipts: Option<Arc<Vec<Receipt>>>, total_gas: u64, total_fee: u64 |
| 4 | SuccessStatus | transaction_status::statuses::Success | block_height: BlockHeight, block_timestamp: Tai64, receipts: Arc<Vec<Receipt>>, program_state: Option<ProgramState>, total_gas: u64, total_fee: u64 |
| 5 | FailureStatus | transaction_status::statuses::Failure | block_height: BlockHeight, block_timestamp: Tai64, reason: String, receipts: Arc<Vec<Receipt>>, total_gas: u64, total_fee: u64 |
| 6 | SqueezedOut | transaction_status::statuses::SqueezedOut | reason: String (e.g. "TTL expired", "Dependency error") |
Sources:
The transaction pool manages pending transactions before block inclusion. Implemented in the fuel_core_txpool crate with the main service type TxPool:
Key Responsibilities:
insert() methodPoolLimits constraintsmax_txs_chain_count)minimal_gas_priceextract_transactions_for_block() for block producersConfiguration Structure (from CLI):
Transaction Selection via Constraints:
The extract_transactions_for_block() method uses a Constraints struct:
minimal_gas_price: u64 - Minimum gas price filtermax_gas: u64 - Total gas limit for blockmaximum_txs: u16 - Maximum transaction countmaximum_block_size: u32 - Size limit for blockexcluded_contracts: HashSet<ContractId> - Contracts to excludeSources:
Tracks transaction status changes and provides subscription capabilities for clients to monitor transaction progress.
Key Features:
Configuration:
Status Update Flow:
Sources:
The ExecutorAdapter wraps the underlying Executor to provide transaction validation and dry-run capabilities:
Key Methods:
validate_without_commit(block: &Block) - Validates block execution at crates/services/executor/src/executor.rs467-499dry_run_txs(txs, block_height, utxo_validation, gas_price, record_reads) - Executes transactions without committing at crates/fuel-core/src/schema/tx.rs124-195estimate_predicates(tx: &mut Transaction) - Estimates predicate gas usage at crates/client/src/client.rs851-860Validation Process (via Executor):
forbid_fake_coins = true)fuel-vmDry Run Features:
utxo_validation: Option<bool> - Override UTXO validationgas_price: Option<u64> - Override gas priceblock_height: Option<BlockHeight> - Run at historical height (requires --historical-execution)record_storage_reads: bool - Record storage access for debuggingSources:
When P2P is enabled, this optional service provides early execution feedback during block production:
Operation:
PRECONFIRMATION topic)Key Rotation:
key_rotation_interval)key_expiration_intervalecho_delegation_intervalSources:
Before entering the pool, transactions go through multi-stage validation:
Validation Steps:
fuel_tx::Transaction::from_bytes() at crates/fuel-core/src/schema/tx.rs155-156BlackList config (addresses, coins, messages, contracts)PoolLimits constraints (max_txs, max_gas, max_bytes_size)tx.into_checked() creates CheckedTransaction validating predicates and inputsutxo_validation = true, verify inputs exist and are unspentminimal_gas_price from consensus parametersmax_txs_chain_countError Types:
ConversionError - Deserialization or malformed transactionCheckError - Predicate or input validation failedTransactionValidityError - UTXO, signature, or structural errorsSources:
The GraphQL assembleTx query constructs complete transactions with inputs, outputs, and estimated fees:
Assembly Process:
coins_to_spend() for inputs covering required_balances amountsestimate_gas_price(block_horizon) to get future gas priceOutput::Change outputs per ChangePolicy for each assetOutput::Variable for execution-determined outputsestimate_predicates = true, run predicate estimationAssembleTx Query Parameters:
Return Type:
Sources:
When a transaction is successfully inserted into the pool, it's broadcast to peer nodes:
Gossipsub Topic: NEW_TX
Peer Reputation Impact:
PeerReportConfig)Sources:
Sources:
| Mutation | Description | Returns |
|---|---|---|
submit(tx, estimatePredicates) | Submit transaction to pool | Transaction! |
dryRun(txs, utxoValidation, gasPrice, blockHeight) | Execute without committing | [DryRunTransactionExecutionStatus!]! |
assembleTx(...) | Assemble complete transaction with inputs/outputs | AssembleTransactionResult! |
| Query | Description | Returns |
|---|---|---|
transaction(id) | Get transaction by ID with status | Transaction |
transactions(first, after, last, before) | Paginated transaction list | TransactionConnection! |
transactionsByOwner(owner, ...) | Transactions owned by address | TransactionConnection! |
estimatePredicates(tx) | Estimate predicate gas usage | Transaction! |
| Subscription | Description | Returns |
|---|---|---|
submitAndAwait(tx, estimatePredicates) | Submit and await final status (Success/Failure/SqueezedOut) | Stream of TransactionStatus! |
submitAndAwaitStatus(tx, estimatePredicates, includePreconfirmation) | Submit and stream all six state changes | Stream of TransactionStatus! |
statusChange(id, includePreconfirmation) | Subscribe to status changes for specific transaction | Stream of TransactionStatus! |
alpha__preconfirmations() | Subscribe to all pre-confirmations (alpha feature) | Stream of TransactionStatus! |
Sources:
Transaction-related services are initialized in a specific order during FuelService startup:
Initialization Dependencies:
Sources:
This document provides an overview of transaction management in fuel-core. For detailed implementation of specific subsystems, refer to:
Refresh this wiki