Jesse A. Green / notebook

Fuel Core User Guide

Generated May 2026 from FuelLabs/fuel-core at c453f81

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

1. Quick Start

Fuel Core is the official Rust implementation of the Fuel protocol — a high-performance, UTXO-based blockchain execution layer designed for modular blockchain architectures. It runs the FuelVM, a purpose-built virtual machine optimized for parallel transaction execution with a fraud-provable design.

Key features:

  • UTXO-based transaction model enabling parallel execution
  • FuelVM execution environment with native multi-asset support
  • GraphQL API for querying blockchain state and submitting transactions
  • Peer-to-peer networking via libp2p for block and transaction propagation
  • Proof-of-Authority (PoA) consensus with configurable block production triggers
  • Ethereum L1 relayer for cross-chain message bridging
  • RocksDB-backed persistent storage with historical state access
  • WASM-based upgradable executor for forkless protocol upgrades

Prerequisites: Rust 1.93.0+, clang/llvm (for RocksDB), and a chain configuration snapshot.

Fastest way to start a local node:

cargo run -p fuel-core-bin -- run --db-type in-memory
GraphQL API listening on 127.0.0.1:4000

Tip

For quick experimentation, use --db-type in-memory to skip RocksDB setup entirely. State is lost on restart but startup is instant.

What to try next: Query the node health at http://127.0.0.1:4000/v1/playground using the built-in GraphiQL interface, or submit a transaction via the fuel-core-client crate.

2. Installation

System Requirements

Requirement Minimum Recommended
Rust toolchain 1.93.0 Latest stable
OS Linux, macOS, Windows Linux (Ubuntu 22.04+)
RAM 4 GB 16 GB+ (production)
Disk 10 GB 100 GB+ SSD (production with RocksDB)
CPU 2 cores 4+ cores

Building from Source

git clone https://github.com/FuelLabs/fuel-core.git
cd fuel-core
cargo build -p fuel-core-bin --release
Compiling fuel-core-bin v0.48.0
    Finished release [optimized] target(s)

Important

The default build includes RocksDB support, which requires clang and llvm development libraries. On Ubuntu: apt install clang llvm libclang-dev. On macOS: xcode-select --install.

Production Build

For production deployments, enable jemalloc for improved memory performance:

cargo build -p fuel-core-bin --release --features rocksdb-production

Feature Flags

Feature Description Default
rocksdb RocksDB persistent storage Yes
rocksdb-production RocksDB with jemalloc allocator No
p2p Peer-to-peer networking via libp2p No
relayer Ethereum L1 relayer for bridge messages No
wasm-executor WASM upgradable executor No
rpc Block aggregator RPC/gRPC API No
shared-sequencer Shared sequencer integration (Cosmos SDK) No

Post-Install Verification

./target/release/fuel-core --version
fuel-core 0.48.0
./target/release/fuel-core run --db-type in-memory &
curl -s http://127.0.0.1:4000/v1/health
true

Warning

If building on ARM (aarch64), use the provided cross-compilation Dockerfiles in ci/Dockerfile.aarch64-unknown-linux-gnu-clang for reproducible builds.

Key Generation

Generate cryptographic keys for block production or P2P peering:

./target/release/fuel-core-keygen new --key-type block-production
{
  "secret": "0x...",
  "address": "0x...",
  "type": "block-production"
}
./target/release/fuel-core-keygen new --key-type peering
{
  "secret": "0x...",
  "peer_id": "16Uiu2HAm...",
  "type": "p2p"
}

Caution

Store generated secret keys securely. The block production key controls consensus authority. Never commit secrets to version control.

Derive Address from Existing Secret

./target/release/fuel-core-keygen parse --key-type block-production --secret 0xYOUR_SECRET_KEY
{
  "address": "0x...",
  "type": "block-production"
}

3. Configuration

Fuel Core uses a chain configuration snapshot for genesis state and consensus parameters. The node is configured primarily through CLI flags.

Chain Configuration

The chain configuration defines the genesis state and consensus rules. It consists of:

File Purpose
chain_config.json Chain name, consensus parameters, state transition bytecode, consensus type (PoA/PoAV2)
state_config.json Genesis coins, contracts, messages, blobs
metadata.json Chain height, DA height metadata

Consensus Modes

Mode CLI Value Behavior
Instant instant Produce a block as soon as transactions arrive (development)
Interval interval { block_time } Produce blocks at fixed time intervals (production)
Never N/A Passive listener — does not produce blocks (follower node)

Essential CLI Flags

