@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.
Files changed (70) hide show
  1. package/dist/index.min.js +1 -1
  2. package/dist/index.min.js.map +4 -4
  3. package/dist/src/constants.d.ts +1 -1
  4. package/dist/src/constants.d.ts.map +1 -1
  5. package/dist/src/constants.js +1 -1
  6. package/dist/src/constants.js.map +1 -1
  7. package/dist/src/content-fetching/index.d.ts.map +1 -1
  8. package/dist/src/content-fetching/index.js +26 -6
  9. package/dist/src/content-fetching/index.js.map +1 -1
  10. package/dist/src/content-routing/index.d.ts.map +1 -1
  11. package/dist/src/content-routing/index.js +84 -38
  12. package/dist/src/content-routing/index.js.map +1 -1
  13. package/dist/src/index.d.ts +55 -10
  14. package/dist/src/index.d.ts.map +1 -1
  15. package/dist/src/index.js +1 -0
  16. package/dist/src/index.js.map +1 -1
  17. package/dist/src/kad-dht.d.ts +3 -1
  18. package/dist/src/kad-dht.d.ts.map +1 -1
  19. package/dist/src/kad-dht.js +12 -8
  20. package/dist/src/kad-dht.js.map +1 -1
  21. package/dist/src/network.d.ts +3 -5
  22. package/dist/src/network.d.ts.map +1 -1
  23. package/dist/src/network.js +10 -8
  24. package/dist/src/network.js.map +1 -1
  25. package/dist/src/peer-distance-list.d.ts +4 -3
  26. package/dist/src/peer-distance-list.d.ts.map +1 -1
  27. package/dist/src/peer-distance-list.js +9 -2
  28. package/dist/src/peer-distance-list.js.map +1 -1
  29. package/dist/src/peer-routing/index.d.ts +7 -5
  30. package/dist/src/peer-routing/index.d.ts.map +1 -1
  31. package/dist/src/peer-routing/index.js +57 -45
  32. package/dist/src/peer-routing/index.js.map +1 -1
  33. package/dist/src/providers.js +4 -4
  34. package/dist/src/providers.js.map +1 -1
  35. package/dist/src/query/events.d.ts +17 -6
  36. package/dist/src/query/events.d.ts.map +1 -1
  37. package/dist/src/query/events.js +18 -0
  38. package/dist/src/query/events.js.map +1 -1
  39. package/dist/src/query/manager.d.ts +0 -4
  40. package/dist/src/query/manager.d.ts.map +1 -1
  41. package/dist/src/query/manager.js +20 -9
  42. package/dist/src/query/manager.js.map +1 -1
  43. package/dist/src/query/query-path.d.ts +7 -11
  44. package/dist/src/query/query-path.d.ts.map +1 -1
  45. package/dist/src/query/query-path.js +67 -45
  46. package/dist/src/query/query-path.js.map +1 -1
  47. package/dist/src/query/types.d.ts +6 -5
  48. package/dist/src/query/types.d.ts.map +1 -1
  49. package/dist/src/rpc/handlers/get-providers.js +1 -1
  50. package/dist/src/rpc/handlers/get-providers.js.map +1 -1
  51. package/dist/src/utils.d.ts +1 -0
  52. package/dist/src/utils.d.ts.map +1 -1
  53. package/dist/src/utils.js +4 -0
  54. package/dist/src/utils.js.map +1 -1
  55. package/package.json +13 -12
  56. package/src/constants.ts +1 -1
  57. package/src/content-fetching/index.ts +26 -6
  58. package/src/content-routing/index.ts +91 -47
  59. package/src/index.ts +62 -10
  60. package/src/kad-dht.ts +12 -8
  61. package/src/network.ts +18 -12
  62. package/src/peer-distance-list.ts +13 -3
  63. package/src/peer-routing/index.ts +61 -48
  64. package/src/providers.ts +4 -4
  65. package/src/query/events.ts +41 -6
  66. package/src/query/manager.ts +23 -14
  67. package/src/query/query-path.ts +83 -65
  68. package/src/query/types.ts +7 -5
  69. package/src/rpc/handlers/get-providers.ts +1 -1
  70. package/src/utils.ts +9 -0
