blind-peer 3.1.0 → 3.2.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 (2) hide show
  1. package/index.js +143 -3
  2. package/package.json +5 -4
package/index.js CHANGED
@@ -5,6 +5,7 @@ const ReadyResource = require('ready-resource')
5
5
  const Hyperswarm = require('hyperswarm')
6
6
  const ProtomuxRPC = require('protomux-rpc')
7
7
  const c = require('compact-encoding')
8
+ const BlindPeerMuxer = require('blind-peer-muxer')
8
9
  const b4a = require('b4a')
9
10
  const crypto = require('hypercore-crypto')
10
11
  const safetyCatch = require('safety-catch')
@@ -14,8 +15,7 @@ const IdEnc = require('hypercore-id-encoding')
14
15
 
15
16
  const BlindPeerDB = require('./lib/db.js')
16
17
 
17
- const { AddCoreEncoding } = require('blind-peer-encodings')
18
- const { DeleteCoreEncoding } = require('blind-peer-encodings')
18
+ const { AddCoreEncoding, DeleteCoreEncoding } = require('blind-peer-encodings')
19
19
 
20
20
  class CoreTracker {
21
21
  constructor(blindPeer, core) {
@@ -228,7 +228,10 @@ class BlindPeer extends ReadyResource {
228
228
  bytesGcd: 0,
229
229
  coresAdded: 0,
230
230
  activations: 0,
231
- wakeups: 0
231
+ wakeups: 0,
232
+ addCoresRx: 0,
233
+ muxerPaired: 0,
234
+ muxerErrors: 0
232
235
  }
233
236
  }
234
237
 
@@ -426,6 +429,23 @@ class BlindPeer extends ReadyResource {
426
429
 
427
430
  rpc.respond('add-core', AddCoreEncoding, this._onaddcore.bind(this, conn))
428
431
  rpc.respond('delete-core', DeleteCoreEncoding, this._ondeletecore.bind(this, conn))
432
+
433
+ const self = this
434
+ BlindPeerMuxer.pair(conn, function () {
435
+ self.emit('muxer-paired', conn)
436
+ self.stats.muxerPaired++
437
+ new BlindPeerMuxer(conn, {
438
+ async oncores(request) {
439
+ try {
440
+ await self._onaddcores(conn, request)
441
+ } catch (e) {
442
+ self.stats.muxerErrors++
443
+ self.emit('muxer-error', e, conn)
444
+ throw e
445
+ }
446
+ }
447
+ })
448
+ })
429
449
  }
430
450
 
431
451
  async _activateCore(stream, record) {
@@ -497,6 +517,7 @@ class BlindPeer extends ReadyResource {
497
517
  const replicationLag = core.length - core.contiguousLength
498
518
  if (replicationLag > this.replicationLagThreshold || core.length === 0) {
499
519
  activeSession = this.swarm.join(core.discoveryKey, { server: true, client: true })
520
+ this.emit('core-client-mode-changed', core, true)
500
521
  } else {
501
522
  activeSession = this.swarm.join(core.discoveryKey, { server: true, client: false })
502
523
  }
@@ -549,6 +570,100 @@ class BlindPeer extends ReadyResource {
549
570
  return coreRecord
550
571
  }
551
572
 
573
+ async _onaddcores(stream, request) {
574
+ this.stats.addCoresRx++
575
+ const priority = Math.min(request.priority, 1) // 2 is reserved for trusted peers
576
+ const { cores, referrer } = request
577
+
578
+ if (request.announce !== false && !this._isTrustedPeer(stream.remotePublicKey)) {
579
+ // Note: we can't use the original downgrade-announce event because that assumes a 'record' object
580
+ this.emit('add-cores-downgrade-announce', {
581
+ request,
582
+ remotePublicKey: stream.remotePublicKey
583
+ })
584
+ request.announce = false
585
+ }
586
+
587
+ this.emit('add-cores-received', stream, request)
588
+
589
+ const discKeys = []
590
+ const overview = new Map()
591
+ for (const c of cores) {
592
+ const discoveryKey = crypto.discoveryKey(c.key)
593
+ discKeys.push(discoveryKey)
594
+ const id = IdEnc.normalize(discoveryKey)
595
+ overview.set(id, {
596
+ key: c.key,
597
+ discoveryKey,
598
+ remoteLength: c.length,
599
+ announce: request.announce,
600
+ priority,
601
+ referrer,
602
+ ownLength: 0, // set later
603
+ ownContigLength: 0, // set later
604
+ needsActivation: false // changed later if needed
605
+ })
606
+ }
607
+
608
+ const recordsToAdd = []
609
+ const infos = await this.store.storage.getInfos(discKeys)
610
+ for (let i = 0; i < infos.length; i++) {
611
+ const id = IdEnc.normalize(discKeys[i])
612
+ const storageInfo = infos[i]
613
+ const entry = overview.get(id)
614
+
615
+ // Note: just the null check does not suffice for storageInfo, because we already try
616
+ // loading some keys from other contexts, like when the system core of an autobase is
617
+ // used as a referrer.
618
+ if (
619
+ storageInfo === null ||
620
+ entry.announce ||
621
+ (storageInfo.head === null && entry.remoteLength > 0)
622
+ ) {
623
+ entry.needsActivation = true
624
+ recordsToAdd.push({
625
+ key: entry.key,
626
+ priority: entry.priority,
627
+ announce: entry.announce,
628
+ referrer: entry.referrer
629
+ })
630
+ } else {
631
+ entry.ownLength = storageInfo.head?.length || 0
632
+ entry.ownContigLength = storageInfo.hints?.contiguousLength || 0
633
+ if (entry.ownLength !== entry.remoteLength) entry.needsActivation = true
634
+ if (entry.ownLength > entry.ownContigLength) entry.needsActivation = true
635
+ }
636
+ }
637
+
638
+ // Note: not race condition safe when called with the same cores at a similar time,
639
+ // but it's no problem if we do add the same core twice
640
+ for (const record of recordsToAdd) this.db.addCore(record)
641
+ if (recordsToAdd.length > 0) await this.flush() // flush now as important data
642
+
643
+ if (referrer) {
644
+ const muxer = stream.userData
645
+ const core = this.store.get({ key: referrer })
646
+ await core.ready()
647
+ const discoveryKey = core.discoveryKey
648
+ await core.close()
649
+ await this._onwakeup(discoveryKey, muxer)
650
+ }
651
+
652
+ for (const r of recordsToAdd) this.emit('add-new-core', r, true, stream)
653
+
654
+ const activateProms = []
655
+ for (const entry of overview.values()) {
656
+ if (!entry.needsActivation) continue
657
+ this.stats.coresAdded++
658
+ this.emit('add-core', entry, true, stream)
659
+ activateProms.push(this._activateCore(stream, entry))
660
+ }
661
+ await Promise.all(activateProms)
662
+
663
+ this.emit('add-cores-done', stream, request)
664
+ return null
665
+ }
666
+
552
667
  async _ondeletecore(stream, { key }) {
553
668
  if (!this._isTrustedPeer(stream.remotePublicKey)) {
554
669
  this.emit('delete-blocked', stream, { key })
@@ -679,6 +794,31 @@ class BlindPeer extends ReadyResource {
679
794
  this.set(self.nrAnnouncedCores)
680
795
  }
681
796
  })
797
+
798
+ new promClient.Gauge({
799
+ // eslint-disable-line no-new
800
+ name: 'blind_peer_muxer_errors',
801
+ help: 'The amount of errors on the protomux muxer',
802
+ collect() {
803
+ this.set(self.stats.muxerErrors)
804
+ }
805
+ })
806
+ new promClient.Gauge({
807
+ // eslint-disable-line no-new
808
+ name: 'blind_peer_muxer_paired',
809
+ help: 'The amount of blind-peer-muxer sessions paired',
810
+ collect() {
811
+ this.set(self.stats.muxerPaired)
812
+ }
813
+ })
814
+ new promClient.Gauge({
815
+ // eslint-disable-line no-new
816
+ name: 'blind_peer_add_cores_rx',
817
+ help: 'The amount of add-cores requests received',
818
+ collect() {
819
+ this.set(self.stats.addCoresRx)
820
+ }
821
+ })
682
822
  }
683
823
  }
684
824
 
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "blind-peer",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "Blind peers help keep hypercores available",
5
5
  "main": "index.js",
6
6
  "dependencies": {
7
7
  "autobase": "^7.0.18",
8
8
  "b4a": "^1.6.7",
9
- "blind-peer-encodings": "^3.1.0",
9
+ "blind-peer-encodings": "^3.1.1",
10
+ "blind-peer-muxer": "^1.0.0",
10
11
  "compact-encoding": "^2.16.0",
11
12
  "corestore": "^7.4.4",
12
13
  "hypercore": "^11.0.12",
@@ -26,13 +27,13 @@
26
27
  "devDependencies": {
27
28
  "bare-events": "^2.8.2",
28
29
  "bare-process": "^4.2.2",
29
- "blind-peering": "^1.13.0",
30
+ "bare-prom-client": "^15.1.3",
31
+ "blind-peering": "^2.0.0",
30
32
  "brittle": "^3.7.0",
31
33
  "debounceify": "^1.1.0",
32
34
  "hyperdht": "^6.20.1",
33
35
  "prettier": "^3.6.2",
34
36
  "prettier-config-holepunch": "^2.0.0",
35
- "bare-prom-client": "^15.1.3",
36
37
  "test-tmp": "^1.3.0",
37
38
  "which-runtime": "^1.3.2"
38
39
  },