Flag Type Description
--db-type rocks-db | in-memory Storage backend
--db-path Path RocksDB database directory
--ip Address GraphQL API bind address (default: 127.0.0.1)
--port u16 GraphQL API port (default: 4000)
--snapshot Path Path to chain configuration snapshot directory
--utxo-validation bool Enable UTXO existence validation
--debug bool Enable debug endpoints (VM debugger)

Note

For full configuration reference including P2P, relayer, gas price, GraphQL tuning, and advanced settings, see the Admin Guide.

Minimal Local Development Configuration

fuel-core run \
  --db-type in-memory \
  --debug \
  --snapshot ./path/to/chain-config

Connecting to an Existing Network

To sync with an existing Fuel network, you need the network's chain configuration snapshot and at least one bootstrap peer:

fuel-core run \
  --db-type rocks-db \
  --db-path /data/fuel-core \
  --snapshot ./chain-config \
  --keypair $P2P_SECRET \
  --reserved-nodes /dns4/bootstrap.fuel.network/tcp/30333/p2p/$PEER_ID

Tip

Use --reserved-nodes to specify bootstrap peers. The node discovers additional peers through the Kademlia DHT once connected.

4. Core Usage

Interacting via GraphQL

Fuel Core exposes a GraphQL API as its primary interface. Access the GraphiQL playground at http://<host>:<port>/v1/playground.

Check Node Health

query {
  health
}
{
  "data": {
    "health": true
  }
}

Query Node Information

query {
  nodeInfo {
    utxoValidation
    vmBacktrace
    maxTx
    maxDepth
    nodeVersion
    peers {
      id
      blockHeight
    }
  }
}

Query Chain Information

query {
  chain {
    name
    latestBlock {
      header {
        height
        time
      }
    }
    consensusParameters {
      version
    }
  }
}

Submit a Transaction

mutation {
  submit(tx: "0x...hex-encoded-transaction...") {
    id
  }
}

Warning

When --utxo-validation is enabled, the node validates that all input UTXOs exist and are unspent before accepting a transaction. Transactions referencing consumed UTXOs are rejected.

Query Transaction Status

query {
  transaction(id: "0x...tx_id...") {
    status {
      ... on SuccessStatus {
        blockHeight
      }
      ... on FailureStatus {
        reason
      }
      ... on SubmittedStatus {
        time
      }
    }
  }
}

Subscribe to Transaction Status Changes

subscription {
  statusChange(id: "0x...tx_id...") {
    ... on SubmittedStatus { time }
    ... on SuccessStatus { blockHeight }
    ... on FailureStatus { reason }
  }
}

Note

Subscriptions use Server-Sent Events (SSE). The fuel-core-client crate handles reconnection automatically when using the subscriptions feature.

Query Account Balance

query {
  balance(owner: "0x...address...", assetId: "0x...asset_id...") {
    amount
  }
}

List Coins (UTXOs)

query {
  coins(filter: { owner: "0x...address..." }, first: 10) {
    nodes {
      utxoId
      amount
      assetId
    }
  }
}

Using the Rust Client

The fuel-core-client crate provides a typed Rust client for the GraphQL API:

use fuel_core_client::client::FuelClient;

let client = FuelClient::new("http://127.0.0.1:4000").unwrap();
let health = client.health().await.unwrap();
assert!(health);

The client supports pagination via cursor-based ConnectionArgs with first/after (forward) or last/before (backward) parameters.

VM Debugger (Debug Mode)

When running with --debug, interactive VM debugging is available via GraphQL mutations:

  1. Start a debug session:

    mutation { startSession }
    
  2. Load and execute a transaction:

    mutation { startTx(id: $sessionId, txJson: "...") { breakpoint jsonReceipts } }
    
  3. Set breakpoints on a contract:

    mutation { setBreakpoint(id: $sessionId, breakpoint: { contract: "0x...", pc: 10 }) }
    
  4. Step through execution:

    mutation { setSingleStepping(id: $sessionId, enable: true) }
    mutation { continueTx(id: $sessionId) { breakpoint jsonReceipts } }
    
  5. Inspect VM state:

    query { register(id: $sessionId, register: 16) }
    query { memory(id: $sessionId, start: 0, size: 256) }
    
  6. End session:

    mutation { endSession(id: $sessionId) }
    

Caution

Debug mode exposes full VM state inspection. Never enable --debug on production nodes — it allows arbitrary transaction execution replay and memory inspection.

5. Common Tasks

Run a Local Development Node

Goal: Start a local node for smart contract development.

Steps:

  1. Build fuel-core with default features
  2. Start the node:
    fuel-core run \
      --db-type in-memory \
      --debug \
      --utxo-validation
    

