@libp2p/kad-dht 2.0.0 → 3.0.2

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 (45) hide show
  1. package/dist/src/content-fetching/index.js +2 -2
  2. package/dist/src/content-fetching/index.js.map +1 -1
  3. package/dist/src/index.d.ts +8 -0
  4. package/dist/src/index.d.ts.map +1 -1
  5. package/dist/src/index.js.map +1 -1
  6. package/dist/src/kad-dht.d.ts +4 -0
  7. package/dist/src/kad-dht.d.ts.map +1 -1
  8. package/dist/src/kad-dht.js +9 -2
  9. package/dist/src/kad-dht.js.map +1 -1
  10. package/dist/src/message/dht.d.ts +6 -5
  11. package/dist/src/message/dht.d.ts.map +1 -1
  12. package/dist/src/message/dht.js +201 -21
  13. package/dist/src/message/dht.js.map +1 -1
  14. package/dist/src/message/index.d.ts +2 -1
  15. package/dist/src/message/index.d.ts.map +1 -1
  16. package/dist/src/message/index.js +1 -1
  17. package/dist/src/message/index.js.map +1 -1
  18. package/dist/src/network.d.ts +3 -2
  19. package/dist/src/network.d.ts.map +1 -1
  20. package/dist/src/network.js +2 -4
  21. package/dist/src/network.js.map +1 -1
  22. package/dist/src/peer-routing/index.d.ts +1 -5
  23. package/dist/src/peer-routing/index.d.ts.map +1 -1
  24. package/dist/src/peer-routing/index.js +1 -0
  25. package/dist/src/peer-routing/index.js.map +1 -1
  26. package/dist/src/routing-table/index.d.ts.map +1 -1
  27. package/dist/src/routing-table/index.js +3 -1
  28. package/dist/src/routing-table/index.js.map +1 -1
  29. package/dist/src/rpc/handlers/put-value.js +1 -1
  30. package/dist/src/rpc/handlers/put-value.js.map +1 -1
  31. package/dist/src/utils.d.ts +1 -1
  32. package/dist/src/utils.d.ts.map +1 -1
  33. package/dist/src/utils.js +3 -3
  34. package/dist/src/utils.js.map +1 -1
  35. package/package.json +20 -15
  36. package/src/content-fetching/index.ts +2 -2
  37. package/src/index.ts +10 -0
  38. package/src/kad-dht.ts +14 -2
  39. package/src/message/dht.ts +244 -26
  40. package/src/message/index.ts +3 -2
  41. package/src/network.ts +5 -6
  42. package/src/peer-routing/index.ts +3 -1
  43. package/src/routing-table/index.ts +8 -4
  44. package/src/rpc/handlers/put-value.ts +1 -1
  45. package/src/utils.ts +3 -3
@@ -1,7 +1,8 @@
1
1
  /* eslint-disable import/export */
2
2
  /* eslint-disable @typescript-eslint/no-namespace */
3
3
 
4
- import { encodeMessage, decodeMessage, message, bytes, string, enumeration, int32 } from 'protons-runtime'
4
+ import { encodeMessage, decodeMessage, message, enumeration } from 'protons-runtime'
5
+ import type { Uint8ArrayList } from 'uint8arraylist'
5
6
  import type { Codec } from 'protons-runtime'
6
7
 
