Skip to content

Commit a5b6db6

Browse files
authored
Merge pull request #476 from ipfs/feat/add-get-closest-peers-to-http-routing
IPIP-0476: Delegated Routing DHT Closest Peers API
2 parents 110bf46 + d551c94 commit a5b6db6

File tree

2 files changed

+236
-12
lines changed

2 files changed

+236
-12
lines changed

src/ipips/ipip-0476.md

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
---
2+
title: "IPIP-0476: Delegated Routing DHT Closest Peers API"
3+
date: 2025-11-20
4+
ipip: ratified
5+
editors:
6+
- name: Alex Potsides
7+
github: achingbrain
8+
affiliation:
9+
name: Shipyard
10+
url: https://ipshipyard.com
11+
- name: Marcin Rataj
12+
github: lidel
13+
affiliation:
14+
name: Shipyard
15+
url: https://ipshipyard.com
16+
relatedIssues:
17+
- https://github.com/ipfs/specs/pull/476
18+
- https://github.com/ipfs/specs/pull/497
19+
order: 476
20+
tags: ['ipips']
21+
---
22+
23+
## Summary
24+
25+
Add a new HTTP endpoint to the Delegated Routing API that allows clients to find the closest peers to a given peer ID without being full DHT clients.
26+
27+
## Motivation
28+
29+
Browser nodes and other resource-constrained clients need to perform peer discovery operations without the overhead of being full DHT clients. The primary use case is for browser nodes performing random walks to find peers that they can make circuit relay reservations on.
30+
31+
Currently, to find peers close to a particular key in the DHT keyspace, a node must:
32+
1. Be a full DHT client with all the associated overhead
33+
2. Maintain connections to many peers
34+
3. Handle the complexity of the DHT protocol
35+
36+
This is particularly problematic for:
37+
- Browser nodes that need to find circuit relay servers
38+
- Light clients that want to populate their routing tables
39+
- Applications that need to find peers to host provider records
40+
41+
## Detailed design
42+
43+
This IPIP introduces a new "DHT Routing API" section to the Delegated Routing V1 HTTP API specification with the following endpoint:
44+
45+
### `GET /routing/v1/dht/closest/peers/{key}`
46+
47+
#### Path Parameters
48+
49+
- `key` is a [CID](https://github.com/multiformats/cid) or Peer ID to find the closest peers to.
50+
- CID SHOULD be a CIDv1 in any encoding.
51+
- Peer ID can be represented as a Multihash in Base58btc, or a CIDv1 with `libp2p-key` (`0x72`) codec in Base36 or Base32.
52+
- Arbitrary multihash lookups can be performed by wrapping the multihash in a CIDv1 with `raw` (`0x55`) codec.
53+
54+
#### Response
55+
56+
The response follows the same format as the existing peer routing endpoints, returning a JSON object with a `Peers` array containing peer records conforming to the Peer Schema.
57+
58+
### Specification Changes
59+
60+
The following changes are made to `src/routing/http-routing-v1.md`:
61+
62+
1. Add a new "## DHT Routing API" section after the "Peer Routing API" section
63+
2. Document the `/routing/v1/dht/closest/peers/{key}` endpoint with its parameters and response format
64+
3. Update the document date to reflect the modification
65+
66+
## Design rationale
67+
68+
The design follows several key principles:
69+
70+
### Simple MVP Approach
71+
72+
The endpoint provides the minimum viable functionality needed for the primary use cases. It can be expanded later if more complex routing scenarios emerge.
73+
74+
### Future-Proofed Path Structure
75+
76+
The path `/routing/v1/dht/closest/peers/{key}` is intentionally structured to allow future expansion:
77+
- The `/dht/` segment clearly indicates DHT-specific operations
78+
- The `/closest/peers/` structure allows for potential future endpoints like `/closest/keys/` for keyspace queries
79+
- This organization keeps the API logical and extensible
80+
81+
### Routing-Agnostic Implementation
82+
83+
While the endpoint is in the DHT namespace, implementations have flexibility in how they determine "closest" peers. This allows for optimization based on the specific routing system being used.
84+
85+
### Consistency with Existing API
86+
87+
The endpoint follows the established patterns of the Delegated Routing API:
88+
- Uses the same response format as other peer routing endpoints
89+
- Follows the same parameter conventions
90+
- Maintains consistency in error handling and status codes
91+
92+
### User benefit
93+
94+
This enhancement provides significant benefits to end users:
95+
96+
1. **Browser Compatibility**: Browser nodes can discover circuit relay servers without implementing the full DHT protocol
97+
2. **Reduced Resource Usage**: Light clients save bandwidth and processing power by delegating peer discovery
98+
3. **Faster Peer Discovery**: Delegated routing servers can provide cached results more quickly than performing DHT walks
99+
4. **Simplified Implementation**: Application developers can implement peer discovery with simple HTTP requests instead of complex DHT logic
100+
101+
### Compatibility
102+
103+
This change is fully backward compatible:
104+
- It adds a new endpoint without modifying existing ones
105+
- Existing clients continue to work unchanged
106+
- Servers that don't implement the endpoint return 501 (Not Implemented) as per the specification
107+
108+
### Security
109+
110+
The new endpoint introduces no additional security considerations beyond those already present in the Delegated Routing API:
111+
112+
- Standard rate limiting should be applied to prevent abuse
113+
- The endpoint reveals no more information than a DHT query would
114+
- Access controls can be implemented at the HTTP layer if needed
115+
- Response caching helps mitigate potential DoS attacks
116+
117+
### Alternatives
118+
119+
Several alternatives were considered:
120+
121+
1. **Full DHT Client Implementation**: Rejected due to excessive resource requirements for browser and mobile environments
122+
123+
2. **Custom libp2p Protocol**: Would require all nodes to implement a new protocol, creating adoption barriers
124+
125+
3. **Extension of Existing Peer Routing**: The `/routing/v1/peers/` endpoint serves a different purpose (finding specific peers rather than closest peers)
126+
127+
4. **Amino-Specific Endpoint**: Initially considered `/routing/v1/amino/` namespace but rejected in favor of the more generic `/dht/` approach
128+
129+
5. **Query Parameters for Filtering and Limiting**: During design discussions, `count` and `closer-than` query parameters were considered:
130+
- `count`: limit the number of results returned
131+
- `closer-than`: filter peers to only return those closer than a reference peer
132+
133+
These were omitted from the initial implementation (boxo v0.35.2, someguy v0.11.0) for simplicity. The endpoint defaults to returning up to the DHT bucket size (20 for Amino DHT). Future backwards-compatible updates MAY add these parameters if use cases emerge that require more fine-grained control.
134+
135+
### Peer Ordering
136+
137+
Implementations SHOULD return peers sorted by closeness to the key. For Kademlia-based DHT implementations (such as Amino DHT), this means sorting by XOR distance with the closest peers first.
138+
139+
## Test fixtures
140+
141+
This IPIP does not deal with content-addressed data, so specific test CIDs are not applicable. However, implementations should test:
142+
143+
1. Valid CID and Peer ID inputs return appropriate closest peers
144+
2. Results are limited to the DHT bucket size
145+
3. Peers are sorted by closeness (XOR distance for Kademlia DHTs)
146+
4. Invalid keys return appropriate error responses
147+
5. Both streaming (NDJSON) and non-streaming (JSON) response formats work correctly
148+
149+
### Copyright
150+
151+
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

src/routing/http-routing-v1.md

Lines changed: 85 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,28 @@ description: >
44
Delegated routing is a mechanism for IPFS implementations to use for offloading
55
content routing, peer routing and naming to another process/server. This specification describes
66
an HTTP API for delegated routing of content, peers, and IPNS.
7-
date: 2024-10-29
7+
date: 2025-11-20
88
maturity: reliable
99
editors:
10+
- name: Marcin Rataj
11+
github: lidel
12+
url: https://lidel.org/
13+
affiliation:
14+
name: Shipyard
15+
url: https://ipshipyard.com
16+
former_editors:
17+
- name: Henrique Dias
18+
url: https://hacdias.com/
19+
github: hacdias
20+
affiliation:
21+
name: Shipyard
22+
url: https://ipshipyard.com
23+
- name: Daniel Norman
24+
github: 2color
25+
affiliation:
26+
name: Shipyard
27+
url: https://ipshipyard.com
28+
thanks:
1029
- name: Gus Eggert
1130
github: guseggert
1231
affiliation:
@@ -17,20 +36,15 @@ editors:
1736
affiliation:
1837
name: Protocol Labs
1938
url: https://protocol.ai/
20-
- name: Henrique Dias
21-
url: https://hacdias.com/
22-
github: hacdias
39+
- name: Alex Potsides
40+
github: achingbrain
2341
affiliation:
2442
name: Shipyard
2543
url: https://ipshipyard.com
26-
- name: Marcin Rataj
27-
github: lidel
28-
url: https://lidel.org/
29-
affiliation:
30-
name: Shipyard
31-
url: https://ipshipyard.com
32-
- name: Daniel Norman
33-
github: 2color
44+
- name: Will Scott
45+
github: willscott
46+
- name: Hector Sanjuan
47+
github: hsanjuan
3448
affiliation:
3549
name: Shipyard
3650
url: https://ipshipyard.com
@@ -245,6 +259,65 @@ The content body must be a [`application/vnd.ipfs.ipns-record`][application/vnd.
245259
- `400` (Bad Request): the provided :ref[IPNS Record] or :ref[IPNS Name] are not valid.
246260
- `406` (Not Acceptable): submitted content type is not supported. Error message returned in body should inform the user to retry with `Content-Type: application/vnd.ipfs.ipns-record`.
247261

262+
## DHT Routing API
263+
264+
The DHT Routing API is OPTIONAL. Implementations that do not support DHT operations MAY return `404` (Not Found) or `501` (Not Implemented) as specified in [Error Codes](#error-codes).
265+
266+
### `GET /routing/v1/dht/closest/peers/{key}`
267+
268+
This optional endpoint allows light clients to lower the cost of DHT walks in browser contexts.
269+
270+
#### Path Parameters
271+
272+
- `key` is a [CID] or [Peer ID][peer-id-representation] to find the closest peers to.
273+
- [CID] SHOULD be a CIDv1 in any encoding.
274+
- [Peer ID][peer-id-representation] can be represented as a Multihash in Base58btc, or a CIDv1 with `libp2p-key` (`0x72`) codec in Base36 or Base32.
275+
- Arbitrary multihash lookups can be performed by wrapping the multihash in a CIDv1 with `raw` (`0x55`) codec.
276+
- Implementations SHOULD support both CID and Peer ID formats for maximum interoperability.
277+
278+
#### Response Status Codes
279+
280+
- `200` (OK): the response body contains peer records.
281+
- `404` (Not Found): must be returned if no matching records are found.
282+
- `422` (Unprocessable Entity): request does not conform to schema or semantic constraints.
283+
- `501` (Not Implemented): may be returned if DHT operations are not supported.
284+
285+
#### Response Headers
286+
287+
- `Content-Type`: the content type of this response, which MUST be `application/json` or `application/x-ndjson` (see [streaming](#streaming)).
288+
- `Last-Modified`: an HTTP-date timestamp ([RFC9110, Section 5.6.7](https://www.rfc-editor.org/rfc/rfc9110#section-5.6.7)) of the resolution, allowing HTTP proxies and CDNs to support inexpensive update checks via `If-Modified-Since`
289+
- `Cache-Control: public, max-age={ttl}, public, stale-while-revalidate={max-ttl}, stale-if-error={max-ttl}`: meaningful cache TTL returned with the response.
290+
- When present, `ttl` SHOULD be shorter for responses whose resolution ended in no results (e.g. 15 seconds),
291+
and longer for responses that have results (e.g. 5 minutes).
292+
- Implementations SHOULD include `max-ttl`, set to the maximum cache window of the underlying routing system.
293+
For example, if Amino DHT results are returned, `stale-while-revalidate` SHOULD be set to `172800` (48h, which at the time of writing this specification, is the provider record expiration window).
294+
- `Vary: Accept`: allows intermediate caches to play nicely with the different possible content types.
295+
296+
#### Response Body
297+
298+
```json
299+
{
300+
"Peers": [
301+
{
302+
"Schema": "<schema>",
303+
"Protocols": ["<protocol-a>", "<protocol-b>", ...],
304+
"ID": "bafz...",
305+
"Addrs": ["/ip4/..."],
306+
...
307+
},
308+
...
309+
]
310+
}
311+
```
312+
313+
The number of peer records in the response SHOULD be limited to the DHT bucket size (20 for Amino DHT).
314+
315+
Peers SHOULD be returned sorted by closeness to the key. For Kademlia-based DHT implementations (such as Amino DHT), this means sorting by XOR distance with the closest peers first.
316+
317+
The client SHOULD be able to make a request with `Accept: application/x-ndjson` and get a [stream](#streaming) with results. Note that due to the XOR sorting requirement, the streamed response may be blocked until the DHT lookup completes and peers can be sorted before transmission.
318+
319+
Each object in the `Peers` list is a record conforming to the [Peer Schema](#peer-schema).
320+
248321
## Pagination
249322

250323
This API does not support pagination, but optional pagination can be added in a backwards-compatible spec update.

0 commit comments

Comments
 (0)