Verify: Query http://127.0.0.1:4000/v1/health returns true.

Run a Persistent Node

Goal: Run a node with data that survives restarts.

Steps:

  1. Create a data directory: mkdir -p /var/lib/fuel-core/db
  2. Start the node:
    fuel-core run \
      --db-type rocks-db \
      --db-path /var/lib/fuel-core/db \
      --snapshot /etc/fuel-core/chain-config
    

Verify: Check that /var/lib/fuel-core/db contains RocksDB files after the first block.

If it fails: Ensure the --db-path directory exists and is writable. Check that the chain configuration snapshot at --snapshot contains valid chain_config.json and state_config.json.

Query Gas Price

Goal: Get the current gas price for transaction fee estimation.

query {
  latestGasPrice {
    gasPrice
    blockHeight
  }
}

To estimate gas price at a future block:

query {
  estimateGasPrice(blockHorizon: 10) {
    gasPrice
  }
}

Dry-Run a Transaction

Goal: Simulate a transaction without committing it to the chain.

mutation {
  dryRun(tx: "0x...hex-encoded-tx...", utxoValidation: true) {
    ... on SuccessStatus {
      totalGas
      totalFee
    }
    receipts {
      receiptType
      data
    }
  }
}

Tip

Use dry-run to estimate gas costs before submitting. The utxoValidation parameter can be set independently of the node's global --utxo-validation flag.

Query Block Details

query {
  block(height: "100") {
    header {
      height
      time
      daHeight
      transactionsCount
    }
    transactions {
      id
    }
  }
}

Query Cross-Chain Messages

query {
  messages(owner: "0x...address...", first: 10) {
    nodes {
      sender
      recipient
      amount
      data
      daHeight
    }
  }
}

Query Contract State

query {
  contract(id: "0x...contract_id...") {
    bytecode
    salt
  }
}

Query DA Compressed Blocks

When the compression service is active, retrieve DA-compressed block data:

query {
  daCompressedBlock(height: "100") {
    bytes
  }
}

Run Benchmarks

Goal: Generate gas cost data for the FuelVM.

Steps:

  1. Run benchmarks:
    cargo bench -p fuel-core-benches
    
  2. Collect gas cost output:
    cargo criterion -p fuel-core-benches --message-format json --bench vm > bench.json
    cargo run -p fuel-core-benches --bin collect --release -- --input bench.json
    
Generated gas-costs.yaml

Note

Benchmarks require the rocksdb and rocksdb-production features enabled (default). See benches/README.md for profiling with flamegraphs.

6. Troubleshooting

Diagnostic Decision Tree

Node won't start?
├── Missing chain config? → Provide --snapshot path
├── RocksDB error? → Check --db-path permissions and disk space
├── Port in use? → Change --port or stop conflicting process
└── Version mismatch? → Ensure chain config matches fuel-core version

Transactions rejected?
├── UTXO not found? → UTXO was already spent or doesn't exist
├── Gas too low? → Query latestGasPrice and increase max_fee
├── Blacklisted? → Input address/UTXO/contract is blacklisted in txpool
├── Pool full? → Pool limits reached; retry with higher tip
└── Mint disallowed? → Only coinbase transactions can use Mint type

Node not syncing?
├── No peers? → Check --reserved-nodes and P2P port accessibility
├── Wrong chain? → Ensure chain config checksum matches network
└── Relayer behind? → Wait for Ethereum finality (~13 min)

Error: Failed to create FuelClient. No URL is provided.

Cause: The FuelClient was constructed without specifying a URL.

Solution:

let client = FuelClient::new("http://127.0.0.1:4000").unwrap();

Prevention: Always pass the GraphQL endpoint URL when constructing FuelClient.

Error: unable to produce blocks without a consensus key

Cause: The node is configured for block production (instant or interval trigger) but no signing key was provided.

Solution:

  1. Generate a key: fuel-core-keygen new --key-type block-production
  2. Pass it via the --consensus-key CLI flag

Prevention: Always configure a consensus key when using block production triggers.

Error: Block production timed out

Cause: Block production exceeded the configured timeout, typically due to slow transaction execution or database I/O.

Solution:

  1. Check disk I/O performance
  2. Reduce the number of transactions per block
  3. Verify the gas limit is not set excessively high

Error: Maximum number of subscriptions reached

Cause: The transaction status manager has reached its subscription limit.

Solution:

  1. Close unused subscriptions
  2. Increase the subscription limit in node configuration

Prevention: Clean up subscription handles in client code after receiving terminal status updates (Success or Failure).

