hypercore 11.12.1 → 11.13.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.
package/lib/audit.js CHANGED
@@ -112,7 +112,7 @@ module.exports = async function auditCore (core, { tree = true, blocks = true, b
112
112
  core.bitfield.set(index, false)
113
113
 
114
114
  const page = core.bitfield.getBitfield(index)
115
- if (page.bitfield) tx.setBitfieldPage(page.index, page.bitfield)
115
+ if (page.bitfield) tx.putBitfieldPage(page.index, page.bitfield)
116
116
  else tx.deleteBitfieldPage(page.idnex)
117
117
  continue
118
118
  }
package/lib/messages.js CHANGED
@@ -514,13 +514,20 @@ wire.data = {
514
514
  wire.noData = {
515
515
  preencode (state, m) {
516
516
  c.uint.preencode(state, m.request)
517
+ c.uint.preencode(state, m.reason ? 1 : 0)
518
+ if (m.reason) c.uint.preencode(state, m.reason)
517
519
  },
518
520
  encode (state, m) {
519
521
  c.uint.encode(state, m.request)
522
+ c.uint.encode(state, m.reason ? 1 : 0)
523
+ if (m.reason) c.uint.encode(state, m.reason)
520
524
  },
521
525
  decode (state, m) {
526
+ const request = c.uint.decode(state)
527
+ const flags = state.start < state.end ? c.uint.decode(state) : 0
522
528
  return {
523
- request: c.uint.decode(state)
529
+ request,
530
+ reason: flags & 1 ? c.uint.decode(state) : 0
524
531
  }
525
532
  }
526
533
  }
package/lib/replicator.js CHANGED
@@ -44,6 +44,11 @@ const MAX_REMOTE_SEGMENTS = 2048
44
44
 
45
45
  const MAX_RANGES = 64
46
46
 
47
+ const NOT_AVAILABLE = 1
48
+ const INVALID_REQUEST = 2
49
+ const MAX_INVALID_REQUESTS = 64
50
+ const MAX_BACKOFFS = MAX_INVALID_REQUESTS / 2
51
+
47
52
  const PRIORITY = {
48
53
  NORMAL: 0,
49
54
  HIGH: 1,
@@ -407,7 +412,8 @@ class Peer {
407
412
  wireExtension: { tx: 0, rx: 0 },
408
413
  hotswaps: 0,
409
414
  invalidData: 0,
410
- invalidRequests: 0
415
+ invalidRequests: 0,
416
+ backoffs: 0
411
417
  }
412
418
 
413
419
  this.receiverQueue = new ReceiverQueue()
@@ -730,9 +736,13 @@ class Peer {
730
736
  return new ProofRequest(msg, proof, block, manifest)
731
737
  } catch (err) {
732
738
  batch.destroy()
733
- this.stats.invalidRequests++
734
- this.replicator.stats.invalidRequests++
735
- throw err
739
+
740
+ this.replicator._oninvalidrequest(err, msg, this)
741
+
742
+ if (this.stats.invalidRequests >= MAX_INVALID_REQUESTS) throw err
743
+
744
+ await backoff(this.stats.invalidRequests)
745
+ return null
736
746
  }
737
747
  }
738
748
 
@@ -791,6 +801,11 @@ class Peer {
791
801
  ? await this._getProof(batch, msg)
792
802
  : new ProofRequest(msg, null, null, null)
793
803
 
804
+ if (req === null) {
805
+ this.wireNoData.send({ request: msg.id, reason: INVALID_REQUEST })
806
+ return
807
+ }
808
+
794
809
  batch.tryFlush()
795
810
 
796
811
  await this._fulfillRequest(req)
@@ -819,7 +834,7 @@ class Peer {
819
834
  return
820
835
  }
821
836
 
822
- this.wireNoData.send({ request: req.msg.id })
837
+ this.wireNoData.send({ request: req.msg.id, reason: NOT_AVAILABLE })
823
838
  return
824
839
  }
825
840
 
@@ -904,7 +919,7 @@ class Peer {
904
919
  if (isBlockRequest(req)) this.replicator._unmarkInflight(req.block.index)
905
920
 
906
921
  this.paused = true
907
- this.replicator._oninvalid(err, req, data, this)
922
+ this.replicator._oninvaliddata(err, req, data, this)
908
923
  return
909
924
  }
910
925
 
@@ -913,7 +928,7 @@ class Peer {
913
928
 
914
929
  try {
915
930
  if (!matchingRequest(req, data) || !(await this.core.verify(data, this))) {
916
- this.replicator._onnodata(this, req)
931
+ this.replicator._onnodata(this, req, 0)
917
932
  return
918
933
  }
919
934
  } catch (err) {
@@ -935,8 +950,8 @@ class Peer {
935
950
  }
936
951
 
937
952
  this.paused = true
938
- this.replicator._onnodata(this, req)
939
- this.replicator._oninvalid(err, req, data, this)
953
+ this.replicator._onnodata(this, req, 0)
954
+ this.replicator._oninvaliddata(err, req, data, this)
940
955
  return
941
956
  } finally {
942
957
  if (isBlockRequest(req)) this.replicator._markProcessed(req.block.index)
@@ -950,13 +965,12 @@ class Peer {
950
965
  }
951
966
  }
952
967
 
953
- onnodata ({ request }) {
968
+ onnodata ({ request, reason }) {
954
969
  const req = request > 0 ? this.replicator._inflight.get(request) : null
955
-
956
970
  if (req === null || req.peer !== this) return
957
971
 
958
972
  this._onrequestroundtrip(req)
959
- this.replicator._onnodata(this, req)
973
+ this.replicator._onnodata(this, req, reason)
960
974
  }
961
975
 
962
976
  _onrequestroundtrip (req) {
@@ -1505,7 +1519,8 @@ module.exports = class Replicator {
1505
1519
  wireExtension: { tx: 0, rx: 0 },
1506
1520
  hotswaps: 0,
1507
1521
  invalidData: 0,
1508
- invalidRequests: 0
1522
+ invalidRequests: 0,
1523
+ backoffs: 0
1509
1524
  }
1510
1525
 
1511
1526
  this._attached = new Set()
@@ -2086,7 +2101,16 @@ module.exports = class Replicator {
2086
2101
  }
2087
2102
  }
2088
2103
 
2089
- _onnodata (peer, req) {
2104
+ _onnodata (peer, req, reason) {
2105
+ if (reason === INVALID_REQUEST) {
2106
+ peer.stats.backoffs++
2107
+ this.stats.backoffs++
2108
+
2109
+ if (peer.stats.backoffs >= MAX_BACKOFFS) {
2110
+ peer.paused = true
2111
+ }
2112
+ }
2113
+
2090
2114
  this._clearRequest(peer, req)
2091
2115
  this.updateAll()
2092
2116
  }
@@ -2547,7 +2571,7 @@ module.exports = class Replicator {
2547
2571
  }
2548
2572
  }
2549
2573
 
2550
- _oninvalid (err, req, res, from) {
2574
+ _oninvaliddata (err, req, res, from) {
2551
2575
  const sessions = this.core.monitors
2552
2576
 
2553
2577
  this.stats.invalidData++
@@ -2556,6 +2580,16 @@ module.exports = class Replicator {
2556
2580
  sessions[i].emit('verification-error', err, req, res, from)
2557
2581
  }
2558
2582
  }
2583
+
2584
+ _oninvalidrequest (err, req, from) {
2585
+ const sessions = this.core.monitors
2586
+
2587
+ from.stats.invalidRequests++
2588
+ this.stats.invalidRequests++
2589
+ for (let i = 0; i < sessions.length; i++) {
2590
+ sessions[i].emit('invalid-request', err, req, from)
2591
+ }
2592
+ }
2559
2593
  }
2560
2594
 
2561
2595
  function matchingRequest (req, data) {
@@ -2707,3 +2741,8 @@ function incrementRx (stats1, stats2) {
2707
2741
  }
2708
2742
 
2709
2743
  function noop () {}
2744
+
2745
+ function backoff (times) {
2746
+ const sleep = times < 2 ? 200 : times < 5 ? 500 : times < 40 ? 1000 : 5000
2747
+ return new Promise(resolve => setTimeout(resolve, sleep))
2748
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore",
3
- "version": "11.12.1",
3
+ "version": "11.13.0",
4
4
  "description": "Hypercore is a secure, distributed append-only log",
5
5
  "main": "index.js",
6
6
  "scripts": {