@@ -1,15 +1,15 @@
1
- import { setMaxListeners } from '@libp2p/interface'
2
1
  import { Queue } from '@libp2p/utils/queue'
3
- import { anySignal } from 'any-signal'
2
+ import { pushable } from 'it-pushable'
4
3
  import { xor as uint8ArrayXor } from 'uint8arrays/xor'
5
4
  import { xorCompare as uint8ArrayXorCompare } from 'uint8arrays/xor-compare'
5
+ import { QueryAbortedError } from '../errors.js'
6
6
  import { convertPeerId, convertBuffer } from '../utils.js'
7
- import { queryErrorEvent } from './events.js'
7
+ import { pathEndedEvent, queryErrorEvent } from './events.js'
8
8
  import type { QueryEvent } from '../index.js'
9
9
  import type { QueryFunc } from '../query/types.js'
10
- import type { Logger, PeerId, RoutingOptions, AbortOptions } from '@libp2p/interface'
10
+ import type { Logger, PeerId, RoutingOptions, AbortOptions, PeerInfo } from '@libp2p/interface'
11
11
  import type { ConnectionManager } from '@libp2p/interface-internal'
12
- import type { PeerSet } from '@libp2p/peer-collections'
12
+ import type { Filter } from '@libp2p/utils/filters'
13
13
 
