Skip to content

Commit 4f37aff

Browse files
authored
fix!: use libp2p ping instad of kad ping (#3074)
The [kad-dht spec](s://github.com./libp2p/specs/tree/master/kad-dht) says: > PING: Deprecated message type replaced by the dedicated ping protocol. Implementations may still handle incoming PING requests for backwards compatibility. Implementations must not actively send PING requests. Switch to using `@libp2p/ping` instead of KAD-DHT `PING` messages to be compliant with the spec. BREAKING CHANGE: `@libp2p/kad-dht` now depends on `@libp2p/ping` - please configure this in your service map
1 parent 53a9be5 commit 4f37aff

File tree

13 files changed

+100
-61
lines changed

13 files changed

+100
-61
lines changed

.github/workflows/examples.yml

+2
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,15 @@ jobs:
7474
- '@libp2p/identify@$PWD/packages/protocol-identify'
7575
- '@libp2p/kad-dht@$PWD/packages/kad-dht'
7676
- '@libp2p/mdns@$PWD/packages/peer-discovery-mdns'
77+
- '@libp2p/ping@$PWD/packages/protocol-ping'
7778
- '@libp2p/tcp@$PWD/packages/transport-tcp'
7879
- 'libp2p@$PWD/packages/libp2p'
7980
- name: js-libp2p-example-peer-and-content-routing
8081
repo: https://github.com./libp2p/js-libp2p-example-peer-and-content-routing.git
8182
deps:
8283
- '@libp2p/identify@$PWD/packages/protocol-identify'
8384
- '@libp2p/kad-dht@$PWD/packages/kad-dht'
85+
- '@libp2p/ping@$PWD/packages/protocol-ping'
8486
- '@libp2p/tcp@$PWD/packages/transport-tcp'
8587
- 'libp2p@$PWD/packages/libp2p'
8688
- name: js-libp2p-example-pnet

packages/integration-tests/test/circuit-relay-discovery.node.ts

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { circuitRelayServer, type CircuitRelayService, circuitRelayTransport } f
55
import { identify } from '@libp2p/identify'
66
import { stop } from '@libp2p/interface'
77
import { kadDHT, passthroughMapper } from '@libp2p/kad-dht'
8+
import { ping } from '@libp2p/ping'
89
import { plaintext } from '@libp2p/plaintext'
910
import { tcp } from '@libp2p/tcp'
1011
import { expect } from 'aegir/chai'
@@ -43,6 +44,7 @@ describe('circuit-relay discovery', () => {
4344
}
4445
}),
4546
identify: identify(),
47+
ping: ping(),
4648
kadDht: kadDHT({
4749
protocol: DHT_PROTOCOL,
4850
peerInfoMapper: passthroughMapper,
@@ -66,6 +68,7 @@ describe('circuit-relay discovery', () => {
6668
],
6769
services: {
6870
identify: identify(),
71+
ping: ping(),
6972
kadDht: kadDHT({
7073
protocol: DHT_PROTOCOL,
7174
peerInfoMapper: passthroughMapper,
@@ -108,6 +111,7 @@ describe('circuit-relay discovery', () => {
108111
],
109112
services: {
110113
identify: identify(),
114+
ping: ping(),
111115
kadDht: kadDHT({
112116
protocol: DHT_PROTOCOL,
113117
peerInfoMapper: passthroughMapper,
@@ -133,6 +137,7 @@ describe('circuit-relay discovery', () => {
133137
],
134138
services: {
135139
identify: identify(),
140+
ping: ping(),
136141
kadDht: kadDHT({
137142
protocol: DHT_PROTOCOL,
138143
peerInfoMapper: passthroughMapper,

packages/integration-tests/test/dht.node.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
/* eslint-env mocha */
22

33
import { yamux } from '@chainsafe/libp2p-yamux'
4+
import { identify, type Identify } from '@libp2p/identify'
45
import { kadDHT, passthroughMapper } from '@libp2p/kad-dht'
56
import { mplex } from '@libp2p/mplex'
7+
import { ping } from '@libp2p/ping'
68
import { plaintext } from '@libp2p/plaintext'
79
import { tcp } from '@libp2p/tcp'
810
import { multiaddr } from '@multiformats/multiaddr'
@@ -13,6 +15,7 @@ import pWaitFor from 'p-wait-for'
1315
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
1416
import type { Libp2p, PeerId } from '@libp2p/interface'
1517
import type { KadDHT } from '@libp2p/kad-dht'
18+
import type { PingService } from '@libp2p/ping'
1619
import type { Multiaddr } from '@multiformats/multiaddr'
1720
import type { Libp2pOptions } from 'libp2p'
1821

@@ -62,7 +65,9 @@ describe('DHT subsystem operates correctly', () => {
6265
protocol: subsystemMulticodecs[0],
6366
peerInfoMapper: passthroughMapper,
6467
allowQueryWithZeroPeers: true
65-
})
68+
}),
69+
ping: ping(),
70+
identify: identify()
6671
}
6772
})
6873

@@ -85,7 +90,9 @@ describe('DHT subsystem operates correctly', () => {
8590
protocol: subsystemMulticodecs[0],
8691
peerInfoMapper: passthroughMapper,
8792
allowQueryWithZeroPeers: true
88-
})
93+
}),
94+
ping: ping(),
95+
identify: identify()
8996
}
9097
})
9198

@@ -145,7 +152,7 @@ describe('DHT subsystem operates correctly', () => {
145152
it('kad-dht should discover other peers', async () => {
146153
const deferred = pDefer()
147154

148-
const getConfig = (): Libp2pOptions<{ dht: KadDHT }> => ({
155+
const getConfig = (): Libp2pOptions<{ dht: KadDHT, ping: PingService, identify: Identify }> => ({
149156
addresses: {
150157
listen: [
151158
listenAddr.toString()
@@ -156,7 +163,9 @@ describe('DHT subsystem operates correctly', () => {
156163
protocol: subsystemMulticodecs[0],
157164
peerInfoMapper: passthroughMapper,
158165
allowQueryWithZeroPeers: true
159-
})
166+
}),
167+
ping: ping(),
168+
identify: identify()
160169
}
161170
})
162171

packages/integration-tests/test/interop.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import { privateKeyFromProtobuf } from '@libp2p/crypto/keys'
77
import { createClient } from '@libp2p/daemon-client'
88
import { createServer } from '@libp2p/daemon-server'
99
import { floodsub } from '@libp2p/floodsub'
10-
import { identify } from '@libp2p/identify'
10+
import { identify, type Identify } from '@libp2p/identify'
1111
import { UnsupportedError, interopTests } from '@libp2p/interop'
1212
import { kadDHT, passthroughMapper } from '@libp2p/kad-dht'
1313
import { logger } from '@libp2p/logger'
1414
import { mplex } from '@libp2p/mplex'
15+
import { ping } from '@libp2p/ping'
1516
import { plaintext } from '@libp2p/plaintext'
1617
import { tcp } from '@libp2p/tcp'
1718
import { tls } from '@libp2p/tls'
@@ -23,6 +24,7 @@ import { createLibp2p, type Libp2pOptions, type ServiceFactoryMap } from 'libp2p
2324
import pDefer from 'p-defer'
2425
import type { ServiceMap, PrivateKey } from '@libp2p/interface'
2526
import type { SpawnOptions, Daemon, DaemonFactory } from '@libp2p/interop'
27+
import type { PingService } from '@libp2p/ping'
2628

2729
/**
2830
* @packageDocumentation
@@ -155,8 +157,9 @@ async function createJsPeer (options: SpawnOptions): Promise<Daemon> {
155157
throw new UnsupportedError()
156158
}
157159

158-
const services: ServiceFactoryMap = {
159-
identify: identify()
160+
const services: ServiceFactoryMap<{ identify: Identify, ping: PingService } & Record<string, any>> = {
161+
identify: identify(),
162+
ping: ping()
160163
}
161164

162165
if (options.encryption === 'tls') {

packages/kad-dht/README.md

+20-4
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,16 @@ The Kademlia DHT allow for several operations such as finding peers, searching f
3434
import { kadDHT } from '@libp2p/kad-dht'
3535
import { createLibp2p } from 'libp2p'
3636
import { peerIdFromString } from '@libp2p/peer-id'
37+
import { ping } from '@libp2p/ping'
38+
import { identify } from '@libp2p/identify'
3739

3840
const node = await createLibp2p({
3941
services: {
4042
dht: kadDHT({
4143
// DHT options
42-
})
44+
}),
45+
ping: ping(),
46+
identify: identify()
4347
}
4448
})
4549

@@ -59,13 +63,17 @@ If you are trying to access content on the public internet, this is the implemen
5963
import { kadDHT, removePrivateAddressesMapper } from '@libp2p/kad-dht'
6064
import { createLibp2p } from 'libp2p'
6165
import { peerIdFromString } from '@libp2p/peer-id'
66+
import { ping } from '@libp2p/ping'
67+
import { identify } from '@libp2p/identify'
6268

6369
const node = await createLibp2p({
6470
services: {
6571
aminoDHT: kadDHT({
6672
protocol: '/ipfs/kad/1.0.0',
6773
peerInfoMapper: removePrivateAddressesMapper
68-
})
74+
}),
75+
ping: ping(),
76+
identify: identify()
6977
}
7078
})
7179

@@ -85,14 +93,18 @@ This is for use when peers are on the local area network.
8593
import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
8694
import { createLibp2p } from 'libp2p'
8795
import { peerIdFromString } from '@libp2p/peer-id'
96+
import { ping } from '@libp2p/ping'
97+
import { identify } from '@libp2p/identify'
8898

8999
const node = await createLibp2p({
90100
services: {
91101
lanDHT: kadDHT({
92102
protocol: '/ipfs/lan/kad/1.0.0',
93103
peerInfoMapper: removePublicAddressesMapper,
94104
clientMode: false
95-
})
105+
}),
106+
ping: ping(),
107+
identify: identify()
96108
}
97109
})
98110

@@ -111,6 +123,8 @@ log prefixes to ensure that data is kept separate for each instance.
111123
import { kadDHT, removePublicAddressesMapper, removePrivateAddressesMapper } from '@libp2p/kad-dht'
112124
import { createLibp2p } from 'libp2p'
113125
import { peerIdFromString } from '@libp2p/peer-id'
126+
import { ping } from '@libp2p/ping'
127+
import { identify } from '@libp2p/identify'
114128

115129
const node = await createLibp2p({
116130
services: {
@@ -128,7 +142,9 @@ const node = await createLibp2p({
128142
logPrefix: 'libp2p:dht-amino',
129143
datastorePrefix: '/dht-amino',
130144
metricsPrefix: 'libp2p_dht_amino'
131-
})
145+
}),
146+
ping: ping(),
147+
identify: identify()
132148
}
133149
})
134150

packages/kad-dht/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"@libp2p/interface-internal": "^2.3.9",
6363
"@libp2p/peer-collections": "^6.0.25",
6464
"@libp2p/peer-id": "^5.1.0",
65+
"@libp2p/ping": "^2.0.27",
6566
"@libp2p/record": "^4.0.5",
6667
"@libp2p/utils": "^6.6.0",
6768
"@multiformats/multiaddr": "^12.3.3",

packages/kad-dht/src/index.ts

+22-4
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@
1111
* import { kadDHT } from '@libp2p/kad-dht'
1212
* import { createLibp2p } from 'libp2p'
1313
* import { peerIdFromString } from '@libp2p/peer-id'
14+
* import { ping } from '@libp2p/ping'
15+
* import { identify } from '@libp2p/identify'
1416
*
1517
* const node = await createLibp2p({
1618
* services: {
1719
* dht: kadDHT({
1820
* // DHT options
19-
* })
21+
* }),
22+
* ping: ping(),
23+
* identify: identify()
2024
* }
2125
* })
2226
*
@@ -36,13 +40,17 @@
3640
* import { kadDHT, removePrivateAddressesMapper } from '@libp2p/kad-dht'
3741
* import { createLibp2p } from 'libp2p'
3842
* import { peerIdFromString } from '@libp2p/peer-id'
43+
* import { ping } from '@libp2p/ping'
44+
* import { identify } from '@libp2p/identify'
3945
*
4046
* const node = await createLibp2p({
4147
* services: {
4248
* aminoDHT: kadDHT({
4349
* protocol: '/ipfs/kad/1.0.0',
4450
* peerInfoMapper: removePrivateAddressesMapper
45-
* })
51+
* }),
52+
* ping: ping(),
53+
* identify: identify()
4654
* }
4755
* })
4856
*
@@ -62,14 +70,18 @@
6270
* import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
6371
* import { createLibp2p } from 'libp2p'
6472
* import { peerIdFromString } from '@libp2p/peer-id'
73+
* import { ping } from '@libp2p/ping'
74+
* import { identify } from '@libp2p/identify'
6575
*
6676
* const node = await createLibp2p({
6777
* services: {
6878
* lanDHT: kadDHT({
6979
* protocol: '/ipfs/lan/kad/1.0.0',
7080
* peerInfoMapper: removePublicAddressesMapper,
7181
* clientMode: false
72-
* })
82+
* }),
83+
* ping: ping(),
84+
* identify: identify()
7385
* }
7486
* })
7587
*
@@ -88,6 +100,8 @@
88100
* import { kadDHT, removePublicAddressesMapper, removePrivateAddressesMapper } from '@libp2p/kad-dht'
89101
* import { createLibp2p } from 'libp2p'
90102
* import { peerIdFromString } from '@libp2p/peer-id'
103+
* import { ping } from '@libp2p/ping'
104+
* import { identify } from '@libp2p/identify'
91105
*
92106
* const node = await createLibp2p({
93107
* services: {
@@ -105,7 +119,9 @@
105119
* logPrefix: 'libp2p:dht-amino',
106120
* datastorePrefix: '/dht-amino',
107121
* metricsPrefix: 'libp2p_dht_amino'
108-
* })
122+
* }),
123+
* ping: ping(),
124+
* identify: identify()
109125
* }
110126
* })
111127
*
@@ -121,6 +137,7 @@ import { MessageType } from './message/dht.js'
121137
import { removePrivateAddressesMapper, removePublicAddressesMapper, passthroughMapper } from './utils.js'
122138
import type { Libp2pEvents, ComponentLogger, TypedEventTarget, Metrics, PeerId, PeerInfo, PeerStore, RoutingOptions, PrivateKey } from '@libp2p/interface'
123139
import type { AddressManager, ConnectionManager, Registrar } from '@libp2p/interface-internal'
140+
import type { Ping } from '@libp2p/ping'
124141
import type { AdaptiveTimeoutInit } from '@libp2p/utils/src/adaptive-timeout.js'
125142
import type { Datastore } from 'interface-datastore'
126143
import type { CID } from 'multiformats/cid'
@@ -617,6 +634,7 @@ export interface KadDHTComponents {
617634
datastore: Datastore
618635
events: TypedEventTarget<Libp2pEvents>
619636
logger: ComponentLogger
637+
ping: Ping
620638
}
621639

622640
/**

packages/kad-dht/src/kad-dht.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ export class KadDHT extends TypedEventEmitter<PeerDiscoveryEvents> implements Ka
366366
]
367367

368368
readonly [serviceDependencies]: string[] = [
369-
'@libp2p/identify'
369+
'@libp2p/identify',
370+
'@libp2p/ping'
370371
]
371372

372373
get [contentRoutingSymbol] (): ContentRouting {

packages/kad-dht/src/routing-table/index.ts

+8-18
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ import { AdaptiveTimeout } from '@libp2p/utils/adaptive-timeout'
33
import { PeerQueue } from '@libp2p/utils/peer-queue'
44
import { anySignal } from 'any-signal'
55
import parallel from 'it-parallel'
6-
import { EventTypes } from '../index.js'
7-
import { MessageType } from '../message/dht.js'
86
import * as utils from '../utils.js'
97
import { ClosestPeers } from './closest-peers.js'
108
import { KBucket, isLeafBucket } from './k-bucket.js'
119
import type { Bucket, LeafBucket, Peer } from './k-bucket.js'
1210
import type { Network } from '../network.js'
1311
import type { AbortOptions, ComponentLogger, CounterGroup, Logger, Metric, Metrics, PeerId, PeerStore, Startable, Stream } from '@libp2p/interface'
12+
import type { Ping } from '@libp2p/ping'
1413
import type { AdaptiveTimeoutInit } from '@libp2p/utils/adaptive-timeout'
1514

1615
export const KBUCKET_SIZE = 20
@@ -59,6 +58,7 @@ export interface RoutingTableComponents {
5958
peerStore: PeerStore
6059
metrics?: Metrics
6160
logger: ComponentLogger
61+
ping: Ping
6262
}
6363

6464
export interface RoutingTableEvents {
@@ -379,24 +379,14 @@ export class RoutingTable extends TypedEventEmitter<RoutingTableEvents> implemen
379379

380380
try {
381381
this.log('pinging contact %p', contact.peerId)
382+
await this.components.ping.ping(contact.peerId, options)
383+
this.log('contact %p ping ok', contact.peerId)
382384

383-
for await (const event of this.network.sendRequest(contact.peerId, { type: MessageType.PING }, options)) {
384-
if (event.type === EventTypes.PEER_RESPONSE) {
385-
if (event.messageType === MessageType.PING) {
386-
this.log('contact %p ping ok', contact.peerId)
387-
388-
this.safeDispatchEvent('peer:ping', {
389-
detail: contact.peerId
390-
})
391-
392-
return true
393-
}
394-
395-
return false
396-
}
397-
}
385+
this.safeDispatchEvent('peer:ping', {
386+
detail: contact.peerId
387+
})
398388

399-
return false
389+
return true
400390
} catch (err: any) {
401391
this.log('error pinging old contact %p - %e', contact.peerId, err)
402392
stream?.abort(err)

0 commit comments

Comments
 (0)