@libp2p/kad-dht 15.0.2-32627c876 → 15.0.2-3df5bf2da
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +4 -4
- package/dist/src/constants.d.ts +1 -1
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +1 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/content-fetching/index.d.ts.map +1 -1
- package/dist/src/content-fetching/index.js +26 -6
- package/dist/src/content-fetching/index.js.map +1 -1
- package/dist/src/content-routing/index.d.ts.map +1 -1
- package/dist/src/content-routing/index.js +84 -38
- package/dist/src/content-routing/index.js.map +1 -1
- package/dist/src/index.d.ts +55 -10
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/kad-dht.d.ts +3 -1
- package/dist/src/kad-dht.d.ts.map +1 -1
- package/dist/src/kad-dht.js +12 -8
- package/dist/src/kad-dht.js.map +1 -1
- package/dist/src/network.d.ts +3 -5
- package/dist/src/network.d.ts.map +1 -1
- package/dist/src/network.js +10 -8
- package/dist/src/network.js.map +1 -1
- package/dist/src/peer-distance-list.d.ts +4 -3
- package/dist/src/peer-distance-list.d.ts.map +1 -1
- package/dist/src/peer-distance-list.js +9 -2
- package/dist/src/peer-distance-list.js.map +1 -1
- package/dist/src/peer-routing/index.d.ts +7 -5
- package/dist/src/peer-routing/index.d.ts.map +1 -1
- package/dist/src/peer-routing/index.js +57 -45
- package/dist/src/peer-routing/index.js.map +1 -1
- package/dist/src/providers.js +4 -4
- package/dist/src/providers.js.map +1 -1
- package/dist/src/query/events.d.ts +17 -6
- package/dist/src/query/events.d.ts.map +1 -1
- package/dist/src/query/events.js +18 -0
- package/dist/src/query/events.js.map +1 -1
- package/dist/src/query/manager.d.ts +0 -4
- package/dist/src/query/manager.d.ts.map +1 -1
- package/dist/src/query/manager.js +20 -9
- package/dist/src/query/manager.js.map +1 -1
- package/dist/src/query/query-path.d.ts +7 -11
- package/dist/src/query/query-path.d.ts.map +1 -1
- package/dist/src/query/query-path.js +67 -45
- package/dist/src/query/query-path.js.map +1 -1
- package/dist/src/query/types.d.ts +6 -5
- package/dist/src/query/types.d.ts.map +1 -1
- package/dist/src/rpc/handlers/get-providers.js +1 -1
- package/dist/src/rpc/handlers/get-providers.js.map +1 -1
- package/dist/src/utils.d.ts +1 -0
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +4 -0
- package/dist/src/utils.js.map +1 -1
- package/package.json +13 -12
- package/src/constants.ts +1 -1
- package/src/content-fetching/index.ts +26 -6
- package/src/content-routing/index.ts +91 -47
- package/src/index.ts +62 -10
- package/src/kad-dht.ts +12 -8
- package/src/network.ts +18 -12
- package/src/peer-distance-list.ts +13 -3
- package/src/peer-routing/index.ts +61 -48
- package/src/providers.ts +4 -4
- package/src/query/events.ts +41 -6
- package/src/query/manager.ts +23 -14
- package/src/query/query-path.ts +83 -65
- package/src/query/types.ts +7 -5
- package/src/rpc/handlers/get-providers.ts +1 -1
- package/src/utils.ts +9 -0
package/src/network.ts
CHANGED
|
@@ -7,9 +7,10 @@ import { fromPbPeerInfo } from './message/utils.js'
|
|
|
7
7
|
import {
|
|
8
8
|
sendQueryEvent,
|
|
9
9
|
peerResponseEvent,
|
|
10
|
-
queryErrorEvent
|
|
10
|
+
queryErrorEvent,
|
|
11
|
+
dialPeerEvent
|
|
11
12
|
} from './query/events.js'
|
|
12
|
-
import type { KadDHTComponents, QueryEvent } from './index.js'
|
|
13
|
+
import type { DisjointPath, KadDHTComponents, QueryEvent } from './index.js'
|
|
13
14
|
import type { AbortOptions, Logger, Stream, PeerId, PeerInfo, Startable, RoutingOptions, CounterGroup } from '@libp2p/interface'
|
|
14
15
|
|
|
15
16
|
export interface NetworkInit {
|
|
@@ -29,7 +30,7 @@ export interface SendMessageOptions extends RoutingOptions {
|
|
|
29
30
|
* this option is which index within `k` this message is for, and it
|
|
30
31
|
* allows observers to collate events together on a per-path basis
|
|
31
32
|
*/
|
|
32
|
-
path:
|
|
33
|
+
path: DisjointPath
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
/**
|
|
@@ -161,9 +162,6 @@ export class Network extends TypedEventEmitter<NetworkEvents> implements Startab
|
|
|
161
162
|
throw new InvalidParametersError('Message type was missing')
|
|
162
163
|
}
|
|
163
164
|
|
|
164
|
-
this.log('sending %s to %p', msg.type, to)
|
|
165
|
-
yield sendQueryEvent({ to, type, path: options.path }, options)
|
|
166
|
-
|
|
167
165
|
let stream: Stream | undefined
|
|
168
166
|
const signal = this.timeout.getTimeoutSignal(options)
|
|
169
167
|
|
|
@@ -175,8 +173,15 @@ export class Network extends TypedEventEmitter<NetworkEvents> implements Startab
|
|
|
175
173
|
try {
|
|
176
174
|
this.metrics.operations?.increment({ [type]: true })
|
|
177
175
|
|
|
176
|
+
this.log('dialling %p', to)
|
|
177
|
+
yield dialPeerEvent({ peer: to, path: options.path }, options)
|
|
178
|
+
|
|
178
179
|
const connection = await this.components.connectionManager.openConnection(to, options)
|
|
179
180
|
stream = await connection.newStream(this.protocol, options)
|
|
181
|
+
|
|
182
|
+
this.log('sending %s to %p', msg.type, to)
|
|
183
|
+
yield sendQueryEvent({ to, type, path: options.path }, options)
|
|
184
|
+
|
|
180
185
|
const response = await this._writeReadMessage(stream, msg, options)
|
|
181
186
|
|
|
182
187
|
stream.close(options)
|
|
@@ -224,9 +229,6 @@ export class Network extends TypedEventEmitter<NetworkEvents> implements Startab
|
|
|
224
229
|
throw new InvalidParametersError('Message type was missing')
|
|
225
230
|
}
|
|
226
231
|
|
|
227
|
-
this.log('sending %s to %p', msg.type, to)
|
|
228
|
-
yield sendQueryEvent({ to, type, path: options.path }, options)
|
|
229
|
-
|
|
230
232
|
let stream: Stream | undefined
|
|
231
233
|
const signal = this.timeout.getTimeoutSignal(options)
|
|
232
234
|
|
|
@@ -238,9 +240,15 @@ export class Network extends TypedEventEmitter<NetworkEvents> implements Startab
|
|
|
238
240
|
try {
|
|
239
241
|
this.metrics.operations?.increment({ [type]: true })
|
|
240
242
|
|
|
243
|
+
this.log('dialling %p', to)
|
|
244
|
+
yield dialPeerEvent({ peer: to, path: options.path }, options)
|
|
245
|
+
|
|
241
246
|
const connection = await this.components.connectionManager.openConnection(to, options)
|
|
242
247
|
stream = await connection.newStream(this.protocol, options)
|
|
243
248
|
|
|
249
|
+
this.log('sending %s to %p', msg.type, to)
|
|
250
|
+
yield sendQueryEvent({ to, type, path: options.path }, options)
|
|
251
|
+
|
|
244
252
|
await this._writeMessage(stream, msg, options)
|
|
245
253
|
|
|
246
254
|
stream.close(options)
|
|
@@ -269,9 +277,7 @@ export class Network extends TypedEventEmitter<NetworkEvents> implements Startab
|
|
|
269
277
|
}
|
|
270
278
|
|
|
271
279
|
/**
|
|
272
|
-
* Write a message and read
|
|
273
|
-
* If no response is received after the specified timeout
|
|
274
|
-
* this will error out.
|
|
280
|
+
* Write a message and read a response
|
|
275
281
|
*/
|
|
276
282
|
async _writeReadMessage (stream: Stream, msg: Partial<Message>, options: AbortOptions): Promise<Message> {
|
|
277
283
|
const pb = pbStream(stream)
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { xor as uint8ArrayXor } from 'uint8arrays/xor'
|
|
2
2
|
import { xorCompare as uint8ArrayXorCompare } from 'uint8arrays/xor-compare'
|
|
3
3
|
import { convertPeerId } from './utils.js'
|
|
4
|
+
import type { DisjointPath } from './index.js'
|
|
4
5
|
import type { PeerId, PeerInfo } from '@libp2p/interface'
|
|
5
6
|
|
|
6
7
|
interface PeerDistance {
|
|
7
8
|
peer: PeerInfo
|
|
8
9
|
distance: Uint8Array
|
|
9
|
-
path:
|
|
10
|
+
path: DisjointPath
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -48,7 +49,7 @@ export class PeerDistanceList {
|
|
|
48
49
|
/**
|
|
49
50
|
* Add a peerId to the list.
|
|
50
51
|
*/
|
|
51
|
-
async add (peer: PeerInfo, path:
|
|
52
|
+
async add (peer: PeerInfo, path: DisjointPath = { index: -1, queued: 0, running: 0, total: 0 }): Promise<void> {
|
|
52
53
|
const dhtKey = await convertPeerId(peer.id)
|
|
53
54
|
|
|
54
55
|
this.addWithKadId(peer, dhtKey, path)
|
|
@@ -57,7 +58,7 @@ export class PeerDistanceList {
|
|
|
57
58
|
/**
|
|
58
59
|
* Add a peerId to the list.
|
|
59
60
|
*/
|
|
60
|
-
addWithKadId (peer: PeerInfo, kadId: Uint8Array, path:
|
|
61
|
+
addWithKadId (peer: PeerInfo, kadId: Uint8Array, path: DisjointPath = { index: -1, queued: 0, running: 0, total: 0 }): void {
|
|
61
62
|
if (this.peerDistances.find(pd => pd.peer.id.equals(peer.id)) != null) {
|
|
62
63
|
return
|
|
63
64
|
}
|
|
@@ -68,6 +69,15 @@ export class PeerDistanceList {
|
|
|
68
69
|
path
|
|
69
70
|
}
|
|
70
71
|
|
|
72
|
+
if (this.peerDistances.length === this.capacity) {
|
|
73
|
+
const lastPeer = this.peerDistances[this.peerDistances.length - 1]
|
|
74
|
+
|
|
75
|
+
// only add if it's closer than our furthest peer
|
|
76
|
+
if (lastPeer != null && uint8ArrayXorCompare(el.distance, lastPeer.distance) !== -1) {
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
71
81
|
let added = false
|
|
72
82
|
|
|
73
83
|
for (let j = 0; j < this.peerDistances.length; j++) {
|
|
@@ -3,7 +3,6 @@ import { InvalidPublicKeyError, NotFoundError } from '@libp2p/interface'
|
|
|
3
3
|
import { peerIdFromPublicKey, peerIdFromMultihash } from '@libp2p/peer-id'
|
|
4
4
|
import { Libp2pRecord } from '@libp2p/record'
|
|
5
5
|
import * as Digest from 'multiformats/hashes/digest'
|
|
6
|
-
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
7
6
|
import { xor as uint8ArrayXor } from 'uint8arrays/xor'
|
|
8
7
|
import { xorCompare as uint8ArrayXorCompare } from 'uint8arrays/xor-compare'
|
|
9
8
|
import { QueryError, InvalidRecordError } from '../errors.js'
|
|
@@ -23,12 +22,14 @@ import type { QueryManager, QueryOptions } from '../query/manager.js'
|
|
|
23
22
|
import type { QueryFunc } from '../query/types.js'
|
|
24
23
|
import type { RoutingTable } from '../routing-table/index.js'
|
|
25
24
|
import type { ComponentLogger, Logger, Metrics, PeerId, PeerInfo, PeerStore, RoutingOptions } from '@libp2p/interface'
|
|
25
|
+
import type { ConnectionManager } from '@libp2p/interface-internal'
|
|
26
26
|
|
|
27
27
|
export interface PeerRoutingComponents {
|
|
28
28
|
peerId: PeerId
|
|
29
29
|
peerStore: PeerStore
|
|
30
30
|
logger: ComponentLogger
|
|
31
31
|
metrics?: Metrics
|
|
32
|
+
connectionManager: ConnectionManager
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
export interface PeerRoutingInit {
|
|
@@ -45,16 +46,14 @@ export class PeerRouting {
|
|
|
45
46
|
private readonly network: Network
|
|
46
47
|
private readonly validators: Validators
|
|
47
48
|
private readonly queryManager: QueryManager
|
|
48
|
-
private readonly
|
|
49
|
-
private readonly peerId: PeerId
|
|
49
|
+
private readonly components: PeerRoutingComponents
|
|
50
50
|
|
|
51
51
|
constructor (components: PeerRoutingComponents, init: PeerRoutingInit) {
|
|
52
52
|
this.routingTable = init.routingTable
|
|
53
53
|
this.network = init.network
|
|
54
54
|
this.validators = init.validators
|
|
55
55
|
this.queryManager = init.queryManager
|
|
56
|
-
this.
|
|
57
|
-
this.peerId = components.peerId
|
|
56
|
+
this.components = components
|
|
58
57
|
this.log = components.logger.forComponent(`${init.logPrefix}:peer-routing`)
|
|
59
58
|
|
|
60
59
|
this.findPeer = components.metrics?.traceFunction('libp2p.kadDHT.findPeer', this.findPeer.bind(this), {
|
|
@@ -77,7 +76,7 @@ export class PeerRouting {
|
|
|
77
76
|
this.log('findPeerLocal found %p in routing table', peer)
|
|
78
77
|
|
|
79
78
|
try {
|
|
80
|
-
peerData = await this.peerStore.get(p)
|
|
79
|
+
peerData = await this.components.peerStore.get(p)
|
|
81
80
|
} catch (err: any) {
|
|
82
81
|
if (err.name !== 'NotFoundError') {
|
|
83
82
|
throw err
|
|
@@ -87,7 +86,7 @@ export class PeerRouting {
|
|
|
87
86
|
|
|
88
87
|
if (peerData == null) {
|
|
89
88
|
try {
|
|
90
|
-
peerData = await this.peerStore.get(peer)
|
|
89
|
+
peerData = await this.components.peerStore.get(peer)
|
|
91
90
|
} catch (err: any) {
|
|
92
91
|
if (err.name !== 'NotFoundError') {
|
|
93
92
|
throw err
|
|
@@ -124,10 +123,16 @@ export class PeerRouting {
|
|
|
124
123
|
*/
|
|
125
124
|
async * getPublicKeyFromNode (peer: PeerId, options: RoutingOptions = {}): AsyncGenerator<QueryEvent> {
|
|
126
125
|
const pkKey = keyForPublicKey(peer)
|
|
126
|
+
const path = {
|
|
127
|
+
index: -1,
|
|
128
|
+
queued: 0,
|
|
129
|
+
running: 0,
|
|
130
|
+
total: 0
|
|
131
|
+
}
|
|
127
132
|
|
|
128
133
|
for await (const event of this._getValueSingle(peer, pkKey, {
|
|
129
134
|
...options,
|
|
130
|
-
path
|
|
135
|
+
path
|
|
131
136
|
})) {
|
|
132
137
|
yield event
|
|
133
138
|
|
|
@@ -146,7 +151,8 @@ export class PeerRouting {
|
|
|
146
151
|
|
|
147
152
|
yield valueEvent({
|
|
148
153
|
from: peer,
|
|
149
|
-
value: event.record.value
|
|
154
|
+
value: event.record.value,
|
|
155
|
+
path
|
|
150
156
|
}, options)
|
|
151
157
|
}
|
|
152
158
|
}
|
|
@@ -168,9 +174,14 @@ export class PeerRouting {
|
|
|
168
174
|
if (pi != null) {
|
|
169
175
|
this.log('found local')
|
|
170
176
|
yield finalPeerEvent({
|
|
171
|
-
from: this.peerId,
|
|
177
|
+
from: this.components.peerId,
|
|
172
178
|
peer: pi,
|
|
173
|
-
path:
|
|
179
|
+
path: {
|
|
180
|
+
index: -1,
|
|
181
|
+
queued: 0,
|
|
182
|
+
running: 0,
|
|
183
|
+
total: 0
|
|
184
|
+
}
|
|
174
185
|
}, options)
|
|
175
186
|
return
|
|
176
187
|
}
|
|
@@ -187,7 +198,7 @@ export class PeerRouting {
|
|
|
187
198
|
key: id.toMultihash().bytes
|
|
188
199
|
}
|
|
189
200
|
|
|
190
|
-
for await (const event of self.network.sendRequest(peer, request, {
|
|
201
|
+
for await (const event of self.network.sendRequest(peer.id, request, {
|
|
191
202
|
...options,
|
|
192
203
|
signal,
|
|
193
204
|
path
|
|
@@ -219,58 +230,64 @@ export class PeerRouting {
|
|
|
219
230
|
}
|
|
220
231
|
|
|
221
232
|
if (!foundPeer) {
|
|
222
|
-
|
|
223
|
-
from: this.peerId,
|
|
224
|
-
error: new NotFoundError('Not found')
|
|
225
|
-
}, options)
|
|
233
|
+
throw new NotFoundError('Not found')
|
|
226
234
|
}
|
|
227
235
|
}
|
|
228
236
|
|
|
229
237
|
/**
|
|
230
|
-
* Kademlia 'FIND_NODE' operation on a key, which could be the bytes from
|
|
231
|
-
*
|
|
238
|
+
* Kademlia 'FIND_NODE' operation on a key, which could be the bytes from a
|
|
239
|
+
* multihash or a peer ID
|
|
232
240
|
*/
|
|
233
241
|
async * getClosestPeers (key: Uint8Array, options: QueryOptions = {}): AsyncGenerator<QueryEvent> {
|
|
234
242
|
this.log('getClosestPeers to %b', key)
|
|
235
243
|
const kadId = await convertBuffer(key)
|
|
236
|
-
const tablePeers = this.routingTable.closestPeers(kadId)
|
|
237
|
-
const self = this // eslint-disable-line @typescript-eslint/no-this-alias
|
|
238
|
-
|
|
239
244
|
const peers = new PeerDistanceList(kadId, this.routingTable.kBucketSize)
|
|
240
|
-
|
|
245
|
+
const self = this // eslint-disable-line @typescript-eslint/no-this-alias
|
|
241
246
|
|
|
242
|
-
const getCloserPeersQuery: QueryFunc = async function * ({ peer,
|
|
243
|
-
self.log('
|
|
247
|
+
const getCloserPeersQuery: QueryFunc = async function * ({ peer, path, peerKadId, signal }) {
|
|
248
|
+
self.log('getClosestPeers asking %p', peer)
|
|
244
249
|
const request: Partial<Message> = {
|
|
245
250
|
type: MessageType.FIND_NODE,
|
|
246
251
|
key
|
|
247
252
|
}
|
|
248
253
|
|
|
249
|
-
yield * self.network.sendRequest(peer, request, {
|
|
254
|
+
yield * self.network.sendRequest(peer.id, request, {
|
|
250
255
|
...options,
|
|
251
256
|
signal,
|
|
252
257
|
path
|
|
253
258
|
})
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
for await (const event of this.queryManager.run(key, getCloserPeersQuery, options)) {
|
|
257
|
-
if (event.name === 'PEER_RESPONSE') {
|
|
258
|
-
await Promise.all(event.closer.map(async peerData => {
|
|
259
|
-
await peers.add(peerData, event.path)
|
|
260
|
-
}))
|
|
261
|
-
}
|
|
262
259
|
|
|
263
|
-
|
|
260
|
+
// add the peer to the list if we've managed to contact it successfully
|
|
261
|
+
peers.addWithKadId(peer, peerKadId, path)
|
|
264
262
|
}
|
|
265
263
|
|
|
264
|
+
yield * this.queryManager.run(key, getCloserPeersQuery, options)
|
|
265
|
+
|
|
266
266
|
this.log('found %d peers close to %b', peers.length, key)
|
|
267
267
|
|
|
268
|
-
for (
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
268
|
+
for (let { peer, path } of peers.peers) {
|
|
269
|
+
try {
|
|
270
|
+
if (peer.multiaddrs.length === 0) {
|
|
271
|
+
peer = await self.components.peerStore.getInfo(peer.id)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (peer.multiaddrs.length === 0) {
|
|
275
|
+
continue
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
yield finalPeerEvent({
|
|
279
|
+
from: this.components.peerId,
|
|
280
|
+
peer: await self.components.peerStore.getInfo(peer.id),
|
|
281
|
+
path: {
|
|
282
|
+
index: path.index,
|
|
283
|
+
queued: 0,
|
|
284
|
+
running: 0,
|
|
285
|
+
total: 0
|
|
286
|
+
}
|
|
287
|
+
}, options)
|
|
288
|
+
} catch {
|
|
289
|
+
continue
|
|
290
|
+
}
|
|
274
291
|
}
|
|
275
292
|
}
|
|
276
293
|
|
|
@@ -318,7 +335,8 @@ export class PeerRouting {
|
|
|
318
335
|
}
|
|
319
336
|
|
|
320
337
|
/**
|
|
321
|
-
* Get the
|
|
338
|
+
* Get the peers in our routing table that are closer than the passed PeerId
|
|
339
|
+
* to the passed key
|
|
322
340
|
*/
|
|
323
341
|
async getCloserPeersOffline (key: Uint8Array, closerThan: PeerId): Promise<PeerInfo[]> {
|
|
324
342
|
const output: PeerInfo[] = []
|
|
@@ -328,7 +346,7 @@ export class PeerRouting {
|
|
|
328
346
|
const multihash = Digest.decode(key)
|
|
329
347
|
const targetPeerId = peerIdFromMultihash(multihash)
|
|
330
348
|
|
|
331
|
-
const peer = await this.peerStore.get(targetPeerId)
|
|
349
|
+
const peer = await this.components.peerStore.get(targetPeerId)
|
|
332
350
|
|
|
333
351
|
output.push({
|
|
334
352
|
id: peer.id,
|
|
@@ -351,12 +369,7 @@ export class PeerRouting {
|
|
|
351
369
|
}
|
|
352
370
|
|
|
353
371
|
try {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
output.push({
|
|
357
|
-
id: peerId,
|
|
358
|
-
multiaddrs: peer.addresses.map(({ multiaddr }) => multiaddr)
|
|
359
|
-
})
|
|
372
|
+
output.push(await this.components.peerStore.getInfo(peerId))
|
|
360
373
|
} catch (err: any) {
|
|
361
374
|
if (err.name !== 'NotFoundError') {
|
|
362
375
|
throw err
|
package/src/providers.ts
CHANGED
|
@@ -41,7 +41,7 @@ export class Providers {
|
|
|
41
41
|
const release = await this.lock.readLock()
|
|
42
42
|
|
|
43
43
|
try {
|
|
44
|
-
this.log('%p provides %s', provider, cid)
|
|
44
|
+
this.log.trace('%p provides %s', provider, cid)
|
|
45
45
|
await this.writeProviderEntry(cid, provider)
|
|
46
46
|
} finally {
|
|
47
47
|
release()
|
|
@@ -56,7 +56,7 @@ export class Providers {
|
|
|
56
56
|
|
|
57
57
|
try {
|
|
58
58
|
const key = toProviderKey(this.datastorePrefix, cid, provider)
|
|
59
|
-
this.log('%p no longer provides %s', provider, cid)
|
|
59
|
+
this.log.trace('%p no longer provides %s', provider, cid)
|
|
60
60
|
await this.datastore.delete(key)
|
|
61
61
|
} finally {
|
|
62
62
|
release()
|
|
@@ -70,9 +70,9 @@ export class Providers {
|
|
|
70
70
|
const release = await this.lock.readLock()
|
|
71
71
|
|
|
72
72
|
try {
|
|
73
|
-
this.log('get providers for %c', cid)
|
|
73
|
+
this.log.trace('get providers for %c', cid)
|
|
74
74
|
const provs = await this.loadProviders(cid, options)
|
|
75
|
-
this.log('got %d providers for %c', provs.size, cid)
|
|
75
|
+
this.log.trace('got %d providers for %c', provs.size, cid)
|
|
76
76
|
|
|
77
77
|
return [...provs.keys()]
|
|
78
78
|
} finally {
|
package/src/query/events.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MessageType, SendQueryEvent, PeerResponseEvent, AddPeerEvent, ValueEvent, ProviderEvent, QueryErrorEvent, FinalPeerEvent } from '../index.js'
|
|
1
|
+
import type { MessageType, SendQueryEvent, PeerResponseEvent, AddPeerEvent, ValueEvent, ProviderEvent, QueryErrorEvent, FinalPeerEvent, DisjointPath, PathEndedEvent, DialPeerEvent } from '../index.js'
|
|
2
2
|
import type { PeerId, PeerInfo } from '@libp2p/interface'
|
|
3
3
|
import type { Libp2pRecord } from '@libp2p/record'
|
|
4
4
|
import type { ProgressOptions } from 'progress-events'
|
|
@@ -6,7 +6,7 @@ import type { ProgressOptions } from 'progress-events'
|
|
|
6
6
|
export interface QueryEventFields {
|
|
7
7
|
to: PeerId
|
|
8
8
|
type: MessageType
|
|
9
|
-
path:
|
|
9
|
+
path: DisjointPath
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function sendQueryEvent (fields: QueryEventFields, options: ProgressOptions = {}): SendQueryEvent {
|
|
@@ -26,7 +26,7 @@ export function sendQueryEvent (fields: QueryEventFields, options: ProgressOptio
|
|
|
26
26
|
export interface PeerResponseEventFields {
|
|
27
27
|
from: PeerId
|
|
28
28
|
messageType: MessageType
|
|
29
|
-
path:
|
|
29
|
+
path: DisjointPath
|
|
30
30
|
closer?: PeerInfo[]
|
|
31
31
|
providers?: PeerInfo[]
|
|
32
32
|
record?: Libp2pRecord
|
|
@@ -50,7 +50,7 @@ export function peerResponseEvent (fields: PeerResponseEventFields, options: Pro
|
|
|
50
50
|
export interface FinalPeerEventFields {
|
|
51
51
|
from: PeerId
|
|
52
52
|
peer: PeerInfo
|
|
53
|
-
path:
|
|
53
|
+
path: DisjointPath
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
export function finalPeerEvent (fields: FinalPeerEventFields, options: ProgressOptions = {}): FinalPeerEvent {
|
|
@@ -68,7 +68,7 @@ export function finalPeerEvent (fields: FinalPeerEventFields, options: ProgressO
|
|
|
68
68
|
export interface ErrorEventFields {
|
|
69
69
|
from: PeerId
|
|
70
70
|
error: Error
|
|
71
|
-
path
|
|
71
|
+
path: DisjointPath
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export function queryErrorEvent (fields: ErrorEventFields, options: ProgressOptions = {}): QueryErrorEvent {
|
|
@@ -86,6 +86,7 @@ export function queryErrorEvent (fields: ErrorEventFields, options: ProgressOpti
|
|
|
86
86
|
export interface ProviderEventFields {
|
|
87
87
|
from: PeerId
|
|
88
88
|
providers: PeerInfo[]
|
|
89
|
+
path: DisjointPath
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
export function providerEvent (fields: ProviderEventFields, options: ProgressOptions = {}): ProviderEvent {
|
|
@@ -103,6 +104,7 @@ export function providerEvent (fields: ProviderEventFields, options: ProgressOpt
|
|
|
103
104
|
export interface ValueEventFields {
|
|
104
105
|
from: PeerId
|
|
105
106
|
value: Uint8Array
|
|
107
|
+
path: DisjointPath
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
export function valueEvent (fields: ValueEventFields, options: ProgressOptions = {}): ValueEvent {
|
|
@@ -119,7 +121,7 @@ export function valueEvent (fields: ValueEventFields, options: ProgressOptions =
|
|
|
119
121
|
|
|
120
122
|
export interface AddPeerEventFields {
|
|
121
123
|
peer: PeerId
|
|
122
|
-
path:
|
|
124
|
+
path: DisjointPath
|
|
123
125
|
}
|
|
124
126
|
|
|
125
127
|
export function addPeerEvent (fields: AddPeerEventFields, options: ProgressOptions = {}): AddPeerEvent {
|
|
@@ -133,3 +135,36 @@ export function addPeerEvent (fields: AddPeerEventFields, options: ProgressOptio
|
|
|
133
135
|
|
|
134
136
|
return event
|
|
135
137
|
}
|
|
138
|
+
|
|
139
|
+
export interface DialPeerEventFields {
|
|
140
|
+
peer: PeerId
|
|
141
|
+
path: DisjointPath
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function dialPeerEvent (fields: DialPeerEventFields, options: ProgressOptions = {}): DialPeerEvent {
|
|
145
|
+
const event: DialPeerEvent = {
|
|
146
|
+
...fields,
|
|
147
|
+
name: 'DIAL_PEER',
|
|
148
|
+
type: 7
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
options.onProgress?.(new CustomEvent('kad-dht:query:dial-peer', { detail: event }))
|
|
152
|
+
|
|
153
|
+
return event
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface PathEndedEventFields {
|
|
157
|
+
path: DisjointPath
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function pathEndedEvent (fields: PathEndedEventFields, options: ProgressOptions = {}): PathEndedEvent {
|
|
161
|
+
const event: PathEndedEvent = {
|
|
162
|
+
...fields,
|
|
163
|
+
name: 'PATH_ENDED',
|
|
164
|
+
type: 8
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
options.onProgress?.(new CustomEvent('kad-dht:query:path-ended', { detail: event }))
|
|
168
|
+
|
|
169
|
+
return event
|
|
170
|
+
}
|
package/src/query/manager.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
/* eslint-disable complexity */
|
|
1
2
|
import { setMaxListeners } from '@libp2p/interface'
|
|
2
|
-
import {
|
|
3
|
+
import { createScalableCuckooFilter } from '@libp2p/utils/filters'
|
|
3
4
|
import { anySignal } from 'any-signal'
|
|
4
5
|
import merge from 'it-merge'
|
|
5
6
|
import { pEvent } from 'p-event'
|
|
@@ -39,11 +40,6 @@ export interface QueryManagerComponents {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export interface QueryOptions extends RoutingOptions {
|
|
42
|
-
/**
|
|
43
|
-
* A timeout for subqueries executed as part of the main query
|
|
44
|
-
*/
|
|
45
|
-
queryFuncTimeout?: number
|
|
46
|
-
|
|
47
43
|
isSelfQuery?: boolean
|
|
48
44
|
}
|
|
49
45
|
|
|
@@ -161,7 +157,7 @@ export class QueryManager implements Startable {
|
|
|
161
157
|
}
|
|
162
158
|
|
|
163
159
|
if (options.isSelfQuery !== true && this.initialQuerySelfHasRun != null) {
|
|
164
|
-
log('waiting for initial
|
|
160
|
+
log('waiting for initial self query before continuing')
|
|
165
161
|
|
|
166
162
|
await raceSignal(this.initialQuerySelfHasRun.promise, signal)
|
|
167
163
|
|
|
@@ -171,8 +167,22 @@ export class QueryManager implements Startable {
|
|
|
171
167
|
log('query:start')
|
|
172
168
|
|
|
173
169
|
const id = await convertBuffer(key)
|
|
174
|
-
const peers = this.routingTable.closestPeers(id)
|
|
175
|
-
|
|
170
|
+
const peers = this.routingTable.closestPeers(id, this.routingTable.kBucketSize)
|
|
171
|
+
|
|
172
|
+
// split peers into d buckets evenly(ish)
|
|
173
|
+
const peersToQuery = peers.sort(() => {
|
|
174
|
+
if (Math.random() > 0.5) {
|
|
175
|
+
return 1
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return -1
|
|
179
|
+
})
|
|
180
|
+
.reduce((acc: PeerId[][], curr, index) => {
|
|
181
|
+
acc[index % this.disjointPaths].push(curr)
|
|
182
|
+
|
|
183
|
+
return acc
|
|
184
|
+
}, new Array(this.disjointPaths).fill(0).map(() => []))
|
|
185
|
+
.filter(peers => peers.length > 0)
|
|
176
186
|
|
|
177
187
|
if (peers.length === 0) {
|
|
178
188
|
log.error('running query with no peers')
|
|
@@ -180,21 +190,20 @@ export class QueryManager implements Startable {
|
|
|
180
190
|
}
|
|
181
191
|
|
|
182
192
|
// make sure we don't get trapped in a loop
|
|
183
|
-
const peersSeen =
|
|
193
|
+
const peersSeen = createScalableCuckooFilter(1024)
|
|
184
194
|
|
|
185
195
|
// Create query paths from the starting peers
|
|
186
196
|
const paths = peersToQuery.map((peer, index) => {
|
|
187
197
|
return queryPath({
|
|
188
198
|
...options,
|
|
189
199
|
key,
|
|
190
|
-
|
|
200
|
+
startingPeers: peer,
|
|
191
201
|
ourPeerId: this.peerId,
|
|
192
202
|
signal,
|
|
193
203
|
query: queryFunc,
|
|
194
204
|
path: index,
|
|
195
205
|
numPaths: peersToQuery.length,
|
|
196
206
|
alpha: this.alpha,
|
|
197
|
-
queryFuncTimeout: options.queryFuncTimeout,
|
|
198
207
|
log,
|
|
199
208
|
peersSeen,
|
|
200
209
|
onProgress: options.onProgress,
|
|
@@ -223,8 +232,8 @@ export class QueryManager implements Startable {
|
|
|
223
232
|
}
|
|
224
233
|
}
|
|
225
234
|
|
|
226
|
-
yield event
|
|
227
235
|
signal.throwIfAborted()
|
|
236
|
+
yield event
|
|
228
237
|
}
|
|
229
238
|
|
|
230
239
|
queryFinished = true
|
|
@@ -241,7 +250,7 @@ export class QueryManager implements Startable {
|
|
|
241
250
|
|
|
242
251
|
signal.clear()
|
|
243
252
|
|
|
244
|
-
log('query
|
|
253
|
+
log('query finished')
|
|
245
254
|
}
|
|
246
255
|
}
|
|
247
256
|
}
|