| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Network.LibP2P
Description
libp2p-hs: Haskell implementation of the libp2p networking stack.
This is the public API facade for the library. Import this module for the common types and functions needed to build a libp2p node:
import Network.LibP2P main :: IO () main = do (pid, kp) <- generateAndPeerId sw <- newSwitch pid kp tcp <- newTCPTransport addTransport sw tcp registerIdentifyHandlers sw registerPingHandler sw addrs <- switchListen sw defaultConnectionGater [fromText "ip4127.0.0.1tcp0"] print addrs -- ... dial other peers, etc. switchClose sw
Synopsis
- data PeerId
- data KeyPair
- generateKeyPair :: IO (Either String KeyPair)
- fromPublicKey :: PublicKey -> PeerId
- peerIdBytes :: PeerId -> ByteString
- toBase58 :: PeerId -> Text
- parsePeerId :: Text -> Either String PeerId
- toCIDv1 :: PeerId -> Text
- newtype Multiaddr = Multiaddr [Protocol]
- data Protocol
- = IP4 !Word32
- | IP6 !ByteString
- | TCP !Word16
- | UDP !Word16
- | P2P !ByteString
- | QuicV1
- | WS
- | WSS
- | DNS !Text
- | DNS4 !Text
- | DNS6 !Text
- | DNSAddr !Text
- | P2PCircuit
- | WebTransport
- | NoiseProto
- | YamuxProto
- splitP2P :: Multiaddr -> Maybe (Multiaddr, PeerId)
- toText :: Multiaddr -> Text
- fromText :: Text -> Either String Multiaddr
- data Switch
- newSwitch :: PeerId -> KeyPair -> IO Switch
- addTransport :: Switch -> Transport -> IO ()
- switchListen :: Switch -> ConnectionGater -> [Multiaddr] -> IO [Multiaddr]
- switchListenAddrs :: Switch -> IO [Multiaddr]
- switchClose :: Switch -> IO ()
- dial :: Switch -> PeerId -> [Multiaddr] -> IO (Either DialError Connection)
- data DialError
- setStreamHandler :: Switch -> ProtocolId -> StreamHandler -> IO ()
- removeStreamHandler :: Switch -> ProtocolId -> IO ()
- data StreamIO = StreamIO {
- streamWrite :: ByteString -> IO ()
- streamReadByte :: IO Word8
- streamClose :: IO ()
- type StreamHandler = StreamIO -> PeerId -> IO ()
- type ProtocolId = Text
- data Connection = Connection {
- connPeerId :: !PeerId
- connDirection :: !Direction
- connLocalAddr :: !Multiaddr
- connRemoteAddr :: !Multiaddr
- connSecurity :: !ProtocolId
- connMuxer :: !ProtocolId
- connSession :: !MuxerSession
- connState :: !(TVar ConnState)
- data Transport = Transport {
- transportDial :: !(Multiaddr -> IO RawConnection)
- transportListen :: !(Multiaddr -> IO Listener)
- transportCanDial :: !(Multiaddr -> Bool)
- newTCPTransport :: IO Transport
- data ConnectionGater = ConnectionGater {
- gateAccept :: !(Multiaddr -> IO Bool)
- gateSecured :: !(PeerId -> IO Bool)
- defaultConnectionGater :: ConnectionGater
- registerIdentifyHandlers :: Switch -> IO ()
- requestIdentify :: Connection -> IO (Either String IdentifyInfo)
- registerPingHandler :: Switch -> IO ()
- sendPing :: Connection -> IO (Either PingError PingResult)
- data PingResult = PingResult {}
- data PingError
- data GossipSubNode = GossipSubNode {
- gsnRouter :: !GossipSubRouter
- gsnSwitch :: !Switch
- gsnHeartbeat :: !(TVar (Maybe (Async ())))
- gsnStreams :: !(TVar (Map PeerId StreamIO))
- data GossipSubParams = GossipSubParams {
- paramD :: !Int
- paramDlo :: !Int
- paramDhi :: !Int
- paramDlazy :: !Int
- paramDscore :: !Int
- paramDout :: !Int
- paramHeartbeatInterval :: !NominalDiffTime
- paramFanoutTTL :: !NominalDiffTime
- paramSeenTTL :: !NominalDiffTime
- paramPruneBackoff :: !NominalDiffTime
- paramUnsubBackoff :: !NominalDiffTime
- paramGossipFactor :: !Double
- paramFloodPublish :: !Bool
- paramMessageIdFn :: !(PubSubMessage -> MessageId)
- paramSignaturePolicy :: !SignaturePolicy
- paramMcacheLen :: !Int
- paramMcacheGossip :: !Int
- defaultGossipSubParams :: GossipSubParams
- newGossipSubNode :: Switch -> GossipSubParams -> IO GossipSubNode
- startGossipSub :: GossipSubNode -> IO ()
- stopGossipSub :: GossipSubNode -> IO ()
- gossipJoin :: GossipSubNode -> Topic -> IO ()
- gossipLeave :: GossipSubNode -> Topic -> IO ()
- gossipPublish :: GossipSubNode -> Topic -> ByteString -> IO ()
Identity
A Peer ID is a multihash of the serialized public key.
generateKeyPair :: IO (Either String KeyPair) Source #
Generate a new random Ed25519 key pair. Returns Left on cryptographic failure (should not occur with proper RNG).
fromPublicKey :: PublicKey -> PeerId Source #
Derive a Peer ID from a public key.
peerIdBytes :: PeerId -> ByteString Source #
Get the raw multihash bytes of a Peer ID.
parsePeerId :: Text -> Either String PeerId Source #
Parse a Peer ID from text, accepting both base58btc and CIDv1 (base32lower) formats.
CIDv1 format: b prefix + base32lower(0x01 || 0x72 || multihash)
toCIDv1 :: PeerId -> Text Source #
Encode a Peer ID as CIDv1 text (base32lower, no padding).
Format: b + base32lower(varint(1) + varint(0x72) + multihash_bytes)
Addressing
A multiaddr is a list of protocol components.
A single protocol component within a multiaddr.
Constructors
| IP4 !Word32 | IPv4 address (4 bytes big-endian) |
| IP6 !ByteString | IPv6 address (16 bytes) |
| TCP !Word16 | TCP port |
| UDP !Word16 | UDP port |
| P2P !ByteString | Peer ID as multihash bytes |
| QuicV1 | QUIC v1 (no address) |
| WS | WebSocket (no address) |
| WSS | WebSocket Secure (no address) |
| DNS !Text | DNS hostname |
| DNS4 !Text | DNS4 hostname |
| DNS6 !Text | DNS6 hostname |
| DNSAddr !Text | DNSAddr hostname |
| P2PCircuit | Circuit relay marker (no address) |
| WebTransport | WebTransport (no address) |
| NoiseProto | Noise protocol marker (no address) |
| YamuxProto | Yamux protocol marker (no address) |
splitP2P :: Multiaddr -> Maybe (Multiaddr, PeerId) Source #
Split off the trailing p2ppeerId component from a multiaddr. Returns the transport address and the peer ID, or Nothing if the multiaddr does not end with a p2p component.
fromText :: Text -> Either String Multiaddr Source #
Parse a multiaddr from its text representation (e.g. "ip4127.0.0.1tcp4001").
Switch (central coordinator)
The Switch: central coordinator of the libp2p networking stack.
Manages transports, connection pool, protocol handlers, and events. All mutable state is STM-based for safe concurrent access.
newSwitch :: PeerId -> KeyPair -> IO Switch Source #
Create a new Switch with the given local identity. All internal state is initialized empty.
addTransport :: Switch -> Transport -> IO () Source #
Register a transport with the switch. Appends to the list of transports; order matters for selectTransport.
switchListen :: Switch -> ConnectionGater -> [Multiaddr] -> IO [Multiaddr] Source #
Start listening on the given addresses.
For each address, selects a matching transport, binds a listener, and spawns an accept loop that handles inbound connections. Returns the actual bound addresses (port 0 resolved to actual port). Fails if the switch is already closed.
switchListenAddrs :: Switch -> IO [Multiaddr] Source #
Get the current listen addresses from all active listeners.
switchClose :: Switch -> IO () Source #
Shut down the switch. Cancels all accept loop threads, closes all listeners, then sets the closed flag.
dial :: Switch -> PeerId -> [Multiaddr] -> IO (Either DialError Connection) Source #
Dial a peer, reusing existing connections or establishing new ones.
Implements the full dial flow from docs/08-switch.md §Dial Flow: 1. Pool reuse: return existing Open connection if available 2. Backoff check: reject if peer recently failed 3. Deduplication: coalesce concurrent dials to same peer via TMVar 4. Staggered parallel dial with 250ms delay (Happy Eyeballs) 5. First success: upgrade, add to pool, return 6. All fail: record backoff, return error
Errors that can occur during a dial operation (docs/08-switch.md §Dialing).
Constructors
| DialBackoff | Peer is in backoff period (recently failed) |
| DialNoAddresses | No addresses provided for dialing |
| DialNoTransport !Multiaddr | No registered transport can handle this address |
| DialAllFailed ![String] | All dial attempts failed |
| DialUpgradeFailed !String | Connection upgrade pipeline failed |
| DialSwitchClosed | Switch has been shut down |
| DialResourceLimit !ResourceError | Resource limit exceeded |
| DialPeerIdMismatch !PeerId !PeerId | Expected vs actual remote PeerId |
setStreamHandler :: Switch -> ProtocolId -> StreamHandler -> IO () Source #
Register a protocol stream handler. Overwrites any existing handler for the same protocol ID.
removeStreamHandler :: Switch -> ProtocolId -> IO () Source #
Remove a protocol stream handler.
Abstraction for stream I/O to enable testing with in-memory buffers.
Constructors
| StreamIO | |
Fields
| |
type StreamHandler = StreamIO -> PeerId -> IO () Source #
A protocol stream handler.
Receives the stream I/O and the remote peer's identity.
type ProtocolId = Text Source #
A protocol identifier (e.g. "noise", "yamux/1.0.0").
data Connection Source #
An upgraded (secure + multiplexed) connection to a remote peer.
Constructors
| Connection | |
Fields
| |
Transport
Transport provides dial/listen capabilities for a specific protocol.
Constructors
| Transport | |
Fields
| |
newTCPTransport :: IO Transport Source #
Create a new TCP transport.
Connection gating
data ConnectionGater Source #
Connection gater: policy-based admission control (docs/08-switch.md §Connection Gating).
Called at multiple points during connection establishment to allow or deny based on policy (IP blocklist, Peer ID allowlist, etc.).
Constructors
| ConnectionGater | |
Fields
| |
defaultConnectionGater :: ConnectionGater Source #
Default gater that allows all connections.
Identify protocol
registerIdentifyHandlers :: Switch -> IO () Source #
Register Identify protocol handlers on the Switch.
Registers: ipfsid/1.0.0 — respond to Identify requests ipfsidpush1.0.0 — handle Identify Push from remote
requestIdentify :: Connection -> IO (Either String IdentifyInfo) Source #
Request Identify from a remote peer (initiator side).
Opens a new stream, negotiates ipfsid/1.0.0, reads until EOF, then decodes the protobuf message.
Ping protocol
registerPingHandler :: Switch -> IO () Source #
Register the Ping handler on the Switch.
sendPing :: Connection -> IO (Either PingError PingResult) Source #
Send a Ping to a remote peer (initiator side).
Opens a new stream, negotiates ipfsping/1.0.0, sends 32 random bytes, reads 32 bytes back, verifies match, measures RTT.
data PingResult Source #
Successful ping result.
Constructors
| PingResult | |
Fields
| |
Instances
| Show PingResult Source # | |
Defined in Network.LibP2P.Protocol.Ping.Ping Methods showsPrec :: Int -> PingResult -> ShowS # show :: PingResult -> String # showList :: [PingResult] -> ShowS # | |
| Eq PingResult Source # | |
Defined in Network.LibP2P.Protocol.Ping.Ping | |
Ping error types.
Constructors
| PingTimeout | No response within timeout |
| PingMismatch | Response doesn't match sent bytes |
| PingStreamError !String | Stream I/O error |
GossipSub
data GossipSubNode Source #
A GossipSub node: Router + Switch integration.
Constructors
| GossipSubNode | |
Fields
| |
data GossipSubParams Source #
GossipSub router parameters.
Constructors
| GossipSubParams | |
Fields
| |
defaultGossipSubParams :: GossipSubParams Source #
Default GossipSub parameters per spec.
newGossipSubNode :: Switch -> GossipSubParams -> IO GossipSubNode Source #
Create a new GossipSub node with a Router wired to the Switch.
The Router's gsSendRPC callback opens/reuses outbound streams to peers via the Switch's connection pool.
startGossipSub :: GossipSubNode -> IO () Source #
Start the GossipSub node: register stream handler, notifier, and start heartbeat.
stopGossipSub :: GossipSubNode -> IO () Source #
Stop the GossipSub node: cancel heartbeat and unregister handler.
gossipJoin :: GossipSubNode -> Topic -> IO () Source #
Subscribe to a topic.
gossipLeave :: GossipSubNode -> Topic -> IO () Source #
Unsubscribe from a topic.
gossipPublish :: GossipSubNode -> Topic -> ByteString -> IO () Source #
Publish a message to a topic (signed with the Switch's identity key).