Skip to content

Commit 1d5bc1f

Browse files
committed
corehttp/routing: wire GetClosestPeers()
This allows Kubo to respond to the GetClosestPeers() http routing v1 endpoint as spec'ed here: ipfs/specs#476 It is based on work from ipfs/boxo#1021 We let IpfsNode implmement the contentRouter.Client interface with the new method. We use our DHTs to get the closest peers. We try to respect the count/closerThan options here. We then trigger FindPeers lookups to fill-in information about the peers (addresses) and return the result. Tests are missing and will come up once discussions around the spec and the boxo pr have settled.
1 parent 72280f3 commit 1d5bc1f

File tree

7 files changed

+88
-18
lines changed

7 files changed

+88
-18
lines changed

core/corehttp/routing.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package corehttp
22

33
import (
44
"context"
5+
"math/rand/v2"
56
"net"
67
"net/http"
78
"time"
@@ -13,6 +14,7 @@ import (
1314
"github.com/ipfs/boxo/routing/http/types/iter"
1415
cid "github.com/ipfs/go-cid"
1516
core "github.com/ipfs/kubo/core"
17+
kbucket "github.com/libp2p/go-libp2p-kbucket"
1618
"github.com/libp2p/go-libp2p/core/peer"
1719
"github.com/libp2p/go-libp2p/core/routing"
1820
)
@@ -96,6 +98,74 @@ func (r *contentRouter) PutIPNS(ctx context.Context, name ipns.Name, record *ipn
9698
return r.n.Routing.PutValue(ctx, string(name.RoutingKey()), raw)
9799
}
98100

101+
func (r *contentRouter) GetClosestPeers(ctx context.Context, pid, closerThan peer.ID, count int) (iter.ResultIter[*types.PeerRecord], error) {
102+
// Per the spec, if the peer ID is empty, we should use self.
103+
if pid == "" {
104+
pid = r.n.Identity
105+
}
106+
107+
peers, err := r.n.DHT.WAN.GetClosestPeers(ctx, string(pid))
108+
if err != nil {
109+
return nil, err
110+
}
111+
112+
lanPeers, err := r.n.DHT.LAN.GetClosestPeers(ctx, string(pid))
113+
if err != nil {
114+
return nil, err
115+
}
116+
peers = append(peers, lanPeers...)
117+
118+
if closerThan != "" {
119+
// filter the peers slice to keep only those closer to pid than to closerThan
120+
filteredPeers := make([]peer.ID, 0)
121+
for _, p := range peers {
122+
if kbucket.Closer(p, closerThan, string(pid)) {
123+
filteredPeers = append(filteredPeers, p)
124+
}
125+
}
126+
peers = filteredPeers
127+
}
128+
129+
if count > 0 && len(peers) > count {
130+
// shuffle the peers slice before truncating it.
131+
rand.Shuffle(len(peers), func(i, j int) { peers[i], peers[j] = peers[j], peers[i] })
132+
peers = peers[0:count]
133+
}
134+
135+
// We have some DHT-closest peers. Find addresses for them. We can
136+
// use any routers for that, we can find records for DHT peers on
137+
// non-DHT routers with whatever protocols. FIXME: right? right??
138+
var records []*types.PeerRecord
139+
for _, p := range peers {
140+
record := types.PeerRecord{
141+
ID: &p,
142+
Schema: types.SchemaPeer,
143+
// we dont seem to care about protocol/extra infos
144+
// FIXME: should FindPeers care? That info seems to
145+
// not cross the FindPeer API.
146+
}
147+
// FindPeers will an iterator with a single item because
148+
// that's how it's implemeneted above. Treat it as if it
149+
// returned several records for a peer anyways. And merge them into the one above.
150+
peerIter, err := r.FindPeers(ctx, p, -1)
151+
if err != nil {
152+
continue
153+
}
154+
defer peerIter.Close()
155+
156+
for peerIter.Next() {
157+
val := peerIter.Val()
158+
if val.Err != nil {
159+
continue
160+
}
161+
record.Addrs = append(record.Addrs, val.Val.Addrs...)
162+
}
163+
records = append(records, &record)
164+
}
165+
166+
return iter.ToResultIter(iter.FromSlice(records)), nil
167+
}
168+
99169
type peerChanIter struct {
100170
ch <-chan peer.AddrInfo
101171
cancel context.CancelFunc

docs/examples/kubo-as-a-library/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ go 1.25
77
replace github.com/ipfs/kubo => ./../../..
88

99
require (
10-
github.com/ipfs/boxo v0.34.0
10+
github.com/ipfs/boxo v0.34.1-0.20250904113950-3bb649c3204e
1111
github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
1212
github.com/libp2p/go-libp2p v0.43.0
1313
github.com/multiformats/go-multiaddr v0.16.1
@@ -116,7 +116,7 @@ require (
116116
github.com/libp2p/go-libp2p-pubsub v0.14.2 // indirect
117117
github.com/libp2p/go-libp2p-pubsub-router v0.6.0 // indirect
118118
github.com/libp2p/go-libp2p-record v0.3.1 // indirect
119-
github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect
119+
github.com/libp2p/go-libp2p-routing-helpers v0.7.6-0.20250903125449-17ee6fbf872c // indirect
120120
github.com/libp2p/go-libp2p-xor v0.1.0 // indirect
121121
github.com/libp2p/go-msgio v0.3.0 // indirect
122122
github.com/libp2p/go-netroute v0.2.2 // indirect

docs/examples/kubo-as-a-library/go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd
287287
github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
288288
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
289289
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
290-
github.com/ipfs/boxo v0.34.0 h1:pMP9bAsTs4xVh8R0ZmxIWviV7kjDa60U24QrlGgHb1g=
291-
github.com/ipfs/boxo v0.34.0/go.mod h1:kzdH/ewDybtO3+M8MCVkpwnIIc/d2VISX95DFrY4vQA=
290+
github.com/ipfs/boxo v0.34.1-0.20250904113950-3bb649c3204e h1:wtAkZQjqeC1ClRUxRUR3T0w3IyXSRmK3AWy1/z0e/VE=
291+
github.com/ipfs/boxo v0.34.1-0.20250904113950-3bb649c3204e/go.mod h1:i+NSkHGIDPmEZ23c1jgKUH2yiTvZLi+5kf/0A/XUai4=
292292
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
293293
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
294294
github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=
@@ -438,8 +438,8 @@ github.com/libp2p/go-libp2p-pubsub-router v0.6.0 h1:D30iKdlqDt5ZmLEYhHELCMRj8b4s
438438
github.com/libp2p/go-libp2p-pubsub-router v0.6.0/go.mod h1:FY/q0/RBTKsLA7l4vqC2cbRbOvyDotg8PJQ7j8FDudE=
439439
github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg=
440440
github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E=
441-
github.com/libp2p/go-libp2p-routing-helpers v0.7.5 h1:HdwZj9NKovMx0vqq6YNPTh6aaNzey5zHD7HeLJtq6fI=
442-
github.com/libp2p/go-libp2p-routing-helpers v0.7.5/go.mod h1:3YaxrwP0OBPDD7my3D0KxfR89FlcX/IEbxDEDfAmj98=
441+
github.com/libp2p/go-libp2p-routing-helpers v0.7.6-0.20250903125449-17ee6fbf872c h1:oWvPNbSi3yoJMDe04qvICNpwrKoub+x0EDb3bjc5cxs=
442+
github.com/libp2p/go-libp2p-routing-helpers v0.7.6-0.20250903125449-17ee6fbf872c/go.mod h1:Q1VSaOawgsvaa3hGl/PejADIhl2deiqSEsQDpB3Ggss=
443443
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
444444
github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
445445
github.com/libp2p/go-libp2p-xor v0.1.0 h1:hhQwT4uGrBcuAkUGXADuPltalOdpf9aag9kaYNT2tLA=

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ require (
2222
github.com/hashicorp/go-version v1.7.0
2323
github.com/ipfs-shipyard/nopfs v0.0.14
2424
github.com/ipfs-shipyard/nopfs/ipfs v0.25.0
25-
github.com/ipfs/boxo v0.34.0
25+
github.com/ipfs/boxo v0.34.1-0.20250904113950-3bb649c3204e
2626
github.com/ipfs/go-block-format v0.2.2
2727
github.com/ipfs/go-cid v0.5.0
2828
github.com/ipfs/go-cidutil v0.1.0
@@ -58,7 +58,7 @@ require (
5858
github.com/libp2p/go-libp2p-pubsub v0.14.2
5959
github.com/libp2p/go-libp2p-pubsub-router v0.6.0
6060
github.com/libp2p/go-libp2p-record v0.3.1
61-
github.com/libp2p/go-libp2p-routing-helpers v0.7.5
61+
github.com/libp2p/go-libp2p-routing-helpers v0.7.6-0.20250903125449-17ee6fbf872c
6262
github.com/libp2p/go-libp2p-testing v0.12.0
6363
github.com/libp2p/go-socket-activation v0.1.1
6464
github.com/miekg/dns v1.1.68

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,8 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd
354354
github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
355355
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
356356
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
357-
github.com/ipfs/boxo v0.34.0 h1:pMP9bAsTs4xVh8R0ZmxIWviV7kjDa60U24QrlGgHb1g=
358-
github.com/ipfs/boxo v0.34.0/go.mod h1:kzdH/ewDybtO3+M8MCVkpwnIIc/d2VISX95DFrY4vQA=
357+
github.com/ipfs/boxo v0.34.1-0.20250904113950-3bb649c3204e h1:wtAkZQjqeC1ClRUxRUR3T0w3IyXSRmK3AWy1/z0e/VE=
358+
github.com/ipfs/boxo v0.34.1-0.20250904113950-3bb649c3204e/go.mod h1:i+NSkHGIDPmEZ23c1jgKUH2yiTvZLi+5kf/0A/XUai4=
359359
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
360360
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
361361
github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=
@@ -524,8 +524,8 @@ github.com/libp2p/go-libp2p-pubsub-router v0.6.0 h1:D30iKdlqDt5ZmLEYhHELCMRj8b4s
524524
github.com/libp2p/go-libp2p-pubsub-router v0.6.0/go.mod h1:FY/q0/RBTKsLA7l4vqC2cbRbOvyDotg8PJQ7j8FDudE=
525525
github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg=
526526
github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E=
527-
github.com/libp2p/go-libp2p-routing-helpers v0.7.5 h1:HdwZj9NKovMx0vqq6YNPTh6aaNzey5zHD7HeLJtq6fI=
528-
github.com/libp2p/go-libp2p-routing-helpers v0.7.5/go.mod h1:3YaxrwP0OBPDD7my3D0KxfR89FlcX/IEbxDEDfAmj98=
527+
github.com/libp2p/go-libp2p-routing-helpers v0.7.6-0.20250903125449-17ee6fbf872c h1:oWvPNbSi3yoJMDe04qvICNpwrKoub+x0EDb3bjc5cxs=
528+
github.com/libp2p/go-libp2p-routing-helpers v0.7.6-0.20250903125449-17ee6fbf872c/go.mod h1:Q1VSaOawgsvaa3hGl/PejADIhl2deiqSEsQDpB3Ggss=
529529
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
530530
github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
531531
github.com/libp2p/go-libp2p-xor v0.1.0 h1:hhQwT4uGrBcuAkUGXADuPltalOdpf9aag9kaYNT2tLA=

test/dependencies/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ require (
134134
github.com/huin/goupnp v1.3.0 // indirect
135135
github.com/inconshreveable/mousetrap v1.1.0 // indirect
136136
github.com/ipfs/bbloom v0.0.4 // indirect
137-
github.com/ipfs/boxo v0.34.0 // indirect
137+
github.com/ipfs/boxo v0.34.1-0.20250904113950-3bb649c3204e // indirect
138138
github.com/ipfs/go-bitfield v1.1.0 // indirect
139139
github.com/ipfs/go-block-format v0.2.2 // indirect
140140
github.com/ipfs/go-cid v0.5.0 // indirect
@@ -183,7 +183,7 @@ require (
183183
github.com/libp2p/go-libp2p-kad-dht v0.34.0 // indirect
184184
github.com/libp2p/go-libp2p-kbucket v0.7.0 // indirect
185185
github.com/libp2p/go-libp2p-record v0.3.1 // indirect
186-
github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect
186+
github.com/libp2p/go-libp2p-routing-helpers v0.7.6-0.20250903125449-17ee6fbf872c // indirect
187187
github.com/libp2p/go-msgio v0.3.0 // indirect
188188
github.com/libp2p/go-netroute v0.2.2 // indirect
189189
github.com/libp2p/go-reuseport v0.4.0 // indirect

test/dependencies/go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
332332
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
333333
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
334334
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
335-
github.com/ipfs/boxo v0.34.0 h1:pMP9bAsTs4xVh8R0ZmxIWviV7kjDa60U24QrlGgHb1g=
336-
github.com/ipfs/boxo v0.34.0/go.mod h1:kzdH/ewDybtO3+M8MCVkpwnIIc/d2VISX95DFrY4vQA=
335+
github.com/ipfs/boxo v0.34.1-0.20250904113950-3bb649c3204e h1:wtAkZQjqeC1ClRUxRUR3T0w3IyXSRmK3AWy1/z0e/VE=
336+
github.com/ipfs/boxo v0.34.1-0.20250904113950-3bb649c3204e/go.mod h1:i+NSkHGIDPmEZ23c1jgKUH2yiTvZLi+5kf/0A/XUai4=
337337
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
338338
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
339339
github.com/ipfs/go-block-format v0.2.2 h1:uecCTgRwDIXyZPgYspaLXoMiMmxQpSx2aq34eNc4YvQ=
@@ -468,8 +468,8 @@ github.com/libp2p/go-libp2p-kbucket v0.7.0 h1:vYDvRjkyJPeWunQXqcW2Z6E93Ywx7fX0jg
468468
github.com/libp2p/go-libp2p-kbucket v0.7.0/go.mod h1:blOINGIj1yiPYlVEX0Rj9QwEkmVnz3EP8LK1dRKBC6g=
469469
github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg=
470470
github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E=
471-
github.com/libp2p/go-libp2p-routing-helpers v0.7.5 h1:HdwZj9NKovMx0vqq6YNPTh6aaNzey5zHD7HeLJtq6fI=
472-
github.com/libp2p/go-libp2p-routing-helpers v0.7.5/go.mod h1:3YaxrwP0OBPDD7my3D0KxfR89FlcX/IEbxDEDfAmj98=
471+
github.com/libp2p/go-libp2p-routing-helpers v0.7.6-0.20250903125449-17ee6fbf872c h1:oWvPNbSi3yoJMDe04qvICNpwrKoub+x0EDb3bjc5cxs=
472+
github.com/libp2p/go-libp2p-routing-helpers v0.7.6-0.20250903125449-17ee6fbf872c/go.mod h1:Q1VSaOawgsvaa3hGl/PejADIhl2deiqSEsQDpB3Ggss=
473473
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
474474
github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
475475
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=

0 commit comments

Comments
 (0)