libp2p Host¶
The XE host is a standard libp2p node configured for TCP transport with persistent identity, connection management, and multiple discovery mechanisms.
Host Creation¶
func NewHost(ctx context.Context, port int, dataDir string, version string, enableRelay bool) (host.Host, error)
| Parameter | Description |
|---|---|
port |
TCP listen port (default: 9000) |
dataDir |
Directory for persistent data. If non-empty, the identity key is persisted here. |
version |
Node version string, used in the User-Agent header |
enableRelay |
Enable relay and hole-punching support |
The host listens on all interfaces:
Connection Manager¶
The connection manager keeps the number of active peer connections within bounds:
| Setting | Value |
|---|---|
| Low watermark | 100 peers |
| High watermark | 400 peers |
| Grace period | 1 minute |
When the number of connections exceeds the high watermark, the connection manager begins pruning connections down toward the low watermark. New connections are not pruned within the grace period.
Persistent Identity¶
When dataDir is provided, the host generates an Ed25519 keypair on first run and persists it to {dataDir}/host.key. On subsequent starts, the key is loaded from disk, giving the node a stable peer ID across restarts.
Key Protection
The host key file is written with mode 0600 (owner read/write only). The data directory is created with mode 0700. Losing this key means the node gets a new peer ID on next start.
If dataDir is empty (e.g., in tests), a new ephemeral identity is generated each time.
User-Agent¶
The host identifies itself with:
This appears in the libp2p identify protocol and can be used for version-aware peer selection.
Relay Support¶
When enableRelay is true, the host enables three capabilities:
| Feature | Purpose |
|---|---|
EnableRelay() |
Accept relayed connections through other peers |
EnableRelayService() |
Act as a relay for other peers |
EnableHolePunching() |
NAT traversal via hole-punching |
This allows nodes behind NAT or firewalls to participate in the network by routing connections through relay-capable peers.
Note
Relay is optional and disabled by default. Enable it for nodes that need to be reachable behind NAT without port forwarding.
Discovery¶
mDNS (Local Network)¶
mDNS discovery is started automatically via SetupDiscovery(). It uses the service tag xe-poc and connects to any discovered peer on the local network.
When a peer is found via mDNS, the node connects automatically. Peers with the same peer ID (self) are ignored.
Bootstrap Peers¶
Bootstrap peers are specified via the -dial CLI flag as comma-separated multiaddrs:
The node dials each address on startup with a 10-second timeout per peer. If any connections fail, a background goroutine retries every 10 seconds until all bootstrap peers are connected.
Startup
│
├─ Dial peer A ─── success
├─ Dial peer B ─── fail
│
└─ Start retry loop (every 10s)
├─ Check: A connected? yes, skip
├─ Check: B connected? no, dial again
└─ All connected? → stop loop
Multiaddr Format
A full multiaddr includes the transport and peer ID:
Example:/ip4/192.168.1.10/tcp/9000/p2p/12D3KooWRnBKUEkAgYBMNR...
Kademlia DHT¶
The DHT provides network-wide peer discovery beyond the local network and bootstrap list. See DHT below.
DHT Setup¶
The DHT is configured with:
| Setting | Value |
|---|---|
| Mode | Server (participates in routing) |
| Protocol prefix | /xe |
The /xe protocol prefix ensures XE nodes form their own DHT, isolated from the public IPFS DHT. Server mode means the node stores and serves routing records, not just queries them.
After creation, Bootstrap() is called to populate the routing table from the existing peerstore.
The DHT is used by the Messenger to resolve peer IDs to addresses via FindPeer() when a target peer is not already known.
Peer Dialing¶
The DialPeer function connects to a peer given a multiaddr string:
The ParsePeerAddr helper extracts peer address info from a multiaddr:
Configuration Summary¶
| CLI Flag | Default | Description |
|---|---|---|
-port |
9000 |
TCP listen port for libp2p |
-data |
./data |
Data directory (identity key stored here) |
-dial |
(none) | Comma-separated bootstrap multiaddrs |
Lifecycle¶
- Create host --
NewHost()sets up TCP transport, connection manager, and identity - Start mDNS --
SetupDiscovery()enables local network discovery - Bootstrap DHT --
SetupDHT()creates and bootstraps the Kademlia DHT - Dial bootstrap peers --
bootstrapWithRetry()connects to known peers with retry - Register protocols -- Sync, messaging, and gossip handlers are registered on the host
- Shutdown -- Host is closed, all streams and connections are terminated