7
8
  export interface Record {
@@ -13,21 +14,85 @@ export interface Record {
13
14
  }
14
15
 
15
16
  export namespace Record {
17
+ let _codec: Codec<Record>
18
+
16
19
  export const codec = (): Codec<Record> => {
17
- return message<Record>({
18
- 1: { name: 'key', codec: bytes, optional: true },
19
- 2: { name: 'value', codec: bytes, optional: true },
20
- 3: { name: 'author', codec: bytes, optional: true },
21
- 4: { name: 'signature', codec: bytes, optional: true },
22
- 5: { name: 'timeReceived', codec: string, optional: true }
23
- })
20
+ if (_codec == null) {
21
+ _codec = message<Record>((obj, writer, opts = {}) => {
22
+ if (opts.lengthDelimited !== false) {
23
+ writer.fork()
24
+ }
25
+
26
+ if (obj.key != null) {
27
+ writer.uint32(10)
28
+ writer.bytes(obj.key)
29
+ }
30
+
31
+ if (obj.value != null) {
32
+ writer.uint32(18)
33
+ writer.bytes(obj.value)
34
+ }
35
+
36
+ if (obj.author != null) {
37
+ writer.uint32(26)
38
+ writer.bytes(obj.author)
39
+ }
40
+
41
+ if (obj.signature != null) {
42
+ writer.uint32(34)
43
+ writer.bytes(obj.signature)
44
+ }
45
+
46
+ if (obj.timeReceived != null) {
47
+ writer.uint32(42)
48
+ writer.string(obj.timeReceived)
49
+ }
50
+
51
+ if (opts.lengthDelimited !== false) {
52
+ writer.ldelim()
53
+ }
54
+ }, (reader, length) => {
55
+ const obj: any = {}
56
+
57
+ const end = length == null ? reader.len : reader.pos + length
58
+
59
+ while (reader.pos < end) {
60
+ const tag = reader.uint32()
61
+
62
+ switch (tag >>> 3) {
63
+ case 1:
64
+ obj.key = reader.bytes()
65
+ break
66
+ case 2:
67
+ obj.value = reader.bytes()
68
+ break
69
+ case 3:
70
+ obj.author = reader.bytes()
71
+ break
72
+ case 4:
73
+ obj.signature = reader.bytes()
74
+ break
75
+ case 5:
76
+ obj.timeReceived = reader.string()
77
+ break
78
+ default:
79
+ reader.skipType(tag & 7)
80
+ break
81
+ }
82
+ }
83
+
84
+ return obj
85
+ })
86
+ }
87
+
88
+ return _codec
24
89
  }
25
90
 
26
91
  export const encode = (obj: Record): Uint8Array => {
27
92
  return encodeMessage(obj, Record.codec())
28
93
  }
29
94
 
30
- export const decode = (buf: Uint8Array): Record => {
95
+ export const decode = (buf: Uint8Array | Uint8ArrayList): Record => {
31
96
  return decodeMessage(buf, Record.codec())
32
97
  }
33
98
  }
@@ -62,7 +127,7 @@ export namespace Message {
62
127
 
63
128
  export namespace MessageType {
64
129
  export const codec = () => {
65
- return enumeration<typeof MessageType>(__MessageTypeValues)
130
+ return enumeration<MessageType>(__MessageTypeValues)
66
131
  }
67
132
  }
68
133
 
@@ -82,7 +147,7 @@ export namespace Message {
82
147
 
83
148
  export namespace ConnectionType {
84
149
  export const codec = () => {
85
- return enumeration<typeof ConnectionType>(__ConnectionTypeValues)
150
+ return enumeration<ConnectionType>(__ConnectionTypeValues)
86
151
  }
87
152
  }
88
153
 
@@ -93,39 +158,192 @@ export namespace Message {
93
158
  }
94
159
 
95
160
  export namespace Peer {
161
+ let _codec: Codec<Peer>
162
+
96
163
  export const codec = (): Codec<Peer> => {
97
- return message<Peer>({
98
- 1: { name: 'id', codec: bytes, optional: true },
99
- 2: { name: 'addrs', codec: bytes, repeats: true },
100
- 3: { name: 'connection', codec: Message.ConnectionType.codec(), optional: true }
101
- })
164
+ if (_codec == null) {
165
+ _codec = message<Peer>((obj, writer, opts = {}) => {
166
+ if (opts.lengthDelimited !== false) {
167
+ writer.fork()
168
+ }
169
+
170
+ if (obj.id != null) {
171
+ writer.uint32(10)
172
+ writer.bytes(obj.id)
173
+ }
174
+
175
+ if (obj.addrs != null) {
176
+ for (const value of obj.addrs) {
177
+ writer.uint32(18)
178
+ writer.bytes(value)
179
+ }
180
+ } else {
181
+ throw new Error('Protocol error: required field "addrs" was not found in object')
182
+ }
183
+
184
+ if (obj.connection != null) {
185
+ writer.uint32(24)
186
+ Message.ConnectionType.codec().encode(obj.connection, writer)
187
+ }
188
+
189
+ if (opts.lengthDelimited !== false) {
190
+ writer.ldelim()
191
+ }
192
+ }, (reader, length) => {
193
+ const obj: any = {}
194
+
195
+ const end = length == null ? reader.len : reader.pos + length
196
+
197
+ while (reader.pos < end) {
198
+ const tag = reader.uint32()
199
+
200
+ switch (tag >>> 3) {
201
+ case 1:
202
+ obj.id = reader.bytes()
203
+ break
204
+ case 2:
205
+ obj.addrs = obj.addrs ?? []
206
+ obj.addrs.push(reader.bytes())
207
+ break
208
+ case 3:
209
+ obj.connection = Message.ConnectionType.codec().decode(reader)
210
+ break
211
+ default:
212
+ reader.skipType(tag & 7)
213
+ break
214
+ }
215
+ }
216
+
217
+ obj.addrs = obj.addrs ?? []
218
+
219
+ if (obj.addrs == null) {
220
+ throw new Error('Protocol error: value for required field "addrs" was not found in protobuf')
221
+ }
222
+
223
+ return obj
224
+ })
225
+ }
226
+
227
+ return _codec
102
228
  }
103
229
 
104
230
  export const encode = (obj: Peer): Uint8Array => {
105
231
  return encodeMessage(obj, Peer.codec())
106
232
  }
107
233
 
108
- export const decode = (buf: Uint8Array): Peer => {
234
+ export const decode = (buf: Uint8Array | Uint8ArrayList): Peer => {
109
235
  return decodeMessage(buf, Peer.codec())
110
236
  }
111
237
  }
112
238
 
239
+ let _codec: Codec<Message>
240
+
113
241
  export const codec = (): Codec<Message> => {
114
- return message<Message>({
115
- 1: { name: 'type', codec: Message.MessageType.codec(), optional: true },
116
- 10: { name: 'clusterLevelRaw', codec: int32, optional: true },
117
- 2: { name: 'key', codec: bytes, optional: true },
118
- 3: { name: 'record', codec: bytes, optional: true },
119
- 8: { name: 'closerPeers', codec: Message.Peer.codec(), repeats: true },
120
- 9: { name: 'providerPeers', codec: Message.Peer.codec(), repeats: true }
121
- })
242
+ if (_codec == null) {
243
+ _codec = message<Message>((obj, writer, opts = {}) => {
244
+ if (opts.lengthDelimited !== false) {
245
+ writer.fork()
246
+ }
247
+
248
+ if (obj.type != null) {
249
+ writer.uint32(8)
250
+ Message.MessageType.codec().encode(obj.type, writer)
251
+ }
252
+
253
+ if (obj.clusterLevelRaw != null) {
254
+ writer.uint32(80)
255
+ writer.int32(obj.clusterLevelRaw)
256
+ }
257
+
258
+ if (obj.key != null) {
259
+ writer.uint32(18)
260
+ writer.bytes(obj.key)
261
+ }
262
+
263
+ if (obj.record != null) {
264
+ writer.uint32(26)
265
+ writer.bytes(obj.record)
266
+ }
267
+
268
+ if (obj.closerPeers != null) {
269
+ for (const value of obj.closerPeers) {
270
+ writer.uint32(66)
271
+ Message.Peer.codec().encode(value, writer)
272
+ }
273
+ } else {
274
+ throw new Error('Protocol error: required field "closerPeers" was not found in object')
275
+ }
276
+
277
+ if (obj.providerPeers != null) {
278
+ for (const value of obj.providerPeers) {
279
+ writer.uint32(74)
280
+ Message.Peer.codec().encode(value, writer)
281
+ }
282
+ } else {
283
+ throw new Error('Protocol error: required field "providerPeers" was not found in object')
284
+ }
285
+
286
+ if (opts.lengthDelimited !== false) {
287
+ writer.ldelim()
288
+ }
289
+ }, (reader, length) => {
290
+ const obj: any = {}
291
+
292
+ const end = length == null ? reader.len : reader.pos + length
293
+
294
+ while (reader.pos < end) {
295
+ const tag = reader.uint32()
296
+
297
+ switch (tag >>> 3) {
298
+ case 1:
299
+ obj.type = Message.MessageType.codec().decode(reader)
300
+ break
301
+ case 10:
302
+ obj.clusterLevelRaw = reader.int32()
303
+ break
304
+ case 2:
305
+ obj.key = reader.bytes()
306
+ break
307
+ case 3:
308
+ obj.record = reader.bytes()
309
+ break
310
+ case 8:
311
+ obj.closerPeers = obj.closerPeers ?? []
312
+ obj.closerPeers.push(Message.Peer.codec().decode(reader, reader.uint32()))
313
+ break
314
+ case 9:
315
+ obj.providerPeers = obj.providerPeers ?? []
316
+ obj.providerPeers.push(Message.Peer.codec().decode(reader, reader.uint32()))
317
+ break
318
+ default:
319
+ reader.skipType(tag & 7)
320
+ break
321
+ }
322
+ }
323
+
324
+ obj.closerPeers = obj.closerPeers ?? []
325
+ obj.providerPeers = obj.providerPeers ?? []
326
+
327
+ if (obj.closerPeers == null) {
328
+ throw new Error('Protocol error: value for required field "closerPeers" was not found in protobuf')
329
+ }
330
+
331
+ if (obj.providerPeers == null) {
332
+ throw new Error('Protocol error: value for required field "providerPeers" was not found in protobuf')
333
+ }
334
+
335
+ return obj
336
+ })
337
+ }
338
+
339
+ return _codec
122
340
  }
123
341
 
124
342
  export const encode = (obj: Message): Uint8Array => {
125
343
  return encodeMessage(obj, Message.codec())
126
344
  }
127
345
 
128
- export const decode = (buf: Uint8Array): Message => {
346
+ export const decode = (buf: Uint8Array | Uint8ArrayList): Message => {
129
347
  return decodeMessage(buf, Message.codec())
130
348
  }
131
349
  }
@@ -3,6 +3,7 @@ import { Multiaddr } from '@multiformats/multiaddr'
3
3
  import { Libp2pRecord } from '@libp2p/record'
4
4
  import { Message as PBMessage } from './dht.js'
5
5
  import type { PeerInfo } from '@libp2p/interface-peer-info'
6
+ import type { Uint8ArrayList } from 'uint8arraylist'
6
7
 
7
8
  export const MESSAGE_TYPE = PBMessage.MessageType
8
9
  export const CONNECTION_TYPE = PBMessage.ConnectionType
@@ -64,14 +65,14 @@ export class Message {
64
65
  clusterLevelRaw: this.clusterLevelRaw,
65
66
  closerPeers: this.closerPeers.map(toPbPeer),
66
67
  providerPeers: this.providerPeers.map(toPbPeer),
67
- record: this.record == null ? undefined : this.record.serialize()
68
+ record: this.record == null ? undefined : this.record.serialize().subarray()
68
69
  })
69
70
  }
70
71
 
71
72
  /**
72
73
  * Decode from protobuf
73
74
  */
74
- static deserialize (raw: Uint8Array) {
75
+ static deserialize (raw: Uint8ArrayList | Uint8Array) {
75
76
  const dec = PBMessage.decode(raw)
76
77
 
77
78
  const msg = new Message(dec.type ?? PBMessage.MessageType.PUT_VALUE, dec.key ?? Uint8Array.from([]), dec.clusterLevelRaw ?? 0)
package/src/network.ts CHANGED
@@ -21,6 +21,7 @@ import type { PeerInfo } from '@libp2p/interface-peer-info'
21
21
  import { Components, Initializable } from '@libp2p/components'
22
22
  import type { Stream } from '@libp2p/interface-connection'
23
23
  import { abortableDuplex } from 'abortable-iterator'
24
+ import type { Uint8ArrayList } from 'uint8arraylist'
24
25
 
25
26
  export interface NetworkInit {
26
27
  protocol: string
@@ -97,8 +98,7 @@ export class Network extends EventEmitter<NetworkEvents> implements Startable, I
97
98
 
98
99
  try {
99
100
  const connection = await this.components.getConnectionManager().openConnection(to, options)
100
- const streamData = await connection.newStream(this.protocol, options)
101
- stream = streamData.stream
101
+ const stream = await connection.newStream(this.protocol, options)
102
102
 
103
103
  const response = await this._writeReadMessage(stream, msg.serialize(), options)
104
104
 
@@ -134,8 +134,7 @@ export class Network extends EventEmitter<NetworkEvents> implements Startable, I
134
134
 
135
135
  try {
136
136
  const connection = await this.components.getConnectionManager().openConnection(to, options)
137
- const data = await connection.newStream(this.protocol, options)
138
- stream = data.stream
137
+ const stream = await connection.newStream(this.protocol, options)
139
138
 
140
139
  await this._writeMessage(stream, msg.serialize(), options)
141
140
 
@@ -152,7 +151,7 @@ export class Network extends EventEmitter<NetworkEvents> implements Startable, I
152
151
  /**
153
152
  * Write a message to the given stream
154
153
  */
155
- async _writeMessage (stream: Duplex<Uint8Array>, msg: Uint8Array, options: AbortOptions) {
154
+ async _writeMessage (stream: Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array>, msg: Uint8Array | Uint8ArrayList, options: AbortOptions) {
156
155
  if (options.signal != null) {
157
156
  stream = abortableDuplex(stream, options.signal)
158
157
  }
@@ -170,7 +169,7 @@ export class Network extends EventEmitter<NetworkEvents> implements Startable, I
170
169
  * If no response is received after the specified timeout
171
170
  * this will error out.
172
171
  */
173
- async _writeReadMessage (stream: Duplex<Uint8Array>, msg: Uint8Array, options: AbortOptions) {
172
+ async _writeReadMessage (stream: Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array>, msg: Uint8Array | Uint8ArrayList, options: AbortOptions) {
174
173
  if (options.signal != null) {
175
174
  stream = abortableDuplex(stream, options.signal)
176
175
  }
@@ -58,7 +58,7 @@ export class PeerRouting implements Initializable {
58
58
  * Look if we are connected to a peer with the given id.
59
59
  * Returns its id and addresses, if found, otherwise `undefined`.
60
60
  */
61
- async findPeerLocal (peer: PeerId) {
61
+ async findPeerLocal (peer: PeerId): Promise<PeerInfo | undefined> {
62
62
  let peerData
63
63
  const p = await this.routingTable.find(peer)
64
64
 
@@ -93,6 +93,8 @@ export class PeerRouting implements Initializable {
93
93
  protocols: []
94
94
  }
95
95
  }
96
+
97
+ return undefined
96
98
  }
97
99
 
98
100
  /**
@@ -158,7 +158,7 @@ export class RoutingTable implements Startable, Initializable {
158
158
 
159
159
  this.log('pinging old contact %p', oldContact.peer)
160
160
  const connection = await this.components.getConnectionManager().openConnection(oldContact.peer, options)
161
- const { stream } = await connection.newStream(this.protocol, options)
161
+ const stream = await connection.newStream(this.protocol, options)
162
162
  stream.close()
163
163
  responded++
164
164
  } catch (err: any) {
@@ -213,30 +213,34 @@ export class RoutingTable implements Startable, Initializable {
213
213
  /**
214
214
  * Find a specific peer by id
215
215
  */
216
- async find (peer: PeerId) {
216
+ async find (peer: PeerId): Promise<PeerId | undefined> {
217
217
  const key = await utils.convertPeerId(peer)
218
218
  const closest = this.closestPeer(key)
219
219
 
220
220
  if (closest != null && peer.equals(closest)) {
221
221
  return closest
222
222
  }
223
+
224
+ return undefined
223
225
  }
224
226
 
225
227
  /**
226
228
  * Retrieve the closest peers to the given key
227
229
  */
228
- closestPeer (key: Uint8Array) {
230
+ closestPeer (key: Uint8Array): PeerId | undefined {
229
231
  const res = this.closestPeers(key, 1)
230
232
 
231
233
  if (res.length > 0) {
232
234
  return res[0]
233
235
  }
236
+
237
+ return undefined
234
238
  }
235
239
 
236
240
  /**
237
241
  * Retrieve the `count`-closest peers to the given key
238
242
  */
239
- closestPeers (key: Uint8Array, count = this.kBucketSize) {
243
+ closestPeers (key: Uint8Array, count = this.kBucketSize): PeerId[] {
240
244
  if (this.kb == null) {
241
245
  return []
242
246
  }
@@ -46,7 +46,7 @@ export class PutValueHandler implements DHTMessageHandler, Initializable {
46
46
 
47
47
  record.timeReceived = new Date()
48
48
  const recordKey = bufferToRecordKey(record.key)
49
- await this.components.getDatastore().put(recordKey, record.serialize())
49
+ await this.components.getDatastore().put(recordKey, record.serialize().subarray())
50
50
  this.log('put record for %b into datastore under key %k', key, recordKey)
51
51
  } catch (err: any) {
52
52
  this.log('did not put record for key %b into datastore %o', key, err)
package/src/utils.ts CHANGED
@@ -92,15 +92,15 @@ export function keyForPublicKey (peer: PeerId) {
92
92
  }
93
93
 
94
94
  export function isPublicKeyKey (key: Uint8Array) {
95
- return uint8ArrayToString(key.slice(0, 4)) === '/pk/'
95
+ return uint8ArrayToString(key.subarray(0, 4)) === '/pk/'
96
96
  }
97
97
 
98
98
  export function isIPNSKey (key: Uint8Array) {
99
- return uint8ArrayToString(key.slice(0, 4)) === '/ipns/'
99
+ return uint8ArrayToString(key.subarray(0, 4)) === '/ipns/'
100
100
  }
101
101
 
102
102
  export function fromPublicKeyKey (key: Uint8Array) {
103
- return peerIdFromBytes(key.slice(4))
103
+ return peerIdFromBytes(key.subarray(4))
104
104
  }
105
105
 
106
106
  /**