# How the P2P Networking Service in Fuel Core Facilitates Node Communication

> Discover how the P2P networking service in Fuel Core uses libp2p for efficient node communication, including gossip transactions and data requests on demand.

- Repository: [Fuel Labs/fuel-core](https://github.com/FuelLabs/fuel-core)
- Tags: internals
- Published: 2026-03-06

---

**The P2P networking service in Fuel Core leverages libp2p to combine Gossipsub broadcasting, request-response protocols, and peer reputation management, enabling nodes to discover each other, gossip transactions efficiently, and request specific blockchain data on demand.**

The P2P networking service in Fuel Core serves as the communication backbone that allows blockchain nodes to form a decentralized network. Built on the robust libp2p framework, this service abstracts low-level networking complexity into the `FuelP2PService`, which orchestrates peer discovery, message propagation, and direct data queries through three complementary primitives: Gossipsub for broadcasting, request-response for targeted queries, and peer management for network health.

## Core Service Architecture

### FuelP2PService – The Runtime Component

At the heart of the system lies `FuelP2PService`, defined in [`crates/services/p2p/src/p2p_service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/p2p/src/p2p_service.rs). This struct encapsulates the libp2p `Swarm` and manages all active connections, pending requests, and protocol handlers.

```rust
pub struct FuelP2PService {
    pub local_peer_id: PeerId,
    local_address: std::net::IpAddr,
    tcp_port: u16,
    swarm: Swarm<FuelBehaviour>,
    outbound_requests_table: HashMap<OutboundRequestId, ResponseSender>,
    inbound_requests_table:  HashMap<InboundRequestId, ResponseChannel<V2ResponseMessage>>,
    gossipsub_codec: GossipsubMessageHandler<PostcardCodec>,
    network_metadata: NetworkMetadata,
    metrics: bool,
    libp2p_metrics_registry: Option<Metrics>,
    peer_manager: PeerManager,
}

```

*Source: [`crates/services/p2p/src/p2p_service.rs#L4-L45`](https://github.com/FuelLabs/fuel-core/blob/master/crates/services/p2p/src/p2p_service.rs#L4-L45)*

The `Swarm` wraps `FuelBehaviour`, which bundles the Gossipsub and request-response protocols. The `peer_manager` field tracks all known peers, their multi-addresses, and reputation scores, while the `outbound_requests_table` maps pending request IDs to response channels for asynchronous handling.

### FuelBehaviour – Wiring libp2p Protocols

`FuelBehaviour`, located in [`crates/services/p2p/src/behavior.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/p2p/src/behavior.rs), implements the `NetworkBehaviour` trait and composes the specific protocol handlers:

| Field | Protocol | Purpose |
|-------|----------|---------|
| `gossipsub` | `libp2p::gossipsub::Behaviour` | Scalable broadcast of transactions and pre-confirmations |
| `request_response` | `libp2p::request_response::Behaviour` | Direct query/response for specific data like block headers |
| `identify` | `libp2p::identify::Behaviour` | Exchange peer identity and observed addresses |
| `heartbeat` | Custom heartbeat task | Propagate block height and monitor peer liveness |

These sub-behaviours emit events that `FuelP2PService` translates into internal `FuelP2PEvent` variants, such as `GossipsubMessage`, `PeerConnected`, and `PeerInfoUpdated`.

*Source: [[`crates/services/p2p/src/behavior.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/p2p/src/behavior.rs)](https://github.com/FuelLabs/fuel-core/blob/master/crates/services/p2p/src/behavior.rs)*

## Communication Primitives and Flows

### Gossipsub Broadcasting

The Gossipsub protocol enables efficient propagation of transactions and consensus messages across the network without requiring direct connections to every peer.

When a node needs to broadcast a transaction, the orchestrator sends a `TaskRequest::BroadcastTransaction` containing an `Arc<Transaction>`. The `FuelP2PService` encodes the transaction using the `PostcardCodec` (specified in `gossipsub_codec`) and publishes it to the **`Transaction`** gossipsub topic. Peers receive the message via `FuelP2PEvent::GossipsubMessage`, validate the content, and either accept it into their transaction pool or ignore it based on `GossipsubMessageAcceptance`.

*Key implementation details*:

- Publishing logic in [`service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/service.rs) handling `TaskRequest::BroadcastTransaction`
- Message validation in [`p2p_service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/p2p_service.rs) within `handle_gossip_message`

### Request-Response Direct Queries

For targeted data retrieval, such as fetching specific block headers or transaction pools, Fuel Core uses libp2p's request-response protocol. This creates a direct communication channel between nodes for synchronous data exchange.

Consider fetching a range of sealed block headers:

```rust
TaskRequest::GetSealedHeaders {
    block_height_range,
    channel: on_response,
}

```

The flow proceeds as follows:

1. The orchestrator creates a `RequestMessage` describing the desired block range
2. `FuelP2PService` selects an appropriate peer via `PeerManager` and sends the request through the `request_response` behaviour
3. The remote node processes the request and replies with `V2ResponseMessage` containing serialized `SealedBlockHeader` objects
4. The response is matched in `outbound_requests_table` and forwarded to the original caller via the `OnResponseWithPeerSelection` channel

*Key implementation details*:

- Request creation in [`service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/service.rs) (lines approximately 140-148)
- Outbound request handling in [`p2p_service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/p2p_service.rs) within `handle_outbound_request`

### Peer Discovery and Reputation Management

Maintaining a healthy network requires robust peer discovery and reputation tracking. Fuel Core implements several mechanisms to ensure nodes connect to reliable peers and isolate malicious actors.

**Bootstrap and Discovery**: At startup, `FuelP2PService::new` receives a list of bootstrap multi-addresses, often DNS-based, to establish initial connections. The libp2p `identify` protocol then exchanges peer identities and observed addresses, populating `PeerInfo` structures that include `client_version` and network metadata.

**Heartbeat Protocol**: Nodes periodically gossip `BlockHeightHeartbeatData` messages containing their current block height. Receiving nodes update the corresponding `PeerInfo` fields, allowing the network to track synchronization status and detect stalled peers.

**Reputation and Punishment**: The `PeerManager` maintains reputation scores for all connected peers. When a peer sends malformed messages or violates protocol rules, `PeerManager::report_peer` penalizes their score. Severe or repeated violations trigger the `Punisher` implementation, which invokes `Swarm::behaviour_mut().block_peer` to ban the peer from future connections.

*Key files*:

- [`crates/services/p2p/src/peer_manager.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/p2p/src/peer_manager.rs) – Peer tracking and reputation logic
- [`crates/services/p2p/src/heartbeat.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/p2p/src/heartbeat.rs) – Block height heartbeat encoding/decoding

## Practical Code Examples

### Starting a Fuel Core Node with P2P Enabled

To initialize the networking service, configure the bootstrap nodes and local address, then instantiate `FuelP2PService`:

```rust
let config = Config::load_from_path("config.toml")?;
let mut p2p_service = FuelP2PService::new(
    config.p2p.clone(),          // includes bootstrap nodes and optional metrics flag
    config.network.clone(),      // local address / port
    &metrics_registry,           // libp2p metrics (optional)
)?;
let runner = Service::<_, _>::new(p2p_service, shared_state);
runner.run().await?;

```

*Relevant constructor*: [`p2p_service.rs#L880-L900`](https://github.com/FuelLabs/fuel-core/blob/master/crates/services/p2p/src/p2p_service.rs#L880-L900)

### Broadcasting a Transaction

Submit a transaction to the network for propagation:

```rust
let tx = Arc::new(transaction);
service.send(TaskRequest::BroadcastTransaction(tx)).await?;

```

*Handling*: [`service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/service.rs) matches `TaskRequest::BroadcastTransaction` and forwards to Gossipsub.

### Requesting Recent Block Headers

Fetch specific block ranges from peers using the request-response protocol:

```rust
let (sender, receiver) = oneshot::channel();
service.send(TaskRequest::GetSealedHeaders {
    block_height_range: 1000..1010,
    channel: OnResponseWithPeerSelection::new(sender),
}).await?;

let result: Result<Vec<SealedBlockHeader>, _> = receiver.await?;

```

*Corresponding request routing* is in `p2p_service.rs::handle_get_sealed_headers`.

### Subscribing to New Peers

Monitor peer join events for transaction pool management:

```rust
let (sub_tx, mut sub_rx) = broadcast::channel(64);
service.subscribe_new_peers(sub_tx)?;
while let Ok(peer_id) = sub_rx.recv().await {
    println!("New peer joined: {}", peer_id);
}

```

*Subscription* is implemented via `FuelP2PEvent::NewSubscription` in [`service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/service.rs).

## Summary

- **FuelP2PService** acts as the central orchestrator, wrapping libp2p's `Swarm` and managing all peer connections through [`crates/services/p2p/src/p2p_service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/p2p/src/p2p_service.rs).
- **Three communication primitives** power the network: Gossipsub for scalable broadcasting, request-response for direct data queries, and peer management with heartbeats for network health.
- **Message serialization** uses the `PostcardCodec` for efficient on-wire representation of transactions, block headers, and heartbeat data.
- **Reputation and security** are enforced by the `PeerManager`, which tracks peer scores and bans malicious actors through the `Punisher` implementation.

## Frequently Asked Questions

### How does Fuel Core handle transaction broadcasting between nodes?

Fuel Core uses the **Gossipsub** protocol to broadcast transactions efficiently across the network. When a node receives a new transaction, `FuelP2PService` encodes it using `PostcardCodec` and publishes it to the `Transaction` gossip topic. Peers receive these messages via `FuelP2PEvent::GossipsubMessage`, validate them, and either accept them into their transaction pool or ignore them based on validation results.

### What mechanism does Fuel Core use to request specific blockchain data from peers?

For targeted data retrieval, Fuel Core implements a **request-response** protocol using libp2p's `request_response::Behaviour`. When a node needs specific data like block headers, it sends a `TaskRequest::GetSealedHeaders` (or similar) through `FuelP2PService`. The service selects an appropriate peer via `PeerManager`, sends the request, and routes the `V2ResponseMessage` back to the original caller through an asynchronous channel.

### How does Fuel Core maintain peer reputation and ban malicious nodes?

Fuel Core maintains peer reputation through the **PeerManager** struct defined in [`crates/services/p2p/src/peer_manager.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/p2p/src/peer_manager.rs). The manager tracks reputation scores for all connected peers. When a peer sends malformed messages or violates protocol rules, the system calls `PeerManager::report_peer` to penalize their score. For severe or repeated violations, the `Punisher` implementation invokes `Swarm::behaviour_mut().block_peer` to permanently ban the peer from future connections.

### What is the role of heartbeats in Fuel Core's P2P networking service?

Heartbeats serve as a liveness and synchronization mechanism within the P2P networking service. Nodes periodically broadcast `BlockHeightHeartbeatData` messages containing their current block height. These messages propagate through the network, allowing peers to update their `PeerInfo` records with the latest block height data from each connection. This enables nodes to detect stalled peers, measure network synchronization status, and make informed decisions when selecting peers for data requests.