This page documents the FuelService architecture, which serves as the main orchestrator for all node subsystems. It describes how FuelService initializes, manages, and coordinates the lifecycle of sub-services like transaction pool, block producer, P2P networking, and GraphQL API.
For details on individual sub-services, see Sub-Services Overview. For configuration management, see Configuration System. For the underlying service framework, see Service Lifecycle Management.
The FuelService is the central orchestrator that composes and manages all node subsystems. It uses the ServiceRunner<Task> pattern from fuel-core-services to coordinate the lifecycle of independent sub-services, each implementing the RunnableService trait.
Sources: crates/fuel-core/src/service.rs114-130 crates/fuel-core/src/service.rs449-471 crates/fuel-core/src/service/sub_services.rs550-589
The FuelService struct composition at service.rs114-130:
runner: ServiceRunner<Task> - Manages the state machine (NotStarted → Starting → Started → Stopping → Stopped)shared: SharedState - Provides cross-service communication through adapters (see below)sub_services: Arc<SubServices> - Vector of Box<dyn ServiceTrait> containing all initialized servicesbound_address: SocketAddr - The GraphQL API listening addressThe Task struct at service.rs449-471 implements RunnableService and RunnableTask, serving as the execution context for all sub-services.
The SharedState struct implements a mediator pattern that enables loose coupling between services. Rather than services directly depending on each other, they access functionality through adapters stored in SharedState. This pattern allows services to remain independent while still communicating.
The SharedState at service.rs78-112 contains adapters that wrap each service's SharedState or provide ports to their functionality:
Sources: crates/fuel-core/src/service.rs78-112
Each adapter wraps a service's shared state and implements port traits defined by consuming services. Key adapters:
| Adapter | Wraps | Port Implementations | Source |
|---|---|---|---|
ExecutorAdapter | Arc<Executor> + watchers | fuel_core_producer::ports::Executor | adapters/executor.rs |
BlockImporterAdapter | Arc<fuel_core_importer::Importer> | fuel_core_poa::ports::BlockImporter | adapters/block_importer.rs |
TxPoolAdapter | TxPoolSharedState | fuel_core_producer::ports::TxPool | adapters/txpool.rs |
PoAAdapter | Option<fuel_core_poa::service::SharedState> | fuel_core_graphql_api::ports::ConsensusModulePort | adapters.rs312-314 |
P2PAdapter | Option<fuel_core_p2p::service::SharedState> | Multiple P2P ports | adapters/p2p.rs |
Sources: crates/fuel-core/src/service/adapters.rs crates/fuel-core/src/service/sub_services.rs206-404
This indirection enables:
The initialization sequence transforms CLI arguments into a running FuelService instance through several stages.
Sources: bin/fuel-core/src/cli/run.rs805-836 bin/fuel-core/src/cli/run.rs343-795 crates/fuel-core/src/service.rs138-197 crates/fuel-core/src/service/sub_services.rs129-569
The Command::get_config() method consolidates CLI arguments into a Config struct:
| CLI Argument Group | Config Field | Source Code |
|---|---|---|
| GraphQL options | graphql_config: GraphQLConfig | bin/fuel-core/src/cli/run/graphql.rs1-227 |
| Transaction pool | txpool: TxPoolConfig | bin/fuel-core/src/cli/run/tx_pool.rs |
| Gas price service | gas_price_config: GasPriceConfig | bin/fuel-core/src/cli/run/gas_price.rs |
| P2P networking | p2p: Option<P2PConfig> | bin/fuel-core/src/cli/run/p2p.rs |
| Relayer | relayer: Option<RelayerConfig> | bin/fuel-core/src/cli/run/relayer.rs |
| PoA consensus | consensus_signer: SignMode | bin/fuel-core/src/cli/run.rs474-512 |
Sources: bin/fuel-core/src/cli/run.rs343-795
The init_sub_services() function creates all services in a specific order to satisfy dependencies. Services are added to the SubServices vector, and the initialization order determines startup sequence.
Sources: crates/fuel-core/src/service/sub_services.rs129-569
The init_sub_services() function at sub_services.rs133-592 builds the SubServices vector by appending services in dependency order:
Sources: crates/fuel-core/src/service/sub_services.rs550-589
Critical Ordering Constraints:
Before creating services, init_sub_services() creates these adapter instances:
Sources: crates/fuel-core/src/service/adapters.rs crates/fuel-core/src/service/sub_services.rs206-404
Each adapter wraps a service's shared state or functionality to provide a clean interface conforming to port traits defined by consuming services.
The FuelService uses the ServiceRunner infrastructure to manage service state transitions. The lifecycle follows this state machine:
Sources: crates/services/src/state.rs6-47
The Task struct at service.rs449-471 implements RunnableService and RunnableTask to orchestrate all sub-services:
Sources: crates/fuel-core/src/service.rs489-546 crates/services/src/service.rs323-454
Key Orchestration Methods:
| Method | Location | Purpose |
|---|---|---|
into_task() | service.rs489-510 | Sequential startup: starts services, waits for each to reach Started state |
run() | service.rs514-531 | Parallel monitoring: uses select_all() to detect first stop signal from any service |
shutdown() | service.rs533-546 | Sequential teardown: stops all services, then database |
The ReadySignal at service.rs474-476 is sent after all services start, signaling that block production can begin. This prevents the PoA service from attempting to produce blocks before dependencies are ready.
The configuration system uses a layered approach with CLI arguments at the top level and sub-configurations for each service.
Sources: crates/fuel-core/src/service/config.rs64-117 crates/fuel-core/src/service/config.rs366-385
The Config::make_config_consistent() method ensures configuration values are internally consistent:
debug = false, forces utxo_validation = true config.rs290-295txpool.utxo_validation with top-level utxo_validation config.rs297-300Sources: crates/fuel-core/src/service/config.rs289-303
Before starting sub-services, FuelService ensures the database contains a valid genesis block. This happens in the start_and_await() method.
Sources: crates/fuel-core/src/service.rs388-421 crates/fuel-core/src/service.rs350-386
Key genesis operations:
Before initialization, FuelService::make_database_compatible_with_config() validates and potentially modifies the database to match configuration requirements.
For PoAV2 consensus, the method checks if any block at an override height has an invalid signature with the new consensus configuration:
Sources: crates/fuel-core/src/service.rs280-348
If an invalid signature is detected at an override height, the database is rolled back to the previous height service.rs334-344
FuelService exposes these methods for external control and status monitoring:
| Method | Purpose | Return Type |
|---|---|---|
new() | Create service from config and database | anyhow::Result<FuelService> |
new_node() | Create and start service | anyhow::Result<FuelService> |
start_and_await() | Start all services and wait for startup | anyhow::Result<State> |
send_stop_signal() | Signal all services to stop | bool |
await_shutdown() | Wait for shutdown to complete | anyhow::Result<State> |
send_stop_signal_and_await_shutdown() | Stop and wait | anyhow::Result<State> |
state() | Get current service state | State |
await_relayer_synced() | Wait for relayer to sync | anyhow::Result<()> |
await_compression_synced_until() | Wait for compression to reach height | anyhow::Result<()> |
await_gas_price_synced() | Wait for gas price service to sync | anyhow::Result<()> |
Sources: crates/fuel-core/src/service.rs138-445
The typical pattern for using FuelService from the CLI:
1. Parse CLI arguments → Command
2. Command::get_config() → Config
3. CombinedDatabase::from_config() → CombinedDatabase
4. FuelService::new(db, config, shutdown_listener) → FuelService
5. service.start_and_await() → State::Started
6. [Service runs until stop signal]
7. service.await_shutdown() → State::Stopped
Sources: bin/fuel-core/src/cli/run.rs805-863
The FuelService implements Drop to ensure graceful shutdown even if the service is dropped without explicit shutdown:
This ensures that dropping a FuelService instance will signal all sub-services to stop, preventing resource leaks and incomplete shutdowns.
Refresh this wiki