@libp2p/kad-dht 12.1.5 → 13.0.0-18dd3cb26
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 +3 -4
- package/dist/src/content-fetching/index.d.ts.map +1 -1
- package/dist/src/content-fetching/index.js +6 -5
- package/dist/src/content-fetching/index.js.map +1 -1
- package/dist/src/content-routing/index.js +1 -1
- package/dist/src/errors.d.ts +25 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +37 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/kad-dht.d.ts.map +1 -1
- package/dist/src/kad-dht.js +3 -3
- package/dist/src/kad-dht.js.map +1 -1
- package/dist/src/message/dht.d.ts +4 -4
- package/dist/src/message/dht.d.ts.map +1 -1
- package/dist/src/message/dht.js +25 -12
- package/dist/src/message/dht.js.map +1 -1
- package/dist/src/message/utils.d.ts.map +1 -1
- package/dist/src/message/utils.js +5 -3
- package/dist/src/message/utils.js.map +1 -1
- package/dist/src/network.d.ts.map +1 -1
- package/dist/src/network.js +3 -4
- package/dist/src/network.js.map +1 -1
- package/dist/src/peer-routing/index.d.ts.map +1 -1
- package/dist/src/peer-routing/index.js +21 -16
- package/dist/src/peer-routing/index.js.map +1 -1
- package/dist/src/query/events.d.ts.map +1 -1
- package/dist/src/query/events.js +0 -1
- package/dist/src/query/events.js.map +1 -1
- package/dist/src/query/manager.js +1 -1
- package/dist/src/query/query-path.d.ts.map +1 -1
- package/dist/src/query/query-path.js +3 -2
- package/dist/src/query/query-path.js.map +1 -1
- package/dist/src/query-self.js +1 -1
- package/dist/src/query-self.js.map +1 -1
- package/dist/src/record/selectors.d.ts.map +1 -1
- package/dist/src/record/selectors.js +5 -7
- package/dist/src/record/selectors.js.map +1 -1
- package/dist/src/record/validators.d.ts.map +1 -1
- package/dist/src/record/validators.js +9 -10
- package/dist/src/record/validators.js.map +1 -1
- package/dist/src/routing-table/index.d.ts.map +1 -1
- package/dist/src/routing-table/index.js +2 -2
- package/dist/src/routing-table/index.js.map +1 -1
- package/dist/src/routing-table/refresh.d.ts.map +1 -1
- package/dist/src/routing-table/refresh.js +5 -3
- package/dist/src/routing-table/refresh.js.map +1 -1
- package/dist/src/rpc/handlers/add-provider.d.ts.map +1 -1
- package/dist/src/rpc/handlers/add-provider.js +7 -5
- package/dist/src/rpc/handlers/add-provider.js.map +1 -1
- package/dist/src/rpc/handlers/find-node.js +4 -4
- package/dist/src/rpc/handlers/find-node.js.map +1 -1
- package/dist/src/rpc/handlers/get-providers.js +6 -6
- package/dist/src/rpc/handlers/get-providers.js.map +1 -1
- package/dist/src/rpc/handlers/get-value.d.ts.map +1 -1
- package/dist/src/rpc/handlers/get-value.js +8 -10
- package/dist/src/rpc/handlers/get-value.js.map +1 -1
- package/dist/src/rpc/handlers/put-value.js +2 -2
- package/dist/src/rpc/handlers/put-value.js.map +1 -1
- package/dist/src/topology-listener.d.ts.map +1 -1
- package/dist/src/topology-listener.js +1 -1
- package/dist/src/topology-listener.js.map +1 -1
- package/dist/src/utils.d.ts +1 -1
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +7 -5
- package/dist/src/utils.js.map +1 -1
- package/package.json +14 -15
- package/src/content-fetching/index.ts +6 -5
- package/src/content-routing/index.ts +1 -1
- package/src/errors.ts +39 -0
- package/src/index.ts +2 -1
- package/src/kad-dht.ts +3 -3
- package/src/message/dht.ts +28 -12
- package/src/message/utils.ts +6 -3
- package/src/network.ts +3 -4
- package/src/peer-routing/index.ts +21 -16
- package/src/query/events.ts +0 -1
- package/src/query/manager.ts +1 -1
- package/src/query/query-path.ts +3 -2
- package/src/query-self.ts +1 -1
- package/src/record/selectors.ts +5 -10
- package/src/record/validators.ts +9 -12
- package/src/routing-table/index.ts +2 -2
- package/src/routing-table/refresh.ts +5 -3
- package/src/rpc/handlers/add-provider.ts +8 -5
- package/src/rpc/handlers/find-node.ts +4 -4
- package/src/rpc/handlers/get-providers.ts +6 -6
- package/src/rpc/handlers/get-value.ts +8 -11
- package/src/rpc/handlers/put-value.ts +2 -2
- package/src/topology-listener.ts +1 -1
- package/src/utils.ts +7 -5
- package/dist/typedoc-urls.json +0 -55
package/src/message/dht.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
|
|
5
5
|
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
6
6
|
|
|
7
|
-
import { type Codec, decodeMessage, encodeMessage, enumeration, message } from 'protons-runtime'
|
|
7
|
+
import { type Codec, decodeMessage, type DecodeOptions, encodeMessage, enumeration, MaxLengthError, message } from 'protons-runtime'
|
|
8
8
|
import { alloc as uint8ArrayAlloc } from 'uint8arrays/alloc'
|
|
9
9
|
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
10
10
|
|
|
@@ -54,7 +54,7 @@ export namespace Record {
|
|
|
54
54
|
if (opts.lengthDelimited !== false) {
|
|
55
55
|
w.ldelim()
|
|
56
56
|
}
|
|
57
|
-
}, (reader, length) => {
|
|
57
|
+
}, (reader, length, opts = {}) => {
|
|
58
58
|
const obj: any = {}
|
|
59
59
|
|
|
60
60
|
const end = length == null ? reader.len : reader.pos + length
|
|
@@ -101,8 +101,8 @@ export namespace Record {
|
|
|
101
101
|
return encodeMessage(obj, Record.codec())
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
export const decode = (buf: Uint8Array | Uint8ArrayList): Record => {
|
|
105
|
-
return decodeMessage(buf, Record.codec())
|
|
104
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<Record>): Record => {
|
|
105
|
+
return decodeMessage(buf, Record.codec(), opts)
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -184,7 +184,7 @@ export namespace PeerInfo {
|
|
|
184
184
|
if (opts.lengthDelimited !== false) {
|
|
185
185
|
w.ldelim()
|
|
186
186
|
}
|
|
187
|
-
}, (reader, length) => {
|
|
187
|
+
}, (reader, length, opts = {}) => {
|
|
188
188
|
const obj: any = {
|
|
189
189
|
id: uint8ArrayAlloc(0),
|
|
190
190
|
multiaddrs: []
|
|
@@ -201,6 +201,10 @@ export namespace PeerInfo {
|
|
|
201
201
|
break
|
|
202
202
|
}
|
|
203
203
|
case 2: {
|
|
204
|
+
if (opts.limits?.multiaddrs != null && obj.multiaddrs.length === opts.limits.multiaddrs) {
|
|
205
|
+
throw new MaxLengthError('Decode error - map field "multiaddrs" had too many elements')
|
|
206
|
+
}
|
|
207
|
+
|
|
204
208
|
obj.multiaddrs.push(reader.bytes())
|
|
205
209
|
break
|
|
206
210
|
}
|
|
@@ -226,8 +230,8 @@ export namespace PeerInfo {
|
|
|
226
230
|
return encodeMessage(obj, PeerInfo.codec())
|
|
227
231
|
}
|
|
228
232
|
|
|
229
|
-
export const decode = (buf: Uint8Array | Uint8ArrayList): PeerInfo => {
|
|
230
|
-
return decodeMessage(buf, PeerInfo.codec())
|
|
233
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<PeerInfo>): PeerInfo => {
|
|
234
|
+
return decodeMessage(buf, PeerInfo.codec(), opts)
|
|
231
235
|
}
|
|
232
236
|
}
|
|
233
237
|
|
|
@@ -287,7 +291,7 @@ export namespace Message {
|
|
|
287
291
|
if (opts.lengthDelimited !== false) {
|
|
288
292
|
w.ldelim()
|
|
289
293
|
}
|
|
290
|
-
}, (reader, length) => {
|
|
294
|
+
}, (reader, length, opts = {}) => {
|
|
291
295
|
const obj: any = {
|
|
292
296
|
type: MessageType.PUT_VALUE,
|
|
293
297
|
closer: [],
|
|
@@ -317,11 +321,23 @@ export namespace Message {
|
|
|
317
321
|
break
|
|
318
322
|
}
|
|
319
323
|
case 8: {
|
|
320
|
-
obj.closer.
|
|
324
|
+
if (opts.limits?.closer != null && obj.closer.length === opts.limits.closer) {
|
|
325
|
+
throw new MaxLengthError('Decode error - map field "closer" had too many elements')
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
obj.closer.push(PeerInfo.codec().decode(reader, reader.uint32(), {
|
|
329
|
+
limits: opts.limits?.closer$
|
|
330
|
+
}))
|
|
321
331
|
break
|
|
322
332
|
}
|
|
323
333
|
case 9: {
|
|
324
|
-
obj.providers.
|
|
334
|
+
if (opts.limits?.providers != null && obj.providers.length === opts.limits.providers) {
|
|
335
|
+
throw new MaxLengthError('Decode error - map field "providers" had too many elements')
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
obj.providers.push(PeerInfo.codec().decode(reader, reader.uint32(), {
|
|
339
|
+
limits: opts.limits?.providers$
|
|
340
|
+
}))
|
|
325
341
|
break
|
|
326
342
|
}
|
|
327
343
|
default: {
|
|
@@ -342,7 +358,7 @@ export namespace Message {
|
|
|
342
358
|
return encodeMessage(obj, Message.codec())
|
|
343
359
|
}
|
|
344
360
|
|
|
345
|
-
export const decode = (buf: Uint8Array | Uint8ArrayList): Message => {
|
|
346
|
-
return decodeMessage(buf, Message.codec())
|
|
361
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<Message>): Message => {
|
|
362
|
+
return decodeMessage(buf, Message.codec(), opts)
|
|
347
363
|
}
|
|
348
364
|
}
|
package/src/message/utils.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { peerIdFromMultihash } from '@libp2p/peer-id'
|
|
2
2
|
import { multiaddr } from '@multiformats/multiaddr'
|
|
3
|
+
import * as Digest from 'multiformats/hashes/digest'
|
|
3
4
|
import type { PeerInfo as PBPeerInfo, ConnectionType } from './dht.js'
|
|
4
5
|
import type { PeerInfo } from '@libp2p/interface'
|
|
5
6
|
|
|
6
7
|
export function toPbPeerInfo (peer: PeerInfo, connection?: ConnectionType): PBPeerInfo {
|
|
7
8
|
const output: PBPeerInfo = {
|
|
8
|
-
id: peer.id.
|
|
9
|
+
id: peer.id.toMultihash().bytes,
|
|
9
10
|
multiaddrs: (peer.multiaddrs ?? []).map((m) => m.bytes),
|
|
10
11
|
connection
|
|
11
12
|
}
|
|
@@ -18,8 +19,10 @@ export function fromPbPeerInfo (peer: PBPeerInfo): PeerInfo {
|
|
|
18
19
|
throw new Error('Invalid peer in message')
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
const multihash = Digest.decode(peer.id)
|
|
23
|
+
|
|
21
24
|
return {
|
|
22
|
-
id:
|
|
25
|
+
id: peerIdFromMultihash(multihash),
|
|
23
26
|
multiaddrs: (peer.multiaddrs ?? []).map((a) => multiaddr(a))
|
|
24
27
|
}
|
|
25
28
|
}
|
package/src/network.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { TypedEventEmitter } from '@libp2p/interface'
|
|
1
|
+
import { InvalidParametersError, TypedEventEmitter } from '@libp2p/interface'
|
|
2
2
|
import { Libp2pRecord } from '@libp2p/record'
|
|
3
3
|
import { AdaptiveTimeout, type AdaptiveTimeoutInit } from '@libp2p/utils/adaptive-timeout'
|
|
4
4
|
import { pbStream } from 'it-protobuf-stream'
|
|
5
|
-
import { CodeError } from 'protons-runtime'
|
|
6
5
|
import { Message } from './message/dht.js'
|
|
7
6
|
import { fromPbPeerInfo } from './message/utils.js'
|
|
8
7
|
import {
|
|
@@ -88,7 +87,7 @@ export class Network extends TypedEventEmitter<NetworkEvents> implements Startab
|
|
|
88
87
|
const type = msg.type
|
|
89
88
|
|
|
90
89
|
if (type == null) {
|
|
91
|
-
throw new
|
|
90
|
+
throw new InvalidParametersError('Message type was missing')
|
|
92
91
|
}
|
|
93
92
|
|
|
94
93
|
this.log('sending %s to %p', msg.type, to)
|
|
@@ -141,7 +140,7 @@ export class Network extends TypedEventEmitter<NetworkEvents> implements Startab
|
|
|
141
140
|
const type = msg.type
|
|
142
141
|
|
|
143
142
|
if (type == null) {
|
|
144
|
-
throw new
|
|
143
|
+
throw new InvalidParametersError('Message type was missing')
|
|
145
144
|
}
|
|
146
145
|
|
|
147
146
|
this.log('sending %s to %p', msg.type, to)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { publicKeyFromProtobuf } from '@libp2p/crypto/keys'
|
|
2
|
+
import { InvalidPublicKeyError, NotFoundError } from '@libp2p/interface'
|
|
3
|
+
import { peerIdFromPublicKey } from '@libp2p/peer-id'
|
|
4
4
|
import { Libp2pRecord } from '@libp2p/record'
|
|
5
5
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
6
|
+
import { QueryError, InvalidRecordError } from '../errors.js'
|
|
6
7
|
import { MessageType } from '../message/dht.js'
|
|
7
8
|
import { PeerDistanceList } from '../peer-list/peer-distance-list.js'
|
|
8
9
|
import {
|
|
@@ -63,7 +64,7 @@ export class PeerRouting {
|
|
|
63
64
|
try {
|
|
64
65
|
peerData = await this.peerStore.get(p)
|
|
65
66
|
} catch (err: any) {
|
|
66
|
-
if (err.
|
|
67
|
+
if (err.name !== 'NotFoundError') {
|
|
67
68
|
throw err
|
|
68
69
|
}
|
|
69
70
|
}
|
|
@@ -73,7 +74,7 @@ export class PeerRouting {
|
|
|
73
74
|
try {
|
|
74
75
|
peerData = await this.peerStore.get(peer)
|
|
75
76
|
} catch (err: any) {
|
|
76
|
-
if (err.
|
|
77
|
+
if (err.name !== 'NotFoundError') {
|
|
77
78
|
throw err
|
|
78
79
|
}
|
|
79
80
|
}
|
|
@@ -113,22 +114,26 @@ export class PeerRouting {
|
|
|
113
114
|
yield event
|
|
114
115
|
|
|
115
116
|
if (event.name === 'PEER_RESPONSE' && event.record != null) {
|
|
116
|
-
const
|
|
117
|
+
const publicKey = publicKeyFromProtobuf(event.record.value)
|
|
118
|
+
const recPeer = peerIdFromPublicKey(publicKey)
|
|
117
119
|
|
|
118
120
|
// compare hashes of the pub key
|
|
119
121
|
if (!recPeer.equals(peer)) {
|
|
120
|
-
throw new
|
|
122
|
+
throw new InvalidPublicKeyError('public key does not match id')
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
if (recPeer.publicKey == null) {
|
|
124
|
-
throw new
|
|
126
|
+
throw new InvalidPublicKeyError('public key missing')
|
|
125
127
|
}
|
|
126
128
|
|
|
127
|
-
yield valueEvent({
|
|
129
|
+
yield valueEvent({
|
|
130
|
+
from: peer,
|
|
131
|
+
value: event.record.value
|
|
132
|
+
}, options)
|
|
128
133
|
}
|
|
129
134
|
}
|
|
130
135
|
|
|
131
|
-
throw new
|
|
136
|
+
throw new QueryError(`Node not responding with its public key: ${peer.toString()}`)
|
|
132
137
|
}
|
|
133
138
|
|
|
134
139
|
/**
|
|
@@ -160,7 +165,7 @@ export class PeerRouting {
|
|
|
160
165
|
const findPeerQuery: QueryFunc = async function * ({ peer, signal }) {
|
|
161
166
|
const request: Partial<Message> = {
|
|
162
167
|
type: MessageType.FIND_NODE,
|
|
163
|
-
key: id.
|
|
168
|
+
key: id.toMultihash().bytes
|
|
164
169
|
}
|
|
165
170
|
|
|
166
171
|
for await (const event of self.network.sendRequest(peer, request, {
|
|
@@ -180,7 +185,7 @@ export class PeerRouting {
|
|
|
180
185
|
}
|
|
181
186
|
}
|
|
182
187
|
|
|
183
|
-
for await (const event of this.queryManager.run(id.
|
|
188
|
+
for await (const event of this.queryManager.run(id.toMultihash().bytes, findPeerQuery, options)) {
|
|
184
189
|
if (event.name === 'FINAL_PEER') {
|
|
185
190
|
foundPeer = true
|
|
186
191
|
}
|
|
@@ -190,7 +195,7 @@ export class PeerRouting {
|
|
|
190
195
|
}
|
|
191
196
|
|
|
192
197
|
if (!foundPeer) {
|
|
193
|
-
yield queryErrorEvent({ from: this.peerId, error: new
|
|
198
|
+
yield queryErrorEvent({ from: this.peerId, error: new NotFoundError('Not found') }, options)
|
|
194
199
|
}
|
|
195
200
|
}
|
|
196
201
|
|
|
@@ -257,7 +262,7 @@ export class PeerRouting {
|
|
|
257
262
|
const errMsg = 'invalid record received, discarded'
|
|
258
263
|
this.log(errMsg)
|
|
259
264
|
|
|
260
|
-
yield queryErrorEvent({ from: event.from, error: new
|
|
265
|
+
yield queryErrorEvent({ from: event.from, error: new QueryError(errMsg) }, options)
|
|
261
266
|
continue
|
|
262
267
|
}
|
|
263
268
|
}
|
|
@@ -273,7 +278,7 @@ export class PeerRouting {
|
|
|
273
278
|
*/
|
|
274
279
|
async _verifyRecordOnline (record: DHTRecord): Promise<void> {
|
|
275
280
|
if (record.timeReceived == null) {
|
|
276
|
-
throw new
|
|
281
|
+
throw new InvalidRecordError('invalid record received')
|
|
277
282
|
}
|
|
278
283
|
|
|
279
284
|
await verifyRecord(this.validators, new Libp2pRecord(record.key, record.value, record.timeReceived))
|
|
@@ -301,7 +306,7 @@ export class PeerRouting {
|
|
|
301
306
|
multiaddrs: peer.addresses.map(({ multiaddr }) => multiaddr)
|
|
302
307
|
})
|
|
303
308
|
} catch (err: any) {
|
|
304
|
-
if (err.
|
|
309
|
+
if (err.name !== 'NotFoundError') {
|
|
305
310
|
throw err
|
|
306
311
|
}
|
|
307
312
|
}
|
package/src/query/events.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { CustomEvent } from '@libp2p/interface'
|
|
2
1
|
import type { MessageType, SendQueryEvent, PeerResponseEvent, DialPeerEvent, AddPeerEvent, ValueEvent, ProviderEvent, QueryErrorEvent, FinalPeerEvent } from '../index.js'
|
|
3
2
|
import type { PeerId, PeerInfo } from '@libp2p/interface'
|
|
4
3
|
import type { Libp2pRecord } from '@libp2p/record'
|
package/src/query/manager.ts
CHANGED
|
@@ -223,7 +223,7 @@ export class QueryManager implements Startable {
|
|
|
223
223
|
|
|
224
224
|
queryFinished = true
|
|
225
225
|
} catch (err: any) {
|
|
226
|
-
if (!this.running && err.
|
|
226
|
+
if (!this.running && err.name === 'QueryAbortedError') {
|
|
227
227
|
// ignore query aborted errors that were thrown during query manager shutdown
|
|
228
228
|
} else {
|
|
229
229
|
throw err
|
package/src/query/query-path.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { setMaxListeners } from '@libp2p/interface'
|
|
2
2
|
import { Queue } from '@libp2p/utils/queue'
|
|
3
3
|
import { anySignal } from 'any-signal'
|
|
4
4
|
import { xor as uint8ArrayXor } from 'uint8arrays/xor'
|
|
5
5
|
import { xorCompare as uint8ArrayXorCompare } from 'uint8arrays/xor-compare'
|
|
6
|
+
import { QueryAbortedError } from '../errors.js'
|
|
6
7
|
import { convertPeerId, convertBuffer } from '../utils.js'
|
|
7
8
|
import { queryErrorEvent } from './events.js'
|
|
8
9
|
import type { QueryEvent } from '../index.js'
|
|
@@ -195,7 +196,7 @@ export async function * queryPath (options: QueryPathOptions): AsyncGenerator<Qu
|
|
|
195
196
|
}
|
|
196
197
|
} catch (err) {
|
|
197
198
|
if (signal.aborted) {
|
|
198
|
-
throw new
|
|
199
|
+
throw new QueryAbortedError('Query aborted')
|
|
199
200
|
}
|
|
200
201
|
|
|
201
202
|
throw err
|
package/src/query-self.ts
CHANGED
|
@@ -125,7 +125,7 @@ export class QuerySelf implements Startable {
|
|
|
125
125
|
const start = Date.now()
|
|
126
126
|
|
|
127
127
|
const found = await pipe(
|
|
128
|
-
this.peerRouting.getClosestPeers(this.peerId.
|
|
128
|
+
this.peerRouting.getClosestPeers(this.peerId.toMultihash().bytes, {
|
|
129
129
|
signal,
|
|
130
130
|
isSelfQuery: true
|
|
131
131
|
}),
|
package/src/record/selectors.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InvalidParametersError } from '@libp2p/interface'
|
|
2
2
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
3
|
+
import { MissingSelectorError } from '../errors.js'
|
|
3
4
|
import type { Selectors } from '../index.js'
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -7,26 +8,20 @@ import type { Selectors } from '../index.js'
|
|
|
7
8
|
*/
|
|
8
9
|
export function bestRecord (selectors: Selectors, k: Uint8Array, records: Uint8Array[]): number {
|
|
9
10
|
if (records.length === 0) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
throw new CodeError(errMsg, 'ERR_NO_RECORDS_RECEIVED')
|
|
11
|
+
throw new InvalidParametersError('No records given')
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
const kStr = uint8ArrayToString(k)
|
|
16
15
|
const parts = kStr.split('/')
|
|
17
16
|
|
|
18
17
|
if (parts.length < 3) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
throw new CodeError(errMsg, 'ERR_NO_SELECTOR_FUNCTION_FOR_RECORD_KEY')
|
|
18
|
+
throw new InvalidParametersError('Record key does not have a selector function')
|
|
22
19
|
}
|
|
23
20
|
|
|
24
21
|
const selector = selectors[parts[1].toString()]
|
|
25
22
|
|
|
26
23
|
if (selector == null) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
throw new CodeError(errMsg, 'ERR_UNRECOGNIZED_KEY_PREFIX')
|
|
24
|
+
throw new MissingSelectorError(`No selector function configured for key type "${parts[1]}"`)
|
|
30
25
|
}
|
|
31
26
|
|
|
32
27
|
if (records.length === 1) {
|
package/src/record/validators.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { publicKeyFromProtobuf } from '@libp2p/crypto/keys'
|
|
2
|
+
import { InvalidParametersError } from '@libp2p/interface'
|
|
3
3
|
import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
|
|
4
4
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
5
5
|
import type { Validators } from '../index.js'
|
|
@@ -23,9 +23,7 @@ export async function verifyRecord (validators: Validators, record: Libp2pRecord
|
|
|
23
23
|
const validator = validators[parts[1].toString()]
|
|
24
24
|
|
|
25
25
|
if (validator == null) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
throw new CodeError(errMsg, 'ERR_INVALID_RECORD_KEY_TYPE')
|
|
26
|
+
throw new InvalidParametersError(`No validator available for key type "${parts[1]}"`)
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
await validator(key, record.value)
|
|
@@ -42,25 +40,24 @@ export async function verifyRecord (validators: Validators, record: Libp2pRecord
|
|
|
42
40
|
*/
|
|
43
41
|
const validatePublicKeyRecord = async (key: Uint8Array, publicKey: Uint8Array): Promise<void> => {
|
|
44
42
|
if (!(key instanceof Uint8Array)) {
|
|
45
|
-
throw new
|
|
43
|
+
throw new InvalidParametersError('"key" must be a Uint8Array')
|
|
46
44
|
}
|
|
47
45
|
|
|
48
46
|
if (key.byteLength < 5) {
|
|
49
|
-
throw new
|
|
47
|
+
throw new InvalidParametersError('Invalid public key record')
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
const prefix = uint8ArrayToString(key.subarray(0, 4))
|
|
53
51
|
|
|
54
52
|
if (prefix !== '/pk/') {
|
|
55
|
-
throw new
|
|
53
|
+
throw new InvalidParametersError('key was not prefixed with /pk/')
|
|
56
54
|
}
|
|
57
55
|
|
|
56
|
+
const pubKey = publicKeyFromProtobuf(publicKey)
|
|
58
57
|
const keyhash = key.slice(4)
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (!uint8ArrayEquals(keyhash, publicKeyHash.bytes)) {
|
|
63
|
-
throw new CodeError('public key does not match passed in key', 'ERR_INVALID_RECORD_HASH_MISMATCH')
|
|
59
|
+
if (!uint8ArrayEquals(keyhash, pubKey.toMultihash().bytes)) {
|
|
60
|
+
throw new InvalidParametersError('public key does not match passed in key')
|
|
64
61
|
}
|
|
65
62
|
}
|
|
66
63
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InvalidMessageError, TypedEventEmitter } from '@libp2p/interface'
|
|
2
2
|
import { PeerSet } from '@libp2p/peer-collections'
|
|
3
3
|
import { PeerQueue } from '@libp2p/utils/peer-queue'
|
|
4
4
|
import { pbStream } from 'it-protobuf-stream'
|
|
@@ -254,7 +254,7 @@ export class RoutingTable extends TypedEventEmitter<RoutingTableEvents> implemen
|
|
|
254
254
|
await pb.unwrap().close()
|
|
255
255
|
|
|
256
256
|
if (response.type !== MessageType.PING) {
|
|
257
|
-
throw new
|
|
257
|
+
throw new InvalidMessageError(`Incorrect message type received, expected PING got ${response.type}`)
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
return true
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { randomBytes } from '@libp2p/crypto'
|
|
2
2
|
import { setMaxListeners } from '@libp2p/interface'
|
|
3
|
-
import {
|
|
3
|
+
import { peerIdFromMultihash } from '@libp2p/peer-id'
|
|
4
4
|
import length from 'it-length'
|
|
5
|
+
import * as Digest from 'multiformats/hashes/digest'
|
|
5
6
|
import { sha256 } from 'multiformats/hashes/sha2'
|
|
6
7
|
import { xor as uint8ArrayXor } from 'uint8arrays/xor'
|
|
7
8
|
import { TABLE_REFRESH_INTERVAL, TABLE_REFRESH_QUERY_TIMEOUT } from '../constants.js'
|
|
@@ -140,7 +141,7 @@ export class RoutingTableRefresh {
|
|
|
140
141
|
const signal = AbortSignal.timeout(this.refreshQueryTimeout)
|
|
141
142
|
setMaxListeners(Infinity, signal)
|
|
142
143
|
|
|
143
|
-
const peers = await length(this.peerRouting.getClosestPeers(peerId.
|
|
144
|
+
const peers = await length(this.peerRouting.getClosestPeers(peerId.toMultihash().bytes, {
|
|
144
145
|
signal
|
|
145
146
|
}))
|
|
146
147
|
|
|
@@ -172,8 +173,9 @@ export class RoutingTableRefresh {
|
|
|
172
173
|
const randomUint16 = (randomData[1] << 8) + randomData[0]
|
|
173
174
|
|
|
174
175
|
const key = await this._makePeerId(this.routingTable.kb.localPeer.kadId, randomUint16, targetCommonPrefixLength)
|
|
176
|
+
const multihash = Digest.decode(key)
|
|
175
177
|
|
|
176
|
-
return
|
|
178
|
+
return peerIdFromMultihash(multihash)
|
|
177
179
|
}
|
|
178
180
|
|
|
179
181
|
async _makePeerId (localKadId: Uint8Array, randomPrefix: number, targetCommonPrefixLength: number): Promise<Uint8Array> {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { InvalidMessageError } from '@libp2p/interface'
|
|
2
|
+
import { peerIdFromMultihash } from '@libp2p/peer-id'
|
|
3
3
|
import { multiaddr } from '@multiformats/multiaddr'
|
|
4
4
|
import { CID } from 'multiformats/cid'
|
|
5
|
+
import * as Digest from 'multiformats/hashes/digest'
|
|
5
6
|
import type { Message } from '../../message/dht.js'
|
|
6
7
|
import type { Providers } from '../../providers'
|
|
7
8
|
import type { DHTMessageHandler } from '../index.js'
|
|
@@ -29,7 +30,7 @@ export class AddProviderHandler implements DHTMessageHandler {
|
|
|
29
30
|
this.log('start')
|
|
30
31
|
|
|
31
32
|
if (msg.key == null || msg.key.length === 0) {
|
|
32
|
-
throw new
|
|
33
|
+
throw new InvalidMessageError('Missing key')
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
let cid: CID
|
|
@@ -37,7 +38,7 @@ export class AddProviderHandler implements DHTMessageHandler {
|
|
|
37
38
|
// this is actually just the multihash, not the whole CID
|
|
38
39
|
cid = CID.decode(msg.key)
|
|
39
40
|
} catch (err: any) {
|
|
40
|
-
throw new
|
|
41
|
+
throw new InvalidMessageError('Invalid CID')
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
if (msg.providers == null || msg.providers.length === 0) {
|
|
@@ -59,7 +60,9 @@ export class AddProviderHandler implements DHTMessageHandler {
|
|
|
59
60
|
|
|
60
61
|
this.log('received provider %p for %s (addrs %s)', peerId, cid, pi.multiaddrs.map((m) => multiaddr(m).toString()))
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
const multihash = Digest.decode(pi.id)
|
|
64
|
+
|
|
65
|
+
await this.providers.addProvider(cid, peerIdFromMultihash(multihash))
|
|
63
66
|
})
|
|
64
67
|
)
|
|
65
68
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InvalidMessageError } from '@libp2p/interface'
|
|
2
2
|
import { protocols } from '@multiformats/multiaddr'
|
|
3
3
|
import { equals as uint8ArrayEquals } from 'uint8arrays'
|
|
4
4
|
import { MessageType } from '../../message/dht.js'
|
|
@@ -45,12 +45,12 @@ export class FindNodeHandler implements DHTMessageHandler {
|
|
|
45
45
|
this.log('incoming request from %p for peers closer to %b', peerId, msg.key)
|
|
46
46
|
|
|
47
47
|
if (msg.key == null) {
|
|
48
|
-
throw new
|
|
48
|
+
throw new InvalidMessageError('Invalid FIND_NODE message received - key was missing')
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
const closer: PeerInfo[] = await this.peerRouting.getCloserPeersOffline(msg.key, peerId)
|
|
52
52
|
|
|
53
|
-
if (uint8ArrayEquals(this.peerId.
|
|
53
|
+
if (uint8ArrayEquals(this.peerId.toMultihash().bytes, msg.key)) {
|
|
54
54
|
closer.push({
|
|
55
55
|
id: this.peerId,
|
|
56
56
|
multiaddrs: this.addressManager.getAddresses().map(ma => ma.decapsulateCode(protocols('p2p').code))
|
|
@@ -64,7 +64,7 @@ export class FindNodeHandler implements DHTMessageHandler {
|
|
|
64
64
|
.map(this.peerInfoMapper)
|
|
65
65
|
.filter(({ multiaddrs }) => multiaddrs.length)
|
|
66
66
|
.map(peerInfo => ({
|
|
67
|
-
id: peerInfo.id.
|
|
67
|
+
id: peerInfo.id.toMultihash().bytes,
|
|
68
68
|
multiaddrs: peerInfo.multiaddrs.map(ma => ma.bytes)
|
|
69
69
|
})),
|
|
70
70
|
providers: []
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InvalidMessageError } from '@libp2p/interface'
|
|
2
2
|
import { CID } from 'multiformats/cid'
|
|
3
3
|
import { MessageType } from '../../message/dht.js'
|
|
4
4
|
import type { PeerInfoMapper } from '../../index.js'
|
|
@@ -40,14 +40,14 @@ export class GetProvidersHandler implements DHTMessageHandler {
|
|
|
40
40
|
|
|
41
41
|
async handle (peerId: PeerId, msg: Message): Promise<Message> {
|
|
42
42
|
if (msg.key == null) {
|
|
43
|
-
throw new
|
|
43
|
+
throw new InvalidMessageError('Invalid GET_PROVIDERS message received - key was missing')
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
let cid
|
|
47
47
|
try {
|
|
48
48
|
cid = CID.decode(msg.key)
|
|
49
49
|
} catch (err: any) {
|
|
50
|
-
throw new
|
|
50
|
+
throw new InvalidMessageError('Invalid CID')
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
this.log('%p asking for providers for %s', peerId, cid)
|
|
@@ -67,14 +67,14 @@ export class GetProvidersHandler implements DHTMessageHandler {
|
|
|
67
67
|
.map(this.peerInfoMapper)
|
|
68
68
|
.filter(({ multiaddrs }) => multiaddrs.length)
|
|
69
69
|
.map(peerInfo => ({
|
|
70
|
-
id: peerInfo.id.
|
|
70
|
+
id: peerInfo.id.toMultihash().bytes,
|
|
71
71
|
multiaddrs: peerInfo.multiaddrs.map(ma => ma.bytes)
|
|
72
72
|
})),
|
|
73
73
|
providers: providerPeers
|
|
74
74
|
.map(this.peerInfoMapper)
|
|
75
75
|
.filter(({ multiaddrs }) => multiaddrs.length)
|
|
76
76
|
.map(peerInfo => ({
|
|
77
|
-
id: peerInfo.id.
|
|
77
|
+
id: peerInfo.id.toMultihash().bytes,
|
|
78
78
|
multiaddrs: peerInfo.multiaddrs.map(ma => ma.bytes)
|
|
79
79
|
}))
|
|
80
80
|
}
|
|
@@ -104,7 +104,7 @@ export class GetProvidersHandler implements DHTMessageHandler {
|
|
|
104
104
|
output.push(peerAfterFilter)
|
|
105
105
|
}
|
|
106
106
|
} catch (err: any) {
|
|
107
|
-
if (err.
|
|
107
|
+
if (err.name !== 'NotFoundError') {
|
|
108
108
|
throw err
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { publicKeyToProtobuf } from '@libp2p/crypto/keys'
|
|
2
|
+
import { InvalidMessageError, NotFoundError } from '@libp2p/interface'
|
|
2
3
|
import { Libp2pRecord } from '@libp2p/record'
|
|
3
4
|
import {
|
|
4
5
|
MAX_RECORD_AGE
|
|
@@ -41,7 +42,7 @@ export class GetValueHandler implements DHTMessageHandler {
|
|
|
41
42
|
this.log('%p asked for key %b', peerId, key)
|
|
42
43
|
|
|
43
44
|
if (key == null || key.length === 0) {
|
|
44
|
-
throw new
|
|
45
|
+
throw new InvalidMessageError('Invalid key')
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
const response: Message = {
|
|
@@ -61,12 +62,12 @@ export class GetValueHandler implements DHTMessageHandler {
|
|
|
61
62
|
const peer = await this.peerStore.get(idFromKey)
|
|
62
63
|
|
|
63
64
|
if (peer.id.publicKey == null) {
|
|
64
|
-
throw new
|
|
65
|
+
throw new NotFoundError('No public key found in key book')
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
pubKey = peer.id.publicKey
|
|
68
|
+
pubKey = publicKeyToProtobuf(peer.id.publicKey)
|
|
68
69
|
} catch (err: any) {
|
|
69
|
-
if (err.
|
|
70
|
+
if (err.name !== 'NotFoundError') {
|
|
70
71
|
throw err
|
|
71
72
|
}
|
|
72
73
|
}
|
|
@@ -91,7 +92,7 @@ export class GetValueHandler implements DHTMessageHandler {
|
|
|
91
92
|
if (closer.length > 0) {
|
|
92
93
|
this.log('had %s closer peers in routing table', closer.length)
|
|
93
94
|
response.closer = closer.map(peerInfo => ({
|
|
94
|
-
id: peerInfo.id.
|
|
95
|
+
id: peerInfo.id.toMultihash().bytes,
|
|
95
96
|
multiaddrs: peerInfo.multiaddrs.map(ma => ma.bytes)
|
|
96
97
|
}))
|
|
97
98
|
}
|
|
@@ -114,7 +115,7 @@ export class GetValueHandler implements DHTMessageHandler {
|
|
|
114
115
|
try {
|
|
115
116
|
rawRecord = await this.datastore.get(dsKey)
|
|
116
117
|
} catch (err: any) {
|
|
117
|
-
if (err.
|
|
118
|
+
if (err.name === 'NotFoundError') {
|
|
118
119
|
return undefined
|
|
119
120
|
}
|
|
120
121
|
throw err
|
|
@@ -123,10 +124,6 @@ export class GetValueHandler implements DHTMessageHandler {
|
|
|
123
124
|
// Create record from the returned bytes
|
|
124
125
|
const record = Libp2pRecord.deserialize(rawRecord)
|
|
125
126
|
|
|
126
|
-
if (record == null) {
|
|
127
|
-
throw new CodeError('Invalid record', 'ERR_INVALID_RECORD')
|
|
128
|
-
}
|
|
129
|
-
|
|
130
127
|
// Check validity: compare time received with max record age
|
|
131
128
|
if (record.timeReceived == null ||
|
|
132
129
|
Date.now() - record.timeReceived.getTime() > MAX_RECORD_AGE) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InvalidMessageError } from '@libp2p/interface'
|
|
2
2
|
import { Libp2pRecord } from '@libp2p/record'
|
|
3
3
|
import { verifyRecord } from '../../record/validators.js'
|
|
4
4
|
import { bufferToRecordKey } from '../../utils.js'
|
|
@@ -39,7 +39,7 @@ export class PutValueHandler implements DHTMessageHandler {
|
|
|
39
39
|
const errMsg = `Empty record from: ${peerId.toString()}`
|
|
40
40
|
|
|
41
41
|
this.log.error(errMsg)
|
|
42
|
-
throw new
|
|
42
|
+
throw new InvalidMessageError(errMsg)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
try {
|
package/src/topology-listener.ts
CHANGED