libp2p 0.34.0 → 0.35.3

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 (36) hide show
  1. package/dist/src/config.d.ts +0 -6
  2. package/dist/src/config.d.ts.map +1 -1
  3. package/dist/src/connection-manager/auto-dialler.d.ts +56 -0
  4. package/dist/src/connection-manager/auto-dialler.d.ts.map +1 -0
  5. package/dist/src/connection-manager/index.d.ts +0 -10
  6. package/dist/src/connection-manager/index.d.ts.map +1 -1
  7. package/dist/src/dht/dht-peer-routing.d.ts.map +1 -1
  8. package/dist/src/dialer/dial-request.d.ts.map +1 -1
  9. package/dist/src/dialer/index.d.ts +1 -1
  10. package/dist/src/dialer/index.d.ts.map +1 -1
  11. package/dist/src/errors.d.ts +24 -0
  12. package/dist/src/index.d.ts +3 -27
  13. package/dist/src/index.d.ts.map +1 -1
  14. package/dist/src/keychain/cms.d.ts.map +1 -1
  15. package/dist/src/keychain/index.d.ts.map +1 -1
  16. package/dist/src/peer-routing.d.ts +8 -1
  17. package/dist/src/peer-routing.d.ts.map +1 -1
  18. package/dist/src/peer-store/book.d.ts.map +1 -1
  19. package/package.json +32 -31
  20. package/src/circuit/index.js +2 -2
  21. package/src/config.js +1 -7
  22. package/src/connection-manager/auto-dialler.js +118 -0
  23. package/src/connection-manager/index.js +0 -52
  24. package/src/content-routing/index.js +2 -2
  25. package/src/dht/dht-peer-routing.js +6 -2
  26. package/src/dialer/dial-request.js +10 -3
  27. package/src/dialer/index.js +10 -9
  28. package/src/errors.js +25 -1
  29. package/src/index.js +9 -9
  30. package/src/keychain/cms.js +7 -6
  31. package/src/keychain/index.js +25 -24
  32. package/src/nat-manager.js +1 -1
  33. package/src/peer-routing.js +21 -8
  34. package/src/peer-store/book.js +4 -7
  35. package/src/ping/index.js +2 -2
  36. package/src/upgrader.js +1 -1
