libp2p-hs-0.1.0.0: Haskell implementation of the libp2p networking stack
Safe HaskellNone
LanguageGHC2021

LibP2P.DHT

Description

DHT node state, RPC handler, and record/provider stores.

The DHTNode is the top-level coordinator for Kademlia DHT operations. It owns the routing table, record store, provider store, and handles both inbound (as handler) and outbound (dhtSendRequest) RPC.

The outbound sender is wired to the Switch by newDHTNode; it remains a record field so tests can inject mocks without a real network.

Synopsis

Types

data DHTNode Source #

Top-level DHT node state.

Constructors

DHTNode 

Fields

data DHTMode Source #

Server or client mode.

Constructors

DHTServer 
DHTClient 

Instances

Instances details
Show DHTMode Source # 
Instance details

Defined in LibP2P.DHT

Eq DHTMode Source # 
Instance details

Defined in LibP2P.DHT

Methods

(==) :: DHTMode -> DHTMode -> Bool #

(/=) :: DHTMode -> DHTMode -> Bool #

data ProviderEntry Source #

A provider record for content routing.

Constructors

ProviderEntry 

Instances

Instances details
Show ProviderEntry Source # 
Instance details

Defined in LibP2P.DHT

Eq ProviderEntry Source # 
Instance details

Defined in LibP2P.DHT

data Validator Source #

Validator interface for record validation.

valValidate checks that a value is well-formed for its key and returns an error for records that must not be stored or served. valSelect picks the index of the best value among conflicting candidates for the same key (used for GET_VALUE conflict resolution).

Validators

defaultValidator :: Validator Source #

The default validator set: pk records only. Additional namespaces can be registered by building a custom namespacedValidator and storing it in the DHT node.

namespacedValidator :: Map ByteString Validator -> Validator Source #

Dispatch validation by key namespace. Keys without a registered namespace are rejected, matching go-libp2p's namespaced validator ("invalid record keytype").

pkValidator :: Validator Source #

Validator for the pk namespace: the value must be a serialized PublicKey protobuf whose derived Peer ID equals the multihash in the key path. Public keys never conflict, so valSelect keeps the first candidate (go-libp2p's record.PublicKeyValidator does the same).

Construction

newDHTNode :: Switch -> DHTMode -> IO DHTNode Source #

Create a new DHT node with the outbound sender wired to the Switch.

Handler registration

registerDHTHandler :: DHTNode -> IO () Source #

Register the DHT handler on the Switch.

Per specs/kad-dht (client and server mode), nodes operating in client mode do not offer the Kademlia protocol identifier for incoming streams, so this is a no-op for DHTClient nodes: they keep issuing outbound queries via dhtSendRequest but never serve inbound RPC.

Inbound RPC handler

handleDHTRequest :: DHTNode -> StreamIO -> PeerId -> IO () Source #

Handle an inbound DHT stream.

Per specs/kad-dht, implementations must handle additional RPC request messages on the same incoming stream: go-libp2p keeps one long-lived stream per peer and pipelines requests over it. Loop until the stream errors, is reset, or reaches EOF.

Routing table maintenance

addPeerToTable :: DHTNode -> BucketEntry -> IO InsertResult Source #

Insert a peer into the routing table, applying the Kademlia full-bucket eviction policy.

When the target bucket is full, the least-recently-seen peer is probed with a FIND_NODE request (the DHT liveness check; our MessageType has no PING, and go-libp2p likewise treats any successful RPC as proof of liveness):

  • if the LRS peer answers, it is kept (refreshed to most-recently-seen) and the new peer is dropped (BucketFull);
  • if it does not answer, it is evicted and the new peer takes its place (Inserted).

Store operations

storeRecord :: DHTNode -> DHTRecord -> IO () Source #

Store a record in the local datastore.

lookupRecord :: DHTNode -> ByteString -> IO (Maybe DHTRecord) Source #

Look up a record by key.

addProvider :: DHTNode -> ByteString -> ProviderEntry -> IO () Source #

Add a provider entry for a content key.

A provider republishing on schedule replaces its previous entry (deduplicated by peer ID) instead of appending a duplicate, so the entry's timestamp is refreshed and GET_PROVIDERS responses stay bounded.

getProviders :: DHTNode -> ByteString -> IO [ProviderEntry] Source #

Get providers for a content key, pruning entries older than providerRecordTTL (48h expiration interval per specs/kad-dht).

Wire helpers

decodePeerAddrs :: [ByteString] -> [Multiaddr] Source #

Decode raw wire multiaddrs from a Peer record, dropping any that fail to parse: a malformed address from a remote peer must not poison the rest of the record.

Constants

dhtProtocolId :: Text Source #

DHT protocol identifier for multistream-select.

providerRecordTTL :: NominalDiffTime Source #

Provider record expiration interval, per specs/kad-dht (48 hours). Expired entries are pruned on read in getProviders.