Error: Database doesn't have a height to rollback

Cause: Attempted to roll back the database to a height that doesn't exist in the history.

Solution:

  1. Check the current database height via GraphQL
  2. Only roll back to heights within the available history window

Error: InvalidDatabaseVersion { expected, found }

Cause: The database was created with an incompatible version of fuel-core.

Solution:

  1. Back up the existing database
  2. Re-sync from genesis with the correct fuel-core version

Prevention: Always use matching fuel-core versions with existing databases. Protocol upgrades use the WASM executor for forkless transitions.

Warning

Database version mismatches cannot be resolved by simply upgrading the binary. A re-sync from the chain configuration snapshot is required.

Error: The block timestamp should monotonically increase

Cause: Attempted to produce a block with a timestamp earlier than or equal to the previous block.

Solution: Ensure system clock is synchronized and not drifting backward. Use NTP on production nodes.

Prevention: Run ntpd or chronyd to keep system time accurate.

P2P Connection Issues

Cause: Node cannot connect to peers.

Solution:

  1. Ensure the P2P port is accessible (not firewalled)
  2. Verify --keypair is set with a valid P2P secret key
  3. Check that --reserved-nodes contains valid multiaddr strings
  4. Verify the chain config checksum matches the network

Prevention: Use DNS-based multiaddrs for bootstrap nodes to handle IP changes.

Tip

Enable RUST_LOG=fuel_core_p2p=debug to see detailed P2P connection diagnostics.

Error: Failed to acquire the production lock, block production is already in progress

Cause: A new block production request was made while another is still executing.

Solution: Wait for the current block production to complete. This is normal under high load.

Prevention: This is a concurrency guard — the system handles it automatically.

7. FAQ

Q: What database backends does fuel-core support?

Fuel Core supports two backends: RocksDB (persistent, production-ready) and in-memory (ephemeral, for development/testing). Use --db-type rocks-db or --db-type in-memory to select.

Q: What is the difference between PoA and PoAV2 consensus?

PoA (V1) uses a single signing key for block production. PoAV2 extends this with height-based consensus parameter overrides, enabling protocol parameter changes at specific block heights without code changes.

Q: How does the WASM executor enable forkless upgrades?

The upgradable executor can load state transition logic from WASM bytecode stored on-chain. When an Upgrade transaction is included, nodes automatically switch to executing the new WASM bytecode — no binary update or hard fork required. The WASM executor is designed for one block execution per instance.

Q: What is the Ethereum relayer?

The relayer monitors the Fuel bridge contract on Ethereum (FuelMessagePortal), downloading finalized log events. It tracks MessageSent and Transaction events. Messages and relayed transactions become available to the Fuel chain after Ethereum finality (~13 minutes / ~100 blocks). The relayer uses a configurable log_page_size (default 10,000) for batch fetching.

Q: How is gas pricing determined?

Fuel Core supports both static and dynamic gas pricing. The static algorithm returns a fixed price. The dynamic algorithm (v1) uses a cumulative percentage-based model that adjusts based on L2 block utilization and DA layer recording costs. Query current prices via the latestGasPrice GraphQL endpoint.

Q: Can I run a node without P2P?

Yes. P2P is an optional feature flag. Without it, the node operates standalone — useful for local development, testing, and single-validator setups.

Q: What transaction types are supported?

Fuel Core supports six transaction types: Script (execute code), Create (deploy contracts), Mint (coinbase/block reward), Upgrade (protocol upgrades), Upload (upload bytecode chunks), and Blob (store arbitrary data).

Q: How do I monitor node health in production?

Query the /v1/health HTTP endpoint or use the GraphQL health query. Fuel-core exposes Prometheus-compatible metrics via the fuel-core-metrics subsystem covering GraphQL query costs, P2P peer counts, txpool sizes, block import times, gas price updates, and PoA block production timing.

Q: What is the block aggregator API?

The block aggregator API (enabled with --features rpc) provides a gRPC/protobuf interface for efficient block data retrieval, with support for S3-backed remote caching and compressed block storage for DA layer submission.

Q: What is the shared sequencer?

The shared sequencer service (enabled with --features shared-sequencer) integrates with a Cosmos SDK-based shared sequencer chain via Tendermint RPC, enabling cross-rollup ordering of transactions.

Q: How does the transaction pool work?

The txpool (v2) manages pending transactions with configurable limits on count, total gas, and byte size. It supports dependency chain tracking via petgraph, collision detection, TTL-based expiration, and a blacklist system for addresses, UTXOs, message nonces, and contract IDs. Transactions are selected using a ratio-based tip/gas algorithm.