blind-peer 2.8.2 → 2.9.0

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 (5) hide show
  1. package/README.md +3 -5
  2. package/bin.js +130 -40
  3. package/index.js +76 -52
  4. package/lib/db.js +23 -21
  5. package/package.json +7 -4
package/README.md CHANGED
@@ -71,18 +71,16 @@ blind.addAutobaseBackground(autobase1)
71
71
 
72
72
  // Add another core
73
73
  blind.addCore(core1, autobase1.wakeupCapability.key)
74
-
75
74
  ```
76
75
 
77
76
  Related services:
78
77
 
79
- https://github.com/holepunchto/autobase-discovery
80
- https://github.com/HDegroote/dht-prometheus
81
-
78
+ https://github.com/holepunchto/autobase-discovery
79
+ https://github.com/HDegroote/dht-prometheus
82
80
 
83
81
  ## Programmatic Usage
84
82
 
85
- ``` js
83
+ ```js
86
84
  const BlindPeer = require('blind-peer')
87
85
  ```
88
86
 
package/bin.js CHANGED
@@ -16,20 +16,54 @@ const BlindPeer = require('.')
16
16
  const SERVICE_NAME = 'blind-peer'
17
17
  const DEFAULT_STORAGE_LIMIT_MB = 100_000
18
18
 
