EXTENDED-KADEMLIA-DISCOVERY
| Field | Value |
|---|---|
| Name | Extended Kademlia Discovery with capability filtering |
| Slug | 143 |
| Status | raw |
| Category | Standards Track |
| Editor | Simon-Pierre Vivier [email protected] |
| Contributors | Hanno Cornelius [email protected] |
Timeline
Abstract
This specification defines a lightweight peer discovery mechanism
built on top of the libp2p Kademlia DHT.
It allows nodes to advertise themselves by storing a new type of peer record under
their own peer ID and enables other nodes to discover peers in the network via
random walks through the DHT.
The mechanism supports capability-based filtering of services entries,
making it suitable for overlay networks that
require connectivity to peers offering specific protocols or features.
Motivation
The standard libp2p Kademlia DHT provides content routing and peer routing toward specific keys or peer IDs, but offers limited support for general-purpose random peer discovery — i.e. finding any well-connected peer in the network.
Existing alternatives such as mDNS, Rendezvous, or bootstrap lists do not always satisfy the needs of large-scale decentralized overlay networks that require:
- Organic growth of connectivity without strong trust in bootstrap nodes
- Discovery of peers offering specific capabilities (e.g. protocols, bandwidth classes, service availability)
- Resilience against eclipse attacks and network partitioning
- Low overhead compared to gossip-based or pubsub-based discovery
By leveraging the already-deployed Kademlia routing table and random-walk behavior, this document define a simple, low-cost discovery primitive that reuses existing infrastructure while adding capability advertisement and filtering via a new record type.
Semantic
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in 2119.
Please refer to libp2p Kademlia DHT specification (Kad-DHT)
and extensible peer records specification (XPR) for terminology used in this document.
Protocol
Record Propagation
A node that wants to make itself discoverable,
also known as an advertiser,
MUST encode its discoverable information in an XPR.
The encoded information MUST be sufficient for discoverers to connect to this advertiser.
It MAY choose to encode some or all of its capabilities (and related information)
as services in the XPR.
This will allow future discoverers to filter discovered records based on desired capabilities.
In order to advertise this record,
the advertiser SHOULD first retrieve the k closest peers to its own peer ID
in its own Kad-DHT routing table.
This assumes that the routing table has been previously initialised
and follows the regular bootstrap process as per the Kad-DHT specification.
The advertiser SHOULD then send a PUT_VALUE message to these k peers
to store the XPR against its own peer ID.
This process SHOULD be repeated periodically to maintain the advertised record.
We RECOMMEND an interval of once every 30 minutes.
Use of XPR in identify
Advertisers SHOULD include their XPRs as the signedPeerRecord
in libp2p Identify messages.
Note: For more information, see the
identifyprotocol implementations, such as go-libp2p, as at the time of writing (Jan 2026) thesignedPeerRecordfield extension is not yet part of any official specification.
Record Discovery
A node that wants to discover peers to connect to,
also known as a discoverer,
SHOULD perform the following random walk discovery procedure (FIND_RANDOM):
-
Choose a random value in the
Kad-DHTkey space. (R_KEY). -
Follow the
Kad-DHTpeer routing algorithm, withR_KEYas the target. This procedure loops theKad-DHTFIND_NODEprocedure to the target key, each time receiving closer peers (closerPeers) to the target key in response, until no new closer peers can be found. Since the target is random, the discoverer SHOULD consider each previously unseen peer in each response'scloserPeersfield, as a randomly discovered node of potential interest. The discoverer MUST keep track of such peers asdiscoveredPeers. -
For each
discoveredPeer, attempt to retrieve a correspondingXPR. This can be done in one of two ways:3.1 If the
discoveredPeerin the response contains at least one multiaddress in theaddrsfield, attempt a connection to that peer and wait to receive theXPRas part of theidentifyprocedure.3.2 If the
discoveredPeerdoes not includeaddrsinformation, or the connection attempt to includedaddrsfails, or more service information is required before a connection can be attempted, MAY perform a value retrieval procedure to thediscoveredPeerID. -
For each retrieved
XPR, validate the signature against the peer ID. In addition, the discoverer MAY filter discovered peers based on the capabilities encoded within theservicesfield of theXPR. The discoverer SHOULD ignore (and disconnect, if already connected) discovered peers with invalidXPRs or that do not advertise theservicesof interest to the discoverer.
Privacy Enhancements
To prevent network topology mapping and eclipse attacks,
Kad-DHT nodes MUST NOT disclose connection type in response messages.
The connection field of every Peer MUST always be set to NOT_CONNECTED.
API Specification
Implementers of this protocol, SHOULD wrap the implementation in a functional interface similar to the one defined below.
In Extended Kademlia Discovery, the discovery protocol is based on a random DHT walk, optionally filtering the randomly discovered peers by capability. However, it's possible to define discovery protocols with better performance in finding peers with specific capabilities. The aim is to define an API that is compatible with Extended Kademlia Discovery and more sophisticated capability discovery protocols, maintaining similar function signatures even if the underlying protocol differs. This section may be extracted into a separate API specification once new capability discovery protocols are defined.
The API is defined in the form of C-style bindings. However, this simply serves to illustrate the exposed functions and can be adapted into the conventions of any strongly typed language. Although unspecified in the API below, all functions SHOULD return an error result type appropriate to the implementation language.
start()
Start the discovery protocol, including all tasks related to bootstrapping and maintaining the routing table and advertising this node and its capabilities.
In the case of Extended Kademlia Discovery,
start() will kick off the periodic task of refreshing the propagated XPR.
stop()
Stop the discovery protocol, including all tasks related to maintaining the routing table and advertising this node and its capabilities.
In the case of Extended Kademlia Discovery,
stop() will cancel the periodic task of refreshing the propagated XPR.
start_advertising(const char* service_id)
Start advertising this node against any capability
encoded as an input service_id string.
In the case of Extended Kademlia Discovery,
start_advertising() will include the input service_id
in the regularly propagated XPR.
stop_advertising(const char* service_id)
Stop advertising this node against the capability
encoded in the input service_id string.
In the case of Extended Kademlia Discovery,
stop_advertising() will exclude the service_id
from the regularly propagated XPR,
if it was previously included.
ExtensiblePeerRecords* lookup(const char* service_id, ...)
Lookup and return records for peers supporting the capability encoded in the input service_id string,
using the underlying discovery protocol.
service_id is an OPTIONAL input argument.
If unset, it indicates a lookup for peers supporting any (or zero) capabilities.
In the case of Extended Kademlia Discovery,
lookup() will trigger the random walk record discovery,
filtering discovered records based on service_id, if specified.
If no service_id is specified,
Extended Kademlia Discovery will just return a random selection of peer records,
matching any capability.
Copyright
Copyright and related rights waived via CC0.