@@ -0,0 +1,118 @@
1
+ 'use strict'
2
+
3
+ const debug = require('debug')
4
+ const mergeOptions = require('merge-options')
5
+ // @ts-ignore retimer does not have types
6
+ const retimer = require('retimer')
7
+
8
+ const log = Object.assign(debug('libp2p:connection-manager:auto-dialler'), {
9
+ error: debug('libp2p:connection-manager:auto-dialler:err')
10
+ })
11
+
12
+ const defaultOptions = {
13
+ enabled: true,
14
+ minConnections: 0,
15
+ autoDialInterval: 10000
16
+ }
17
+
18
+ /**
19
+ * @typedef {import('../index')} Libp2p
20
+ * @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} AutoDiallerOptions
25
+ * @property {boolean} [enabled = true] - Should preemptively guarantee connections are above the low watermark
26
+ * @property {number} [minConnections = 0] - The minimum number of connections to avoid pruning
27
+ * @property {number} [autoDialInterval = 10000] - How often, in milliseconds, it should preemptively guarantee connections are above the low watermark
28
+ */
29
+
30
+ class AutoDialler {
31
+ /**
32
+ * Proactively tries to connect to known peers stored in the PeerStore.
33
+ * It will keep the number of connections below the upper limit and sort
34
+ * the peers to connect based on wether we know their keys and protocols.
35
+ *
36
+ * @class
37
+ * @param {Libp2p} libp2p
38
+ * @param {AutoDiallerOptions} options
39
+ */
40
+ constructor (libp2p, options = {}) {
41
+ this._options = mergeOptions.call({ ignoreUndefined: true }, defaultOptions, options)
42
+ this._libp2p = libp2p
43
+ this._running = false
44
+ this._autoDialTimeout = null
45
+ this._autoDial = this._autoDial.bind(this)
46
+
47
+ log('options: %j', this._options)
48
+ }
49
+
50
+ /**
51
+ * Starts the auto dialer
52
+ */
53
+ start () {
54
+ if (!this._options.enabled) {
55
+ log('not enabled')
56
+ return
57
+ }
58
+
59
+ this._running = true
60
+ this._autoDial()
61
+ log('started')
62
+ }
63
+
64
+ /**
65
+ * Stops the auto dialler
66
+ */
67
+ async stop () {
68
+ if (!this._options.enabled) {
69
+ log('not enabled')
70
+ return
71
+ }
72
+
73
+ this._running = false
74
+ this._autoDialTimeout && this._autoDialTimeout.clear()
75
+ log('stopped')
76
+ }
77
+
78
+ async _autoDial () {
79
+ const minConnections = this._options.minConnections
80
+
81
+ // Already has enough connections
82
+ if (this._libp2p.connections.size >= minConnections) {
83
+ this._autoDialTimeout = retimer(this._autoDial, this._options.autoDialInterval)
84
+ return
85
+ }
86
+
87
+ // Sort peers on wether we know protocols of public keys for them
88
+ const peers = Array.from(this._libp2p.peerStore.peers.values())
89
+ .sort((a, b) => {
90
+ if (b.protocols && b.protocols.length && (!a.protocols || !a.protocols.length)) {
91
+ return 1
92
+ } else if (b.id.pubKey && !a.id.pubKey) {
93
+ return 1
94
+ }
95
+ return -1
96
+ })
97
+
98
+ for (let i = 0; this._running && i < peers.length && this._libp2p.connections.size < minConnections; i++) {
99
+ if (!this._libp2p.connectionManager.get(peers[i].id)) {
100
+ log('connecting to a peerStore stored peer %s', peers[i].id.toB58String())
101
+ try {
102
+ await this._libp2p.dialer.connectToPeer(peers[i].id)
103
+ } catch (/** @type {any} */ err) {
104
+ log.error('could not connect to peerStore stored peer', err)
105
+ }
106
+ }
107
+ }
108
+
109
+ // Connection Manager was stopped
110
+ if (!this._running) {
111
+ return
112
+ }
113
+
114
+ this._autoDialTimeout = retimer(this._autoDial, this._options.autoDialInterval)
115
+ }
116
+ }
117
+
118
+ module.exports = AutoDialler
@@ -94,9 +94,7 @@ class ConnectionManager extends EventEmitter {
94
94
 
95
95
  this._started = false
96
96
  this._timer = null
97
- this._autoDialTimeout = null
98
97
  this._checkMetrics = this._checkMetrics.bind(this)
99
- this._autoDial = this._autoDial.bind(this)
100
98
 
101
99
  this._latencyMonitor = new LatencyMonitor({
102
100
  latencyCheckIntervalMs: this._options.pollInterval,
@@ -128,8 +126,6 @@ class ConnectionManager extends EventEmitter {
128
126
 
129
127
  this._started = true
130
128
  log('started')
131
-
132
- this._options.autoDial && this._autoDial()
133
129
  }
134
130
 
135
131
  /**
@@ -138,7 +134,6 @@ class ConnectionManager extends EventEmitter {
138
134
  * @async
139
135
  */
140
136
  async stop () {
141
- this._autoDialTimeout && this._autoDialTimeout.clear()
142
137
  this._timer && this._timer.clear()
143
138
 
144
139
  this._latencyMonitor.removeListener('data', this._onLatencyMeasure)
@@ -312,53 +307,6 @@ class ConnectionManager extends EventEmitter {
312
307
  }
313
308
  }
314
309
 
315
- /**
316
- * Proactively tries to connect to known peers stored in the PeerStore.
317
- * It will keep the number of connections below the upper limit and sort
318
- * the peers to connect based on wether we know their keys and protocols.
319
- *
320
- * @async
321
- * @private
322
- */
323
- async _autoDial () {
324
- const minConnections = this._options.minConnections
325
-
326
- // Already has enough connections
327
- if (this.size >= minConnections) {
328
- this._autoDialTimeout = retimer(this._autoDial, this._options.autoDialInterval)
329
- return
330
- }
331
-
332
- // Sort peers on wether we know protocols of public keys for them
333
- const peers = Array.from(this._libp2p.peerStore.peers.values())
334
- .sort((a, b) => {
335
- if (b.protocols && b.protocols.length && (!a.protocols || !a.protocols.length)) {
336
- return 1
337
- } else if (b.id.pubKey && !a.id.pubKey) {
338
- return 1
339
- }
340
- return -1
341
- })
342
-
343
- for (let i = 0; i < peers.length && this.size < minConnections; i++) {
344
- if (!this.get(peers[i].id)) {
345
- log('connecting to a peerStore stored peer %s', peers[i].id.toB58String())
346
- try {
347
- await this._libp2p.dialer.connectToPeer(peers[i].id)
348
-
349
- // Connection Manager was stopped
350
- if (!this._started) {
351
- return
352
- }
353
- } catch (/** @type {any} */ err) {
354
- log.error('could not connect to peerStore stored peer', err)
355
- }
356
- }
357
- }
358
-
359
- this._autoDialTimeout = retimer(this._autoDial, this._options.autoDialInterval)
360
- }
361
-
362
310
  /**
363
311
  * If we have more connections than our maximum, close a connection
364
312
  * to the lowest valued peer.
@@ -54,7 +54,7 @@ class ContentRouting {
54
54
  */
55
55
  async * findProviders (key, options = {}) {
56
56
  if (!this.routers.length) {
57
- throw errCode(new Error('No content this.routers available'), 'NO_ROUTERS_AVAILABLE')
57
+ throw errCode(new Error('No content this.routers available'), codes.ERR_NO_ROUTERS_AVAILABLE)
58
58
  }
59
59
 
60
60
  yield * pipe(
@@ -77,7 +77,7 @@ class ContentRouting {
77
77
  */
78
78
  async provide (key) {
79
79
  if (!this.routers.length) {
80
- throw errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE')
80
+ throw errCode(new Error('No content routers available'), codes.ERR_NO_ROUTERS_AVAILABLE)
81
81
  }
82
82
 
83
83
  await Promise.all(this.routers.map((router) => router.provide(key)))
@@ -27,8 +27,12 @@ class DHTPeerRouting {
27
27
  */
28
28
  async findPeer (peerId, options = {}) {
29
29
  for await (const event of this._dht.findPeer(peerId, options)) {
30
- if (event.name === 'FINAL_PEER') {
31
- return event.peer
30
+ if (event.name === 'PEER_RESPONSE') {
31
+ const peer = event.closer.find(peerData => peerData.id.equals(peerId))
32
+
33
+ if (peer) {
34
+ return peer
35
+ }
32
36
  }
33
37
  }
34
38
 
@@ -1,11 +1,13 @@
1
1
  'use strict'
2
2
 
3
3
  const errCode = require('err-code')
4
- const AbortController = require('abort-controller').default
5
4
  const { anySignal } = require('any-signal')
6
5
  // @ts-ignore p-fifo does not export types
7
6
  const FIFO = require('p-fifo')
8
7
  const pAny = require('p-any')
8
+ // @ts-expect-error setMaxListeners is missing from the types
9
+ const { setMaxListeners } = require('events')
10
+ const { codes } = require('../errors')
9
11
 
10
12
  /**
11
13
  * @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
@@ -54,12 +56,17 @@ class DialRequest {
54
56
  const tokens = this.dialer.getTokens(this.addrs.length)
55
57
  // If no tokens are available, throw
56
58
  if (tokens.length < 1) {
57
- throw errCode(new Error('No dial tokens available'), 'ERR_NO_DIAL_TOKENS')
59
+ throw errCode(new Error('No dial tokens available'), codes.ERR_NO_DIAL_TOKENS)
58
60
  }
59
61
 
60
62
  const tokenHolder = new FIFO()
61
63
  tokens.forEach(token => tokenHolder.push(token))
62
- const dialAbortControllers = this.addrs.map(() => new AbortController())
64
+ const dialAbortControllers = this.addrs.map(() => {
65
+ const controller = new AbortController()
66
+ setMaxListeners && setMaxListeners(Infinity, controller.signal)
67
+
68
+ return controller
69
+ })
63
70
  let completedDials = 0
64
71
 
65
72
  try {
@@ -6,8 +6,7 @@ const log = Object.assign(debug('libp2p:dialer'), {
6
6
  })
7
7
  const errCode = require('err-code')
8
8
  const { Multiaddr } = require('multiaddr')
9
- // @ts-ignore timeout-abourt-controles does not export types
10
- const TimeoutController = require('timeout-abort-controller')
9
+ const { TimeoutController } = require('timeout-abort-controller')
11
10
  const { AbortError } = require('abortable-iterator')
12
11
  const { anySignal } = require('any-signal')
13
12
 
@@ -156,14 +155,16 @@ class Dialer {
156
155
  this._pendingDialTargets.set(id, { resolve, reject })
157
156
  })
158
157
 
159
- const dialTarget = await Promise.race([
160
- this._createDialTarget(peer),
161
- cancellablePromise
162
- ])
163
-
164
- this._pendingDialTargets.delete(id)
158
+ try {
159
+ const dialTarget = await Promise.race([
160
+ this._createDialTarget(peer),
161
+ cancellablePromise
162
+ ])
165
163
 
166
- return dialTarget
164
+ return dialTarget
165
+ } finally {
166
+ this._pendingDialTargets.delete(id)
167
+ }
167
168
  }
168
169
 
169
170
  /**
package/src/errors.js CHANGED
@@ -36,5 +36,29 @@ exports.codes = {
36
36
  ERR_TRANSPORT_DIAL_FAILED: 'ERR_TRANSPORT_DIAL_FAILED',
37
37
  ERR_UNSUPPORTED_PROTOCOL: 'ERR_UNSUPPORTED_PROTOCOL',
38
38
  ERR_INVALID_MULTIADDR: 'ERR_INVALID_MULTIADDR',
39
- ERR_SIGNATURE_NOT_VALID: 'ERR_SIGNATURE_NOT_VALID'
39
+ ERR_SIGNATURE_NOT_VALID: 'ERR_SIGNATURE_NOT_VALID',
40
+ ERR_FIND_SELF: 'ERR_FIND_SELF',
41
+ ERR_NO_ROUTERS_AVAILABLE: 'ERR_NO_ROUTERS_AVAILABLE',
42
+ ERR_CONNECTION_NOT_MULTIPLEXED: 'ERR_CONNECTION_NOT_MULTIPLEXED',
43
+ ERR_NO_DIAL_TOKENS: 'ERR_NO_DIAL_TOKENS',
44
+ ERR_KEYCHAIN_REQUIRED: 'ERR_KEYCHAIN_REQUIRED',
45
+ ERR_INVALID_CMS: 'ERR_INVALID_CMS',
46
+ ERR_MISSING_KEYS: 'ERR_MISSING_KEYS',
47
+ ERR_NO_KEY: 'ERR_NO_KEY',
48
+ ERR_INVALID_KEY_NAME: 'ERR_INVALID_KEY_NAME',
49
+ ERR_INVALID_KEY_TYPE: 'ERR_INVALID_KEY_TYPE',
50
+ ERR_KEY_ALREADY_EXISTS: 'ERR_KEY_ALREADY_EXISTS',
51
+ ERR_INVALID_KEY_SIZE: 'ERR_INVALID_KEY_SIZE',
52
+ ERR_KEY_NOT_FOUND: 'ERR_KEY_NOT_FOUND',
53
+ ERR_OLD_KEY_NAME_INVALID: 'ERR_OLD_KEY_NAME_INVALID',
54
+ ERR_NEW_KEY_NAME_INVALID: 'ERR_NEW_KEY_NAME_INVALID',
55
+ ERR_PASSWORD_REQUIRED: 'ERR_PASSWORD_REQUIRED',
56
+ ERR_PEM_REQUIRED: 'ERR_PEM_REQUIRED',
57
+ ERR_CANNOT_READ_KEY: 'ERR_CANNOT_READ_KEY',
58
+ ERR_MISSING_PRIVATE_KEY: 'ERR_MISSING_PRIVATE_KEY',
59
+ ERR_INVALID_OLD_PASS_TYPE: 'ERR_INVALID_OLD_PASS_TYPE',
60
+ ERR_INVALID_NEW_PASS_TYPE: 'ERR_INVALID_NEW_PASS_TYPE',
61
+ ERR_INVALID_PASS_LENGTH: 'ERR_INVALID_PASS_LENGTH',
62
+ ERR_NOT_IMPLEMENTED: 'ERR_NOT_IMPLEMENTED',
63
+ ERR_WRONG_PING_ACK: 'ERR_WRONG_PING_ACK'
40
64
  }
package/src/index.js CHANGED
@@ -18,6 +18,7 @@ const { codes, messages } = require('./errors')
18
18
 
19
19
  const AddressManager = require('./address-manager')
20
20
  const ConnectionManager = require('./connection-manager')
21
+ const AutoDialler = require('./connection-manager/auto-dialler')
21
22
  const Circuit = require('./circuit/transport')
22
23
  const Relay = require('./circuit')
23
24
  const Dialer = require('./dialer')
@@ -55,16 +56,9 @@ const { updateSelfPeerRecord } = require('./record/utils')
55
56
  * @property {MuxedStream} stream
56
57
  * @property {string} protocol
57
58
  *
58
- * @typedef {Object} RandomWalkOptions
59
- * @property {boolean} [enabled = false]
60
- * @property {number} [queriesPerPeriod = 1]
61
- * @property {number} [interval = 300e3]
62
- * @property {number} [timeout = 10e3]
63
- *
64
59
  * @typedef {Object} DhtOptions
65
60
  * @property {boolean} [enabled = false]
66
61
  * @property {number} [kBucketSize = 20]
67
- * @property {RandomWalkOptions} [randomWalk]
68
62
  * @property {boolean} [clientMode]
69
63
  * @property {import('libp2p-interfaces/src/types').DhtSelectors} [selectors]
70
64
  * @property {import('libp2p-interfaces/src/types').DhtValidators} [validators]
@@ -193,9 +187,13 @@ class Libp2p extends EventEmitter {
193
187
 
194
188
  // Create the Connection Manager
195
189
  this.connectionManager = new ConnectionManager(this, {
196
- autoDial: this._config.peerDiscovery.autoDial,
197
190
  ...this._options.connectionManager
198
191
  })
192
+ this._autodialler = new AutoDialler(this, {
193
+ enabled: this._config.peerDiscovery.autoDial,
194
+ minConnections: this._options.connectionManager.minConnections,
195
+ autoDialInterval: this._options.connectionManager.autoDialInterval
196
+ })
199
197
 
200
198
  // Create Metrics
201
199
  if (this._options.metrics.enabled) {
@@ -380,6 +378,8 @@ class Libp2p extends EventEmitter {
380
378
 
381
379
  this.relay && this.relay.stop()
382
380
  this.peerRouting.stop()
381
+ this._autodialler.stop()
382
+ await (this._dht && this._dht.stop())
383
383
 
384
384
  for (const service of this._discovery.values()) {
385
385
  service.removeListener('peer', this._onDiscoveryPeer)
@@ -394,7 +394,6 @@ class Libp2p extends EventEmitter {
394
394
 
395
395
  await Promise.all([
396
396
  this.pubsub && this.pubsub.stop(),
397
- this._dht && this._dht.stop(),
398
397
  this.metrics && this.metrics.stop()
399
398
  ])
400
399
 
@@ -650,6 +649,7 @@ class Libp2p extends EventEmitter {
650
649
  }
651
650
 
652
651
  this.connectionManager.start()
652
+ this._autodialler.start()
653
653
 
654
654
  // Peer discovery
655
655
  await this._setupPeerDiscovery()
@@ -10,6 +10,7 @@ const { certificateForKey, findAsync } = require('./util')
10
10
  const errcode = require('err-code')
11
11
  const { fromString: uint8ArrayFromString } = require('uint8arrays/from-string')
12
12
  const { toString: uint8ArrayToString } = require('uint8arrays/to-string')
13
+ const { codes } = require('../errors')
13
14
 
14
15
  const privates = new WeakMap()
15
16
 
@@ -31,7 +32,7 @@ class CMS {
31
32
  */
32
33
  constructor (keychain, dek) {
33
34
  if (!keychain) {
34
- throw errcode(new Error('keychain is required'), 'ERR_KEYCHAIN_REQUIRED')
35
+ throw errcode(new Error('keychain is required'), codes.ERR_KEYCHAIN_REQUIRED)
35
36
  }
36
37
 
37
38
  this.keychain = keychain
@@ -49,7 +50,7 @@ class CMS {
49
50
  */
50
51
  async encrypt (name, plain) {
51
52
  if (!(plain instanceof Uint8Array)) {
52
- throw errcode(new Error('Plain data must be a Uint8Array'), 'ERR_INVALID_PARAMS')
53
+ throw errcode(new Error('Plain data must be a Uint8Array'), codes.ERR_INVALID_PARAMETERS)
53
54
  }
54
55
 
55
56
  const key = await this.keychain.findKeyByName(name)
@@ -81,7 +82,7 @@ class CMS {
81
82
  */
82
83
  async decrypt (cmsData) {
83
84
  if (!(cmsData instanceof Uint8Array)) {
84
- throw errcode(new Error('CMS data is required'), 'ERR_INVALID_PARAMS')
85
+ throw errcode(new Error('CMS data is required'), codes.ERR_INVALID_PARAMETERS)
85
86
  }
86
87
 
87
88
  let cms
@@ -91,7 +92,7 @@ class CMS {
91
92
  // @ts-ignore not defined
92
93
  cms = forge.pkcs7.messageFromAsn1(obj)
93
94
  } catch (/** @type {any} */ err) {
94
- throw errcode(new Error('Invalid CMS: ' + err.message), 'ERR_INVALID_CMS')
95
+ throw errcode(new Error('Invalid CMS: ' + err.message), codes.ERR_INVALID_CMS)
95
96
  }
96
97
 
97
98
  // Find a recipient whose key we hold. We only deal with recipient certs
@@ -123,7 +124,7 @@ class CMS {
123
124
  if (!r) {
124
125
  // @ts-ignore cms types not defined
125
126
  const missingKeys = recipients.map(r => r.keyId)
126
- throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), 'ERR_MISSING_KEYS', {
127
+ throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), codes.ERR_MISSING_KEYS, {
127
128
  missingKeys
128
129
  })
129
130
  }
@@ -131,7 +132,7 @@ class CMS {
131
132
  const key = await this.keychain.findKeyById(r.keyId)
132
133
 
133
134
  if (!key) {
134
- throw errcode(new Error('No key available to decrypto'), 'ERR_NO_KEY')
135
+ throw errcode(new Error('No key available to decrypto'), codes.ERR_NO_KEY)
135
136
  }
136
137
 
137
138
  const pem = await this.keychain._getPrivateKey(key.name)
@@ -10,6 +10,7 @@ const crypto = require('libp2p-crypto')
10
10
  const { Key } = require('interface-datastore/key')
11
11
  const CMS = require('./cms')
12
12
  const errcode = require('err-code')
13
+ const { codes } = require('../errors')
13
14
  const { toString: uint8ArrayToString } = require('uint8arrays/to-string')
14
15
  const { fromString: uint8ArrayFromString } = require('uint8arrays/from-string')
15
16
 
@@ -210,21 +211,21 @@ class Keychain {
210
211
  const self = this
211
212
 
212
213
  if (!validateKeyName(name) || name === 'self') {
213
- return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
214
+ return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
214
215
  }
215
216
 
216
217
  if (typeof type !== 'string') {
217
- return throwDelayed(errcode(new Error(`Invalid key type '${type}'`), 'ERR_INVALID_KEY_TYPE'))
218
+ return throwDelayed(errcode(new Error(`Invalid key type '${type}'`), codes.ERR_INVALID_KEY_TYPE))
218
219
  }
219
220
 
220
221
  const dsname = DsName(name)
221
222
  const exists = await self.store.has(dsname)
222
- if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
223
+ if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
223
224
 
224
225
  switch (type.toLowerCase()) {
225
226
  case 'rsa':
226
227
  if (!Number.isSafeInteger(size) || size < 2048) {
227
- return throwDelayed(errcode(new Error(`Invalid RSA key size ${size}`), 'ERR_INVALID_KEY_SIZE'))
228
+ return throwDelayed(errcode(new Error(`Invalid RSA key size ${size}`), codes.ERR_INVALID_KEY_SIZE))
228
229
  }
229
230
  break
230
231
  default:
@@ -297,7 +298,7 @@ class Keychain {
297
298
  */
298
299
  async findKeyByName (name) {
299
300
  if (!validateKeyName(name)) {
300
- return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
301
+ return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
301
302
  }
302
303
 
303
304
  const dsname = DsInfoName(name)
@@ -305,7 +306,7 @@ class Keychain {
305
306
  const res = await this.store.get(dsname)
306
307
  return JSON.parse(uint8ArrayToString(res))
307
308
  } catch (/** @type {any} */ err) {
308
- return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), 'ERR_KEY_NOT_FOUND'))
309
+ return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), codes.ERR_KEY_NOT_FOUND))
309
310
  }
310
311
  }
311
312
 
@@ -318,7 +319,7 @@ class Keychain {
318
319
  async removeKey (name) {
319
320
  const self = this
320
321
  if (!validateKeyName(name) || name === 'self') {
321
- return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
322
+ return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
322
323
  }
323
324
  const dsname = DsName(name)
324
325
  const keyInfo = await self.findKeyByName(name)
@@ -339,10 +340,10 @@ class Keychain {
339
340
  async renameKey (oldName, newName) {
340
341
  const self = this
341
342
  if (!validateKeyName(oldName) || oldName === 'self') {
342
- return throwDelayed(errcode(new Error(`Invalid old key name '${oldName}'`), 'ERR_OLD_KEY_NAME_INVALID'))
343
+ return throwDelayed(errcode(new Error(`Invalid old key name '${oldName}'`), codes.ERR_OLD_KEY_NAME_INVALID))
343
344
  }
344
345
  if (!validateKeyName(newName) || newName === 'self') {
345
- return throwDelayed(errcode(new Error(`Invalid new key name '${newName}'`), 'ERR_NEW_KEY_NAME_INVALID'))
346
+ return throwDelayed(errcode(new Error(`Invalid new key name '${newName}'`), codes.ERR_NEW_KEY_NAME_INVALID))
346
347
  }
347
348
  const oldDsname = DsName(oldName)
348
349
  const newDsname = DsName(newName)
@@ -350,7 +351,7 @@ class Keychain {
350
351
  const newInfoName = DsInfoName(newName)
351
352
 
352
353
  const exists = await self.store.has(newDsname)
353
- if (exists) return throwDelayed(errcode(new Error(`Key '${newName}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
354
+ if (exists) return throwDelayed(errcode(new Error(`Key '${newName}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
354
355
 
355
356
  try {
356
357
  const pem = await self.store.get(oldDsname)
@@ -379,10 +380,10 @@ class Keychain {
379
380
  */
380
381
  async exportKey (name, password) {
381
382
  if (!validateKeyName(name)) {
382
- return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
383
+ return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
383
384
  }
384
385
  if (!password) {
385
- return throwDelayed(errcode(new Error('Password is required'), 'ERR_PASSWORD_REQUIRED'))
386
+ return throwDelayed(errcode(new Error('Password is required'), codes.ERR_PASSWORD_REQUIRED))
386
387
  }
387
388
 
388
389
  const dsname = DsName(name)
@@ -409,20 +410,20 @@ class Keychain {
409
410
  async importKey (name, pem, password) {
410
411
  const self = this
411
412
  if (!validateKeyName(name) || name === 'self') {
412
- return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
413
+ return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
413
414
  }
414
415
  if (!pem) {
415
- return throwDelayed(errcode(new Error('PEM encoded key is required'), 'ERR_PEM_REQUIRED'))
416
+ return throwDelayed(errcode(new Error('PEM encoded key is required'), codes.ERR_PEM_REQUIRED))
416
417
  }
417
418
  const dsname = DsName(name)
418
419
  const exists = await self.store.has(dsname)
419
- if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
420
+ if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
420
421
 
421
422
  let privateKey
422
423
  try {
423
424
  privateKey = await crypto.keys.import(pem, password)
424
425
  } catch (/** @type {any} */ err) {
425
- return throwDelayed(errcode(new Error('Cannot read the key, most likely the password is wrong'), 'ERR_CANNOT_READ_KEY'))
426
+ return throwDelayed(errcode(new Error('Cannot read the key, most likely the password is wrong'), codes.ERR_CANNOT_READ_KEY))
426
427
  }
427
428
 
428
429
  let kid
@@ -457,16 +458,16 @@ class Keychain {
457
458
  async importPeer (name, peer) {
458
459
  const self = this
459
460
  if (!validateKeyName(name)) {
460
- return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
461
+ return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
461
462
  }
462
463
  if (!peer || !peer.privKey) {
463
- return throwDelayed(errcode(new Error('Peer.privKey is required'), 'ERR_MISSING_PRIVATE_KEY'))
464
+ return throwDelayed(errcode(new Error('Peer.privKey is required'), codes.ERR_MISSING_PRIVATE_KEY))
464
465
  }
465
466
 
466
467
  const privateKey = peer.privKey
467
468
  const dsname = DsName(name)
468
469
  const exists = await self.store.has(dsname)
469
- if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
470
+ if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
470
471
 
471
472
  try {
472
473
  const kid = await privateKey.id()
@@ -495,7 +496,7 @@ class Keychain {
495
496
  */
496
497
  async _getPrivateKey (name) {
497
498
  if (!validateKeyName(name)) {
498
- return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
499
+ return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
499
500
  }
500
501
 
501
502
  try {
@@ -503,7 +504,7 @@ class Keychain {
503
504
  const res = await this.store.get(dsname)
504
505
  return uint8ArrayToString(res)
505
506
  } catch (/** @type {any} */ err) {
506
- return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), 'ERR_KEY_NOT_FOUND'))
507
+ return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), codes.ERR_KEY_NOT_FOUND))
507
508
  }
508
509
  }
509
510
 
@@ -515,13 +516,13 @@ class Keychain {
515
516
  */
516
517
  async rotateKeychainPass (oldPass, newPass) {
517
518
  if (typeof oldPass !== 'string') {
518
- return throwDelayed(errcode(new Error(`Invalid old pass type '${typeof oldPass}'`), 'ERR_INVALID_OLD_PASS_TYPE'))
519
+ return throwDelayed(errcode(new Error(`Invalid old pass type '${typeof oldPass}'`), codes.ERR_INVALID_OLD_PASS_TYPE))
519
520
  }
520
521
  if (typeof newPass !== 'string') {
521
- return throwDelayed(errcode(new Error(`Invalid new pass type '${typeof newPass}'`), 'ERR_INVALID_NEW_PASS_TYPE'))
522
+ return throwDelayed(errcode(new Error(`Invalid new pass type '${typeof newPass}'`), codes.ERR_INVALID_NEW_PASS_TYPE))
522
523
  }
523
524
  if (newPass.length < 20) {
524
- return throwDelayed(errcode(new Error(`Invalid pass length ${newPass.length}`), 'ERR_INVALID_PASS_LENGTH'))
525
+ return throwDelayed(errcode(new Error(`Invalid pass length ${newPass.length}`), codes.ERR_INVALID_PASS_LENGTH))
525
526
  }
526
527
  log('recreating keychain')
527
528
  const oldDek = privates.get(this).dek
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  // @ts-ignore nat-api does not export types
4
- const NatAPI = require('@motrix/nat-api')
4
+ const NatAPI = require('nat-api')
5
5
  const debug = require('debug')
6
6
  const { promisify } = require('es6-promisify')
7
7
  const { Multiaddr } = require('multiaddr')