14
14
  export interface QueryPathOptions extends RoutingOptions {
15
15
  /**
@@ -20,18 +20,13 @@ export interface QueryPathOptions extends RoutingOptions {
20
20
  /**
21
21
  * Where we start our query
22
22
  */
23
- startingPeer: PeerId
23
+ startingPeers: PeerId[]
24
24
 
25
25
  /**
26
26
  * Who we are
27
27
  */
28
28
  ourPeerId: PeerId
29
29
 
30
- /**
31
- * When to stop querying
32
- */
33
- signal: AbortSignal
34
-
35
30
  /**
36
31
  * The query function to run with each peer
37
32
  */
@@ -52,11 +47,6 @@ export interface QueryPathOptions extends RoutingOptions {
52
47
  */
53
48
  numPaths: number
54
49
 
55
- /**
56
- * A timeout for queryFunc in ms
57
- */
58
- queryFuncTimeout?: number
59
-
60
50
  /**
61
51
  * Query log
62
52
  */
@@ -65,12 +55,17 @@ export interface QueryPathOptions extends RoutingOptions {
65
55
  /**
66
56
  * Set of peers seen by this and other paths
67
57
  */
68
- peersSeen: PeerSet
58
+ peersSeen: Filter
69
59
 
70
60
  /**
71
61
  * The libp2p connection manager
72
62
  */
73
63
  connectionManager: ConnectionManager
64
+
65
+ /**
66
+ * The overall query abort signal
67
+ */
68
+ signal: AbortSignal
74
69
  }
75
70
 
76
71
  interface QueryQueueOptions extends AbortOptions {
@@ -82,60 +77,75 @@ interface QueryQueueOptions extends AbortOptions {
82
77
  * every peer encountered that we have not seen before
83
78
  */
84
79
  export async function * queryPath (options: QueryPathOptions): AsyncGenerator<QueryEvent, void, undefined> {
85
- const { key, startingPeer, ourPeerId, signal, query, alpha, path, numPaths, queryFuncTimeout, log, peersSeen, connectionManager } = options
80
+ const { key, startingPeers, ourPeerId, query, alpha, path, numPaths, log, peersSeen, connectionManager, signal } = options
81
+ const events = pushable<QueryEvent>({
82
+ objectMode: true
83
+ })
84
+
86
85
  // Only ALPHA node/value lookups are allowed at any given time for each process
87
86
  // https://github.com/libp2p/specs/tree/master/kad-dht#alpha-concurrency-parameter-%CE%B1
88
- const queue = new Queue<QueryEvent | undefined, QueryQueueOptions>({
87
+ const queue = new Queue<undefined, QueryQueueOptions>({
89
88
  concurrency: alpha,
90
89
  sort: (a, b) => uint8ArrayXorCompare(a.options.distance, b.options.distance)
91
90
  })
91
+ queue.addEventListener('idle', () => {
92
+ events.push(pathEndedEvent({
93
+ path: {
94
+ index: path,
95
+ queued: queue.queued,
96
+ running: queue.running,
97
+ total: queue.size
98
+ }
99
+ }, options))
100
+
101
+ events.end()
102
+ })
103
+ queue.addEventListener('error', (evt) => {
104
+ log.error('error during query - %e', evt.detail)
105
+ })
106
+
107
+ signal.addEventListener('abort', () => {
108
+ queue.abort()
109
+ events.end(new QueryAbortedError())
110
+ })
92
111
 
93
112
  // perform lookups on kadId, not the actual value
94
113
  const kadId = await convertBuffer(key)
95
114
 
96
115
  /**
97
- * Adds the passed peer to the query queue if it's not us and no
98
- * other path has passed through this peer
116
+ * Adds the passed peer to the query queue if it's not us and no other path
117
+ * has passed through this peer
99
118
  */
100
- function queryPeer (peer: PeerId, peerKadId: Uint8Array): void {
119
+ function queryPeer (peer: PeerInfo, peerKadId: Uint8Array): void {
101
120
  if (peer == null) {
102
121
  return
103
122
  }
104
123
 
105
- peersSeen.add(peer)
124
+ peersSeen.add(peer.id.toMultihash().bytes)
106
125
 
107
126
  const peerXor = uint8ArrayXor(peerKadId, kadId)
108
127
 
109
128
  queue.add(async () => {
110
- const signals = [signal]
111
-
112
- if (queryFuncTimeout != null) {
113
- signals.push(AbortSignal.timeout(queryFuncTimeout))
114
- }
115
-
116
- const compoundSignal = anySignal(signals)
117
-
118
- // this signal can get listened to a lot
119
- setMaxListeners(Infinity, compoundSignal)
120
-
121
129
  try {
122
130
  for await (const event of query({
123
131
  ...options,
124
132
  key,
125
133
  peer,
126
- signal: compoundSignal,
127
- path,
128
- numPaths
134
+ path: {
135
+ index: path,
136
+ queued: queue.queued,
137
+ running: queue.running,
138
+ total: queue.size
139
+ },
140
+ numPaths,
141
+ peerKadId,
142
+ signal
129
143
  })) {
130
- if (compoundSignal.aborted) {
131
- return
132
- }
133
-
134
144
  // if there are closer peers and the query has not completed, continue the query
135
145
  if (event.name === 'PEER_RESPONSE') {
136
146
  for (const closerPeer of event.closer) {
137
- if (peersSeen.has(closerPeer.id)) { // eslint-disable-line max-depth
138
- log.trace('already seen %p in query', closerPeer.id)
147
+ if (peersSeen.has(closerPeer.id.toMultihash().bytes)) { // eslint-disable-line max-depth
148
+ log('already seen %p in query', closerPeer.id)
139
149
  continue
140
150
  }
141
151
 
@@ -154,44 +164,52 @@ export async function * queryPath (options: QueryPathOptions): AsyncGenerator<Qu
154
164
 
155
165
  // only continue query if closer peer is actually closer
156
166
  if (uint8ArrayXorCompare(closerPeerXor, peerXor) !== -1) { // eslint-disable-line max-depth
157
- log.trace('skipping %p as they are not closer to %b than %p', closerPeer.id, key, peer)
167
+ log('skipping %p as they are not closer to %b than %p', closerPeer.id, key, peer)
158
168
  continue
159
169
  }
160
170
 
161
- log.trace('querying closer peer %p', closerPeer.id)
162
- queryPeer(closerPeer.id, closerPeerKadId)
171
+ log('querying closer peer %p', closerPeer.id)
172
+ queryPeer(closerPeer, closerPeerKadId)
163
173
  }
164
174
  }
165
175
 
166
- queue.safeDispatchEvent('completed', {
167
- detail: event
176
+ events.push({
177
+ ...event,
178
+ path: {
179
+ index: path,
180
+ queued: queue.queued,
181
+ running: queue.running,
182
+ total: queue.size
183
+ }
168
184
  })
169
185
  }
170
186
  } catch (err: any) {
171
- if (!signal.aborted) {
172
- return queryErrorEvent({
173
- from: peer,
174
- error: err,
175
- path
176
- }, options)
177
- }
178
- } finally {
179
- compoundSignal.clear()
187
+ // yield error event if query is continuing
188
+ events.push(queryErrorEvent({
189
+ from: peer.id,
190
+ error: err,
191
+ path: {
192
+ index: path,
193
+ queued: queue.queued,
194
+ running: queue.running - 1,
195
+ total: queue.size - 1
196
+ }
197
+ }, options))
180
198
  }
181
199
  }, {
182
200
  distance: peerXor
183
201
  }).catch(err => {
184
- log.error(err)
202
+ log.error('error during query - %e', err)
185
203
  })
186
204
  }
187
205
 
188
- // begin the query with the starting peer
189
- queryPeer(startingPeer, await convertPeerId(startingPeer))
206
+ // begin the query with the starting peers
207
+ await Promise.all(
208
+ startingPeers.map(async startingPeer => {
209
+ queryPeer({ id: startingPeer, multiaddrs: [] }, await convertPeerId(startingPeer))
210
+ })
211
+ )
190
212
 
191
213
  // yield results as they come in
192
- for await (const event of queue.toGenerator({ signal })) {
193
- if (event != null) {
194
- yield event
195
- }
196
- }
214
+ yield * events
197
215
  }
@@ -1,15 +1,17 @@
1
- import type { QueryEvent } from '../index.js'
2
- import type { PeerId } from '@libp2p/interface'
1
+ import type { DisjointPath, QueryEvent } from '../index.js'
2
+ import type { PeerInfo } from '@libp2p/interface'
3
3
 
4
4
  export interface QueryContext {
5
5
  // the key we are looking up
6
6
  key: Uint8Array
7
7
  // the current peer being queried
8
- peer: PeerId
8
+ peer: PeerInfo
9
+ // the KAD ID of the peer being queried
10
+ peerKadId: Uint8Array
9
11
  // if this signal emits an 'abort' event, any long-lived processes or requests started as part of this query should be terminated
10
- signal: AbortSignal
12
+ signal?: AbortSignal
11
13
  // which disjoint path we are following
12
- path: number
14
+ path: DisjointPath
13
15
  // the total number of disjoint paths being executed
14
16
  numPaths: number
15
17
  }
@@ -67,7 +67,7 @@ export class GetProvidersHandler implements DHTMessageHandler {
67
67
 
68
68
  return info
69
69
  })),
70
- this.peerRouting.getCloserPeersOffline(msg.key, this.peerId)
70
+ this.peerRouting.getCloserPeersOffline(msg.key, peerId)
71
71
  ])
72
72
 
73
73
  const response: Message = {
package/src/utils.ts CHANGED
@@ -140,6 +140,15 @@ export function fromPublicKeyKey (key: Uint8Array): PeerId {
140
140
  return peerIdFromMultihash(multihash)
141
141
  }
142
142
 
143
+ export function uint8ArrayToBigInt (buf: Uint8Array): bigint {
144
+ return BigInt(
145
+ `0x${
146
+ Array.from(buf)
147
+ .map(val => val.toString(16).padStart(2, '0')).join('')
148
+ }`
149
+ )
150
+ }
151
+
143
152
  /**
144
153
  * Create a new put record, encodes and signs it if enabled
145
154
  */