19
- const cmd = command('blind-peer',
19
+ const cmd = command(
20
+ 'blind-peer',
20
21
  flag('--storage|-s [path]', 'Storage path, defaults to ./blind-peer'),
21
- flag('--port|-p [int]', 'DHT Port to try to bind to. Only relevant when that port is not firewalled. (defaults to a random port)'),
22
- flag('--trusted-peer|-t [trusted-peer]', 'Public key of a trusted peer (allowed to set announce: true). Can be more than 1.').multiple(),
22
+ flag(
23
+ '--port|-p [int]',
24
+ 'DHT Port to try to bind to. Only relevant when that port is not firewalled. (defaults to a random port)'
25
+ ),
26
+ flag(
27
+ '--trusted-peer|-t [trusted-peer]',
28
+ 'Public key of a trusted peer (allowed to set announce: true). Can be more than 1.'
29
+ ).multiple(),
23
30
  flag('--debug|-d', 'Enable debug mode (more logs)'),
24
- flag(`--max-storage|-m [int]', 'Max storage usage, in Mb (defaults to ${DEFAULT_STORAGE_LIMIT_MB})`),
25
- flag('--autodiscovery-rpc-key [autodiscovery-rpc-key]', 'Public key where the autodiscovery service is listening. When set, the autodiscovery-seed must also be set. Can be hex or z32.'),
26
- flag('--autodiscovery-seed [autodiscovery-seed]', '64-byte seed used to authenticate to the autodiscovery service. Can be hex or z32.'),
27
- flag('--autodiscovery-service-name [autodiscovery-service-name]', `Name under which to register the service (default ${SERVICE_NAME})`),
28
- flag('--scraper-public-key [scraper-public-key]', 'Public key of a dht-prometheus scraper. Can be hex or z32.'),
29
- flag('--scraper-secret [scraper-secret]', 'Secret of the dht-prometheus scraper. Can be hex or z32.'),
31
+ flag(
32
+ `--max-storage|-m [int]', 'Max storage usage, in Mb (defaults to ${DEFAULT_STORAGE_LIMIT_MB})`
33
+ ),
34
+ flag(
35
+ '--autodiscovery-rpc-key [autodiscovery-rpc-key]',
36
+ 'Public key where the autodiscovery service is listening. When set, the autodiscovery-seed must also be set. Can be hex or z32.'
37
+ ),
38
+ flag(
39
+ '--autodiscovery-seed [autodiscovery-seed]',
40
+ '64-byte seed used to authenticate to the autodiscovery service. Can be hex or z32.'
41
+ ),
42
+ flag(
43
+ '--autodiscovery-service-name [autodiscovery-service-name]',
44
+ `Name under which to register the service (default ${SERVICE_NAME})`
45
+ ),
46
+ flag(
47
+ '--scraper-public-key [scraper-public-key]',
48
+ 'Public key of a dht-prometheus scraper. Can be hex or z32.'
49
+ ),
50
+ flag(
51
+ '--scraper-secret [scraper-secret]',
52
+ 'Secret of the dht-prometheus scraper. Can be hex or z32.'
53
+ ),
30
54
  flag('--scraper-alias [scraper-alias]', '(optional) Alias with which to register to the scraper'),
31
- flag('--log-streams', '(Temporary, Advanced): enable debug logs on the UDX streams managed by the dht'),
32
- flag('--repl [repl]', 'Expose a repl-swarm at the passed-in seed (32 bytes in hex or z32 notation). Use for debugging only.'),
55
+ flag(
56
+ '--log-streams',
57
+ '(Temporary, Advanced): enable debug logs on the UDX streams managed by the dht'
58
+ ),
59
+ flag(
60
+ '--repl [repl]',
61
+ 'Expose a repl-swarm at the passed-in seed (32 bytes in hex or z32 notation). Use for debugging only.'
62
+ ),
63
+ flag(
64
+ '--auto-shutdown-minutes [auto-shutdown-minutes]',
65
+ '(Temporary, Advanced) Automatically shut the process down after X minutes, with a variation of 20%'
66
+ ),
33
67
  async function ({ flags }) {
34
68
  const debug = flags.debug
35
69
  const logger = pino({
@@ -44,55 +78,75 @@ const cmd = command('blind-peer',
44
78
  const port = flags.port ? parseInt(flags.port) : null
45
79
 
46
80
  const maxBytes = 1_000_000 * parseInt(flags.maxStorage || DEFAULT_STORAGE_LIMIT_MB)
47
- const trustedPubKeys = (flags.trustedPeer || []).map(k => idEnc.decode(k))
81
+ const trustedPubKeys = (flags.trustedPeer || []).map((k) => idEnc.decode(k))
48
82
 
49
83
  const blindPeer = new BlindPeer(storage, { trustedPubKeys, maxBytes, port })
50
84
 
51
- blindPeer.on('flush-error', e => {
85
+ blindPeer.on('flush-error', (e) => {
52
86
  logger.warn(`Error while flushing the db: ${e.stack}`)
53
87
  })
54
88
 
55
- blindPeer.on('add-core', (record, _, stream) => {
89
+ blindPeer.on('add-new-core', (record, _, stream) => {
56
90
  try {
57
- logger.info(`add-core request received from peer ${streamToStr(stream)} for record ${recordToStr(record)}`)
91
+ if (record.announce) {
92
+ logger.info(
93
+ `add-core request received from peer ${streamToStr(stream)} for record ${recordToStr(record)}`
94
+ )
95
+ } else {
96
+ logger.debug(
97
+ `add-core request received from peer ${streamToStr(stream)} for record ${recordToStr(record)}`
98
+ )
99
+ }
58
100
  } catch (e) {
59
101
  logger.info(`Invalid add-core request received: ${e.stack}`)
60
102
  logger.info(record)
61
103
  }
62
104
  })
63
105
  blindPeer.on('delete-blocked', (stream, { key }) => {
64
- logger.info(`Blocked delete-core request from untrusted peer ${streamToStr(stream)} for core ${idEnc.normalize(key)}`)
106
+ logger.info(
107
+ `Blocked delete-core request from untrusted peer ${streamToStr(stream)} for core ${idEnc.normalize(key)}`
108
+ )
65
109
  })
66
110
  blindPeer.on('delete-core', (stream, { key, existing }) => {
67
- logger.info(`Received delete-core request from trusted peer ${streamToStr(stream)} for core ${idEnc.normalize(key)}. Existing: ${existing}`)
111
+ logger.info(
112
+ `Received delete-core request from trusted peer ${streamToStr(stream)} for core ${idEnc.normalize(key)}. Existing: ${existing}`
113
+ )
68
114
  })
69
115
  blindPeer.on('delete-core-end', (stream, { key, announced }) => {
70
- logger.info(`Completed delete-core request from trusted peer ${streamToStr(stream)} for core ${idEnc.normalize(key)}. Was announced: ${announced}`)
116
+ logger.info(
117
+ `Completed delete-core request from trusted peer ${streamToStr(stream)} for core ${idEnc.normalize(key)}. Was announced: ${announced}`
118
+ )
71
119
  })
72
120
 
73
121
  blindPeer.on('downgrade-announce', ({ record, remotePublicKey }) => {
74
122
  try {
75
- logger.info(`Downgraded announce for peer ${idEnc.normalize(remotePublicKey)} because the peer is not trusted (Original: ${recordToStr(record)})`)
123
+ logger.info(
124
+ `Downgraded announce for peer ${idEnc.normalize(remotePublicKey)} because the peer is not trusted (Original: ${recordToStr(record)})`
125
+ )
76
126
  } catch (e) {
77
127
  logger.error(`Unexpected error while logging downgrade-announce: ${e.stack}`)
78
128
  }
79
129
  })
80
130
 
81
- blindPeer.on('announce-core', core => {
131
+ blindPeer.on('announce-core', (core) => {
82
132
  logger.info(`Started announcing core ${coreToInfo(core, true)}`)
83
133
  })
84
- blindPeer.on('core-downloaded', core => {
134
+ blindPeer.on('core-downloaded', (core) => {
85
135
  logger.info(`Announced core fully downloaded: ${coreToInfo(core, true)}`)
86
136
  })
87
- blindPeer.on('core-append', core => {
137
+ blindPeer.on('core-append', (core) => {
88
138
  logger.info(`Detected announced-core length update: ${coreToInfo(core, true)}`)
89
139
  })
90
140
 
91
141
  blindPeer.on('gc-start', ({ bytesToClear }) => {
92
- logger.info(`Starting GC, trying to clear ${byteSize(bytesToClear)} (bytes allocated: ${byteSize(blindPeer.digest.bytesAllocated)} of ${byteSize(blindPeer.maxBytes)})`)
142
+ logger.info(
143
+ `Starting GC, trying to clear ${byteSize(bytesToClear)} (bytes allocated: ${byteSize(blindPeer.digest.bytesAllocated)} of ${byteSize(blindPeer.maxBytes)})`
144
+ )
93
145
  })
94
146
  blindPeer.on('gc-done', ({ bytesCleared }) => {
95
- logger.info(`Completed GC, cleared ${byteSize(bytesCleared)} bytes (bytes allocated: ${byteSize(blindPeer.digest.bytesAllocated)} of ${byteSize(blindPeer.maxBytes)})`)
147
+ logger.info(
148
+ `Completed GC, cleared ${byteSize(bytesCleared)} bytes (bytes allocated: ${byteSize(blindPeer.digest.bytesAllocated)} of ${byteSize(blindPeer.maxBytes)})`
149
+ )
96
150
  })
97
151
  if (debug) {
98
152
  blindPeer.on('core-activity', (core) => {
@@ -104,12 +158,16 @@ const cmd = command('blind-peer',
104
158
  const address = `${from.stream?.rawStream?.remoteHost}:${from.stream?.rawStream?.remotePort}`
105
159
  const remotePubKey = idEnc.normalize(from.stream.remotePublicKey)
106
160
  const key = idEnc.normalize(core.key)
107
- logger.warn(`Received invalid request for core ${key} from peer ${remotePubKey} at ${address} (${err.stack})`)
161
+ logger.warn(
162
+ `Received invalid request for core ${key} from peer ${remotePubKey} at ${address} (${err.stack})`
163
+ )
108
164
  })
109
165
 
110
166
  logger.info(`Using storage '${storage}'`)
111
167
  if (trustedPubKeys.length > 0) {
112
- logger.info(`Trusted public keys:\n -${[...blindPeer.trustedPubKeys].map(idEnc.normalize).join('\n -')}`)
168
+ logger.info(
169
+ `Trusted public keys:\n -${[...blindPeer.trustedPubKeys].map(idEnc.normalize).join('\n -')}`
170
+ )
113
171
  }
114
172
 
115
173
  let instrumentation = null
@@ -158,11 +216,16 @@ const cmd = command('blind-peer',
158
216
  const pendingWrites = stream._wreqs.length - stream._wfree.length
159
217
  if (pendingWrites >= 100) {
160
218
  nrBigStreams++
161
- logger.warn(`Stream ${stream.id} (remote id: ${stream.remoteId}) has ${pendingWrites} pending writes:\nStream JSON: ${JSON.stringify(stream.toJSON(), null, 1)}\nSocket json: ${stream.socket ? JSON.stringify(stream.socket.toJSON(), null, 1) : 'none'}\nhex streamhandle: ${b4a.toString(stream._handle, 'hex')}\nhex socket handle: ${stream.socket ? b4a.toString(stream.socket._handle, 'hex') : 'none'}`)
219
+ logger.warn(
220
+ `Stream ${stream.id} (remote id: ${stream.remoteId}) has ${pendingWrites} pending writes:\nStream JSON: ${JSON.stringify(stream.toJSON(), null, 1)}\nSocket json: ${stream.socket ? JSON.stringify(stream.socket.toJSON(), null, 1) : 'none'}\nhex streamhandle: ${b4a.toString(stream._handle, 'hex')}\nhex socket handle: ${stream.socket ? b4a.toString(stream.socket._handle, 'hex') : 'none'}`
221
+ )
162
222
  }
163
223
  }
164
- if (nrBigStreams > 0) logger.warn(`Total streams with many pending writes: ${nrBigStreams}`)
165
- } catch (e) { // we don't want to crash the process with our debugging
224
+ if (nrBigStreams > 0) {
225
+ logger.warn(`Total streams with many pending writes: ${nrBigStreams}`)
226
+ }
227
+ } catch (e) {
228
+ // we don't want to crash the process with our debugging
166
229
  logger.warn(`logStreams errored unexpectedly: ${e.stack}`)
167
230
  }
168
231
  }, 30_000)
@@ -170,8 +233,12 @@ const cmd = command('blind-peer',
170
233
 
171
234
  await blindPeer.listen()
172
235
 
173
- logger.info(`Blind peer listening, local address is ${blindPeer.swarm.dht.localAddress().host}:${blindPeer.swarm.dht.localAddress().port}`)
174
- logger.info(`Bytes allocated: ${byteSize(blindPeer.digest.bytesAllocated)} of ${byteSize(blindPeer.maxBytes)}`)
236
+ logger.info(
237
+ `Blind peer listening, local address is ${blindPeer.swarm.dht.localAddress().host}:${blindPeer.swarm.dht.localAddress().port}`
238
+ )
239
+ logger.info(
240
+ `Bytes allocated: ${byteSize(blindPeer.digest.bytesAllocated)} of ${byteSize(blindPeer.maxBytes)}`
241
+ )
175
242
 
176
243
  if (flags.autodiscoveryRpcKey) {
177
244
  const autodiscoveryRpcKey = idEnc.decode(flags.autodiscoveryRpcKey)
@@ -180,11 +247,20 @@ const cmd = command('blind-peer',
180
247
  const registerClient = new RegisterClient(autodiscoveryRpcKey, blindPeer.swarm.dht, seed)
181
248
 
182
249
  // No need to block on this, so we run it in the background
183
- logger.info(`Registering own RPC key rpc key ${idEnc.normalize(blindPeer.publicKey)} with service '${serviceName}' at autodiscovery service ${idEnc.normalize(autodiscoveryRpcKey)} (using public key ${idEnc.normalize(registerClient.keyPair.publicKey)})`)
184
- registerClient.putService(blindPeer.publicKey, serviceName)
185
- .then(() => { logger.info('Successfully requested to be added to the autodiscovery service') })
186
- .catch(e => { logger.warn(`Failed to register to the autodiscovery service: ${e.stack}`) })
187
- .finally(() => { registerClient.close().catch(safetyCatch) })
250
+ logger.info(
251
+ `Registering own RPC key rpc key ${idEnc.normalize(blindPeer.publicKey)} with service '${serviceName}' at autodiscovery service ${idEnc.normalize(autodiscoveryRpcKey)} (using public key ${idEnc.normalize(registerClient.keyPair.publicKey)})`
252
+ )
253
+ registerClient
254
+ .putService(blindPeer.publicKey, serviceName)
255
+ .then(() => {
256
+ logger.info('Successfully requested to be added to the autodiscovery service')
257
+ })
258
+ .catch((e) => {
259
+ logger.warn(`Failed to register to the autodiscovery service: ${e.stack}`)
260
+ })
261
+ .finally(() => {
262
+ registerClient.close().catch(safetyCatch)
263
+ })
188
264
  }
189
265
 
190
266
  if (flags.scraperPublicKey) {
@@ -195,7 +271,9 @@ const cmd = command('blind-peer',
195
271
  const scraperSecret = idEnc.decode(flags.scraperSecret)
196
272
 
197
273
  let prometheusAlias = flags.scraperAlias
198
- if (prometheusAlias && prometheusAlias.length > 99) throw new Error('The Prometheus alias must have length less than 100')
274
+ if (prometheusAlias && prometheusAlias.length > 99) {
275
+ throw new Error('The Prometheus alias must have length less than 100')
276
+ }
199
277
  if (!prometheusAlias) {
200
278
  prometheusAlias = `blind-peer-${idEnc.normalize(swarm.keyPair.publicKey)}`.slice(0, 99)
201
279
  }
@@ -216,20 +294,32 @@ const cmd = command('blind-peer',
216
294
 
217
295
  logger.info(`Listening at ${idEnc.normalize(blindPeer.publicKey)}`)
218
296
  logger.info(`Encryption public key is ${idEnc.normalize(blindPeer.encryptionPublicKey)}`)
297
+
298
+ if (flags.autoShutdownMinutes) {
299
+ const delay = flags.autoShutdownMinutes * (1 + Math.random() / 5)
300
+ logger.warn(`Automatically shutting down the process in ${delay} minutes`)
301
+ setTimeout(
302
+ () => {
303
+ logger.warn('Auto-shutdown triggered. Shutting down...')
304
+ goodbye.exit()
305
+ },
306
+ delay * 60 * 1000
307
+ )
308
+ }
219
309
  }
220
310
  )
221
311
 
222
- function recordToStr (record) {
312
+ function recordToStr(record) {
223
313
  const discKey = hypCrypto.discoveryKey(record.key)
224
314
  return `DB Record for discovery key ${idEnc.normalize(discKey)} with priority: ${record.priority}. Announcing? ${record.announce}`
225
315
  }
226
316
 
227
- function streamToStr (stream) {
317
+ function streamToStr(stream) {
228
318
  const pubKey = idEnc.normalize(stream.remotePublicKey)
229
319
  return `${pubKey}`
230
320
  }
231
321
 
232
- function coreToInfo (core, includePublicKey = false) {
322
+ function coreToInfo(core, includePublicKey = false) {
233
323
  const discKey = hypCrypto.discoveryKey(core.key)
234
324
  let res = `Discovery key ${idEnc.normalize(discKey)} (${core.contiguousLength} / ${core.length}, ${core.peers.length} peers)`
235
325
  if (includePublicKey) res += `. Public key: ${idEnc.normalize(core.key)}`
package/index.js CHANGED
@@ -18,7 +18,7 @@ const { AddCoreEncoding } = require('blind-peer-encodings')
18
18
  const { DeleteCoreEncoding } = require('blind-peer-encodings')
19
19
 
20
20
  class CoreTracker {
21
- constructor (blindPeer, core) {
21
+ constructor(blindPeer, core) {
22
22
  this.blindPeer = blindPeer
23
23
  this.core = core
24
24
  this.destroyed = false
@@ -40,7 +40,7 @@ class CoreTracker {
40
40
  this.core.on('append', onupdate)
41
41
  }
42
42
 
43
- _onupdate () {
43
+ _onupdate() {
44
44
  this.updated = true
45
45
  if (!this.record) return
46
46
 
@@ -50,7 +50,7 @@ class CoreTracker {
50
50
  this.blindPeer.flush().then(this.announceToReferrerBound, safetyCatch)
51
51
  }
52
52
 
53
- _onactive () {
53
+ _onactive() {
54
54
  this.activated = true
55
55
 
56
56
  if (this.record) {
@@ -60,7 +60,8 @@ class CoreTracker {
60
60
  this.blindPeer.emit('core-activity', this.core, this.record)
61
61
  }
62
62
 
63
- gc () { // TODO: support gc-ing till less than last block (required hypercore to support getting byteLength at arbitrary versions)
63
+ gc() {
64
+ // TODO: support gc-ing till less than last block (required hypercore to support getting byteLength at arbitrary versions)
64
65
  const bytesCleared = this.core.byteLength
65
66
  const blocksCleared = this.core.length
66
67
  this.record.bytesAllocated = this.core.byteLength - bytesCleared
@@ -76,7 +77,7 @@ class CoreTracker {
76
77
  return bytesCleared
77
78
  }
78
79
 
79
- async refresh () {
80
+ async refresh() {
80
81
  await this.core.ready()
81
82
  if (this.destroyed) return
82
83
 
@@ -93,11 +94,14 @@ class CoreTracker {
93
94
  if (this.activated) this._onactive()
94
95
  }
95
96
 
96
- announceToReferrer () {
97
+ announceToReferrer() {
97
98
  if (!this.record || !this.record.referrer) return
98
- if (!this.referrerDiscoveryKey) this.referrerDiscoveryKey = crypto.discoveryKey(this.record.referrer)
99
+ if (!this.referrerDiscoveryKey)
100
+ this.referrerDiscoveryKey = crypto.discoveryKey(this.record.referrer)
99
101
 
100
- const sessions = this.blindPeer.wakeup.getSessions(null, { discoveryKey: this.referrerDiscoveryKey })
102
+ const sessions = this.blindPeer.wakeup.getSessions(null, {
103
+ discoveryKey: this.referrerDiscoveryKey
104
+ })
101
105
  if (sessions.length === 0) return
102
106
 
103
107
  const wakeup = [{ key: this.core.key, length: this.core.length }]
@@ -116,21 +120,21 @@ class CoreTracker {
116
120
  }
117
121
  }
118
122
 
119
- destroy () {
123
+ destroy() {
120
124
  if (this.destroyed) return
121
125
  this.destroyed = true
122
126
  }
123
127
  }
124
128
 
125
129
  class WakeupHandler {
126
- constructor (db, key, discoveryKey) {
130
+ constructor(db, key, discoveryKey) {
127
131
  this.db = db
128
132
  this.key = key
129
133
  this.discoveryKey = discoveryKey
130
134
  this.active = false
131
135
  }
132
136
 
133
- async onpeeractive (peer, session) {
137
+ async onpeeractive(peer, session) {
134
138
  const referrer = this.key
135
139
  const query = {
136
140
  gte: { referrer },
@@ -150,7 +154,10 @@ class WakeupHandler {
150
154
  }
151
155
 
152
156
  class BlindPeer extends ReadyResource {
153
- constructor (rocks, { swarm, store, wakeup, maxBytes = 100_000_000_000, enableGc = true, trustedPubKeys, port } = {}) {
157
+ constructor(
158
+ rocks,
159
+ { swarm, store, wakeup, maxBytes = 100_000_000_000, enableGc = true, trustedPubKeys, port } = {}
160
+ ) {
154
161
  super()
155
162
 
156
163
  this.rocks = typeof rocks === 'string' ? new RocksDB(rocks) : rocks
@@ -181,36 +188,39 @@ class BlindPeer extends ReadyResource {
181
188
  }
182
189
  }
183
190
 
184
- get encryptionPublicKey () {
191
+ get encryptionPublicKey() {
185
192
  return this.db.encryptionKeyPair.publicKey
186
193
  }
187
194
 
188
- get publicKey () {
195
+ get publicKey() {
189
196
  return this.swarm.keyPair.publicKey
190
197
  }
191
198
 
192
- get digest () {
199
+ get digest() {
193
200
  return this.db.digest
194
201
  }
195
202
 
196
- get nrAnnouncedCores () {
203
+ get nrAnnouncedCores() {
197
204
  return this.announcedCores.size
198
205
  }
199
206
 
200
- addTrustedPubKey (key) {
207
+ addTrustedPubKey(key) {
201
208
  this.trustedPubKeys.add(IdEnc.normalize(key))
202
209
  }
203
210
 
204
- _isTrustedPeer (key) {
211
+ _isTrustedPeer(key) {
205
212
  return this.trustedPubKeys.has(IdEnc.normalize(key))
206
213
  }
207
214
 
208
- async _open () {
215
+ async _open() {
209
216
  await this.store.ready()
210
217
 
211
218
  // legacy, we can remove once current ones are upgraded
212
219
  const { secretKey } = await this.store.createKeyPair('blind-mirror-swarm')
213
- this.db = new BlindPeerDB(this.rocks.session(), { swarming: secretKey.subarray(0, 32), encryption: null })
220
+ this.db = new BlindPeerDB(this.rocks.session(), {
221
+ swarming: secretKey.subarray(0, 32),
222
+ encryption: null
223
+ })
214
224
  await this.db.ready()
215
225
 
216
226
  // We don't need to track our own db, so we set this handler after the db core opened
@@ -218,7 +228,8 @@ class BlindPeer extends ReadyResource {
218
228
 
219
229
  if (this.swarm === null) {
220
230
  const swarmOpts = { keyPair: this.db.swarmingKeyPair }
221
- if (this._port) swarmOpts.port = typeof this._port === 'number' ? [this._port, this._port + 64] : this._port
231
+ if (this._port)
232
+ swarmOpts.port = typeof this._port === 'number' ? [this._port, this._port + 64] : this._port
222
233
  this.swarm = new Hyperswarm(swarmOpts)
223
234
  }
224
235
  this.swarm.on('connection', this._onconnection.bind(this))
@@ -232,7 +243,7 @@ class BlindPeer extends ReadyResource {
232
243
  this.flushInterval = setInterval(this.flush.bind(this), 10_000)
233
244
  }
234
245
 
235
- async _onwakeup (discoveryKey, muxer) {
246
+ async _onwakeup(discoveryKey, muxer) {
236
247
  this.stats.wakeups++
237
248
 
238
249
  const auth = await this.store.storage.getAuth(discoveryKey)
@@ -256,16 +267,17 @@ class BlindPeer extends ReadyResource {
256
267
  stream.once('close', () => w.destroy())
257
268
  }
258
269
 
259
- async listen () {
270
+ async listen() {
260
271
  if (!this.opened) await this.ready()
261
272
  return this.swarm.listen()
262
273
  }
263
274
 
264
- needsGc () {
275
+ needsGc() {
265
276
  return this.digest.bytesAllocated >= this.maxBytes
266
277
  }
267
278
 
268
- async _gc () { // Do not call directly (assumes lock)
279
+ async _gc() {
280
+ // Do not call directly (assumes lock)
269
281
  if (!this.needsGc()) return
270
282
 
271
283
  const bytesToClear = this.digest.bytesAllocated - this.maxBytes
@@ -302,7 +314,7 @@ class BlindPeer extends ReadyResource {
302
314
  this.emit('gc-done', { bytesCleared })
303
315
  }
304
316
 
305
- _onreferrerupdates (updates) {
317
+ _onreferrerupdates(updates) {
306
318
  const pending = new Set()
307
319
 
308
320
  for (const u of updates) {
@@ -319,7 +331,7 @@ class BlindPeer extends ReadyResource {
319
331
  }
320
332
  }
321
333
 
322
- _oncoreopen (core) {
334
+ _oncoreopen(core) {
323
335
  const session = new Hypercore({ core, weak: true })
324
336
  const id = b4a.toString(core.discoveryKey, 'hex')
325
337
  const tracker = new CoreTracker(this, session)
@@ -338,7 +350,8 @@ class BlindPeer extends ReadyResource {
338
350
  })
339
351
  }
340
352
 
341
- async flush () { // not allowed to throw
353
+ async flush() {
354
+ // not allowed to throw
342
355
  if (!(await this.lock.lock())) return
343
356
  try {
344
357
  if (this.enableGc && this.needsGc()) await this._gc()
@@ -351,7 +364,7 @@ class BlindPeer extends ReadyResource {
351
364
  }
352
365
  }
353
366
 
354
- _onconnection (conn) {
367
+ _onconnection(conn) {
355
368
  if (this.closing) {
356
369
  conn.destroy()
357
370
  return
@@ -369,7 +382,7 @@ class BlindPeer extends ReadyResource {
369
382
  rpc.respond('delete-core', DeleteCoreEncoding, this._ondeletecore.bind(this, conn))
370
383
  }
371
384
 
372
- async _activateCore (stream, record) {
385
+ async _activateCore(stream, record) {
373
386
  this.stats.activations++
374
387
 
375
388
  const core = this.store.get({ key: record.key })
@@ -391,7 +404,7 @@ class BlindPeer extends ReadyResource {
391
404
  stream.on('close', () => core.close().catch(safetyCatch))
392
405
  }
393
406
 
394
- async _announceCore (key) {
407
+ async _announceCore(key) {
395
408
  const coreId = IdEnc.normalize(key)
396
409
  if (this.announcedCores.has(coreId)) return
397
410
 
@@ -417,7 +430,7 @@ class BlindPeer extends ReadyResource {
417
430
  this.emit('announce-core', core)
418
431
  }
419
432
 
420
- async _onaddcore (stream, record) {
433
+ async _onaddcore(stream, record) {
421
434
  if (!this.opened) await this.ready()
422
435
 
423
436
  record.priority = Math.min(record.priority, 1) // 2 is reserved for trusted peers
@@ -433,6 +446,7 @@ class BlindPeer extends ReadyResource {
433
446
  if (!existing || upgradeToAnnounce) {
434
447
  this.db.addCore(record)
435
448
  await this.flush() // flush now as important data
449
+ this.emit('add-new-core', record, true, stream)
436
450
  }
437
451
 
438
452
  if (record.referrer) {
@@ -457,13 +471,13 @@ class BlindPeer extends ReadyResource {
457
471
  return coreRecord
458
472
  }
459
473
 
460
- async _ondeletecore (stream, { key }) {
474
+ async _ondeletecore(stream, { key }) {
461
475
  if (!this._isTrustedPeer(stream.remotePublicKey)) {
462
476
  this.emit('delete-blocked', stream, { key })
463
477
  throw new Error('Only trusted peers can delete cores')
464
478
  }
465
479
 
466
- const existing = await this.db.getCoreRecord(key) !== null
480
+ const existing = (await this.db.getCoreRecord(key)) !== null
467
481
  this.emit('delete-core', stream, { key, existing })
468
482
  if (!existing) return false
469
483
 
@@ -502,7 +516,7 @@ class BlindPeer extends ReadyResource {
502
516
  return true
503
517
  }
504
518
 
505
- async _close () {
519
+ async _close() {
506
520
  clearInterval(this.flushInterval)
507
521
  if (this.ownsWakeup) this.wakeup.destroy()
508
522
  if (this.ownsSwarm) await this.swarm.destroy()
@@ -512,68 +526,78 @@ class BlindPeer extends ReadyResource {
512
526
  await this.rocks.close()
513
527
  }
514
528
 
515
- registerMetrics (promClient) {
529
+ registerMetrics(promClient) {
530
+ this.wakeup.registerMetrics(promClient)
531
+
516
532
  const self = this
517
- new promClient.Gauge({ // eslint-disable-line no-new
533
+ new promClient.Gauge({
534
+ // eslint-disable-line no-new
518
535
  name: 'blind_peer_bytes_allocated',
519
536
  help: 'The amount of bytes allocated by the hyperdb (as reported in its digest)',
520
- collect () {
537
+ collect() {
521
538
  this.set(self.digest.bytesAllocated)
522
539
  }
523
540
  })
524
541
 
525
- new promClient.Gauge({ // eslint-disable-line no-new
542
+ new promClient.Gauge({
543
+ // eslint-disable-line no-new
526
544
  name: 'blind_peer_cores',
527
545
  help: 'The amount of cores (as reported in its digest)',
528
- collect () {
546
+ collect() {
529
547
  this.set(self.digest.cores)
530
548
  }
531
549
  })
532
550
 
533
- new promClient.Gauge({ // eslint-disable-line no-new
551
+ new promClient.Gauge({
552
+ // eslint-disable-line no-new
534
553
  name: 'blind_peer_cores_added',
535
554
  help: 'The total amount of add-core RPC requests that have been processed',
536
- collect () {
555
+ collect() {
537
556
  this.set(self.stats.coresAdded)
538
557
  }
539
558
  })
540
559
 
541
- new promClient.Gauge({ // eslint-disable-line no-new
560
+ new promClient.Gauge({
561
+ // eslint-disable-line no-new
542
562
  name: 'blind_peer_bytes_gcd',
543
563
  help: 'The total amount of bytes garbage collected since the process started',
544
- collect () {
564
+ collect() {
545
565
  this.set(self.stats.bytesGcd)
546
566
  }
547
567
  })
548
568
 
549
- new promClient.Gauge({ // eslint-disable-line no-new
569
+ new promClient.Gauge({
570
+ // eslint-disable-line no-new
550
571
  name: 'blind_peer_core_activations',
551
572
  help: 'The total amount of hypercore activations since the process started',
552
- collect () {
573
+ collect() {
553
574
  this.set(self.stats.activations)
554
575
  }
555
576
  })
556
577
 
557
- new promClient.Gauge({ // eslint-disable-line no-new
578
+ new promClient.Gauge({
579
+ // eslint-disable-line no-new
558
580
  name: 'blind_peer_wakeups',
559
581
  help: 'The total amount of hypercore wakeups since the process started',
560
- collect () {
582
+ collect() {
561
583
  this.set(self.stats.wakeups)
562
584
  }
563
585
  })
564
586
 
565
- new promClient.Gauge({ // eslint-disable-line no-new
587
+ new promClient.Gauge({
588
+ // eslint-disable-line no-new
566
589
  name: 'blind_peer_db_flushes',
567
590
  help: 'The total amount of database flushes since the process started',
568
- collect () {
591
+ collect() {
569
592
  this.set(self.db.stats.flushes)
570
593
  }
571
594
  })
572
595
 
573
- new promClient.Gauge({ // eslint-disable-line no-new
596
+ new promClient.Gauge({
597
+ // eslint-disable-line no-new
574
598
  name: 'blind_peer_announced_cores',
575
599
  help: 'The amount of announced cores',
576
- collect () {
600
+ collect() {
577
601
  this.set(self.nrAnnouncedCores)
578
602
  }
579
603
  })
package/lib/db.js CHANGED
@@ -8,7 +8,7 @@ const { definition: spec } = require('blind-peer-encodings')
8
8
  const MAX_PRIO = 2
9
9
 
10
10
  module.exports = class BlindPeerDB extends ReadyResource {
11
- constructor (db, auth) {
11
+ constructor(db, auth) {
12
12
  super()
13
13
 
14
14
  this.db = HyperDB.rocks(db, spec)
@@ -29,19 +29,19 @@ module.exports = class BlindPeerDB extends ReadyResource {
29
29
  this.ready().catch(noop)
30
30
  }
31
31
 
32
- find (col, q) {
32
+ find(col, q) {
33
33
  return this.db.find(col, q)
34
34
  }
35
35
 
36
- get (col, q) {
36
+ get(col, q) {
37
37
  return this.db.get(col, q)
38
38
  }
39
39
 
40
- getCoreRecord (key) {
40
+ getCoreRecord(key) {
41
41
  return this.get('@blind-peer/cores', { key })
42
42
  }
43
43
 
44
- async _open () {
44
+ async _open() {
45
45
  await this.db.ready()
46
46
 
47
47
  const auth = await this.db.get('@blind-peer/auth')
@@ -63,7 +63,8 @@ module.exports = class BlindPeerDB extends ReadyResource {
63
63
  await this.db.flush()
64
64
  }
65
65
 
66
- async flush () { // The caller is responsible for ensuring this runs in a lock
66
+ async flush() {
67
+ // The caller is responsible for ensuring this runs in a lock
67
68
  if (!this.opened) await this.ready()
68
69
 
69
70
  const coresAdding = this.coresAdding
@@ -96,9 +97,7 @@ module.exports = class BlindPeerDB extends ReadyResource {
96
97
  if (existing) {
97
98
  if (!info.announce && (info.priority || 0) <= existing.priority) continue // would be a downgrade, which we never want
98
99
 
99
- existing.priority = Math.min(
100
- Math.max(info.priority || 0, existing.priority)
101
- )
100
+ existing.priority = Math.min(Math.max(info.priority || 0, existing.priority))
102
101
  existing.announce = info.announce || existing.announce
103
102
  existing.updated = time
104
103
  existing.active = time
@@ -128,7 +127,7 @@ module.exports = class BlindPeerDB extends ReadyResource {
128
127
 
129
128
  const updated = c.length !== core.length
130
129
 
131
- bytesAllocated += (core.bytesAllocated - c.bytesAllocated)
130
+ bytesAllocated += core.bytesAllocated - c.bytesAllocated
132
131
 
133
132
  c.length = core.length
134
133
  c.bytesAllocated = core.bytesAllocated
@@ -153,38 +152,41 @@ module.exports = class BlindPeerDB extends ReadyResource {
153
152
  await tx.flush()
154
153
  }
155
154
 
156
- async hasCore (key) {
155
+ async hasCore(key) {
157
156
  key = IdEnc.decode(key)
158
- return await this.db.get('@blind-peer/cores', { key }) !== null
157
+ return (await this.db.get('@blind-peer/cores', { key })) !== null
159
158
  }
160
159
 
161
- addCore (info) {
160
+ addCore(info) {
162
161
  this.coresAdding.push(info)
163
162
  }
164
163
 
165
- deleteCore (key) {
164
+ deleteCore(key) {
166
165
  this.coresDeleting.push(key)
167
166
  }
168
167
 
169
- updateCore (core, id) { // TODO: id is technically optional
168
+ updateCore(core, id) {
169
+ // TODO: id is technically optional
170
170
  this.coresUpdated.set(id, core)
171
171
  }
172
172
 
173
- updated () {
174
- return this.coresAdding.length > 0 || this.coresUpdated.size > 0 || this.coresDeleting.length > 0
173
+ updated() {
174
+ return (
175
+ this.coresAdding.length > 0 || this.coresUpdated.size > 0 || this.coresDeleting.length > 0
176
+ )
175
177
  }
176
178
 
177
- createGcCandidateReadStream () {
179
+ createGcCandidateReadStream() {
178
180
  return this.db.find('@blind-peer/cores-by-activity')
179
181
  }
180
182
 
181
- createAnnouncingCoresStream () {
183
+ createAnnouncingCoresStream() {
182
184
  return this.db.find('@blind-peer/cores-by-announce')
183
185
  }
184
186
 
185
- async _close () {
187
+ async _close() {
186
188
  await this.db.close()
187
189
  }
188
190
  }
189
191
 
190
- function noop () {}
192
+ function noop() {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blind-peer",
3
- "version": "2.8.2",
3
+ "version": "2.9.0",
4
4
  "description": "Blind peers help keep hypercores available",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -24,7 +24,7 @@
24
24
  "paparam": "^1.8.0",
25
25
  "pino": "^9.6.0",
26
26
  "protomux-rpc": "^1.7.1",
27
- "protomux-wakeup": "^2.6.0",
27
+ "protomux-wakeup": "^2.7.0",
28
28
  "ready-resource": "^1.1.2",
29
29
  "repl-swarm": "^2.3.0",
30
30
  "rocksdb-native": "^3.1.6",
@@ -37,8 +37,9 @@
37
37
  "brittle": "^3.7.0",
38
38
  "debounceify": "^1.1.0",
39
39
  "hyperdht": "^6.20.1",
40
+ "prettier": "^3.6.2",
41
+ "prettier-config-holepunch": "^2.0.0",
40
42
  "prom-client": "^15.1.3",
41
- "standard": "^17.1.2",
42
43
  "test-tmp": "^1.3.0"
43
44
  },
44
45
  "files": [
@@ -47,7 +48,9 @@
47
48
  "lib/"
48
49
  ],
49
50
  "scripts": {
50
- "test": "standard && brittle test/*.js"
51
+ "format": "prettier --write .",
52
+ "test": "prettier --check . && brittle test/*.js",
53
+ "test:bare": "bare test/basic.js"
51
54
  },
52
55
  "repository": {
53
56
  "type": "git",