hypercore 11.0.43 → 11.0.45

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/index.js CHANGED
@@ -370,6 +370,9 @@ class Hypercore extends EventEmitter {
370
370
  if (this.state && checkout !== -1) {
371
371
  if (!opts.name && !opts.atom) throw ASSERTION('Checkouts must be named or atomized')
372
372
  if (checkout > this.state.length) throw ASSERTION('Invalid checkout ' + checkout + ' for ' + opts.name + ', length is ' + this.state.length)
373
+ if (this.state.prologue && checkout < this.state.prologue.length) {
374
+ throw ASSERTION('Invalid checkout ' + checkout + ' for ' + opts.name + ', prologue length is ' + this.state.prologue.length)
375
+ }
373
376
  if (checkout < this.state.length) await this.state.truncate(checkout, this.fork)
374
377
  }
375
378
 
package/lib/core.js CHANGED
@@ -171,6 +171,7 @@ module.exports = class Core {
171
171
  key: opts.key || (compat ? manifest.signers[0].publicKey : Verifier.manifestHash(manifest)),
172
172
  manifest,
173
173
  keyPair: keyPair ? { publicKey: keyPair.publicKey, secretKey: keyPair.secretKey || null } : null,
174
+ frozen: false,
174
175
  userData: [],
175
176
  tree: {
176
177
  fork: 0,
@@ -190,6 +191,7 @@ module.exports = class Core {
190
191
  key: header.key,
191
192
  manifest,
192
193
  keyPair,
194
+ frozen: false,
193
195
  discoveryKey,
194
196
  userData: opts.userData || [],
195
197
  alias: opts.alias || null
@@ -494,6 +496,11 @@ module.exports = class Core {
494
496
  return false
495
497
  }
496
498
 
499
+ // sanity check -> no manifest, no way to verify
500
+ if (!this.header.manifest) {
501
+ return false
502
+ }
503
+
497
504
  const batch = MerkleTree.verifyFullyRemote(this.state, proof)
498
505
 
499
506
  try {
@@ -502,24 +509,57 @@ module.exports = class Core {
502
509
  return true
503
510
  }
504
511
 
512
+ const roots = await MerkleTree.getRootsFromStorage(this.storage, proof.upgrade.length)
513
+ const remoteTreeHash = crypto.tree(proof.upgrade.nodes)
514
+ const localTreeHash = crypto.tree(roots)
515
+
516
+ try {
517
+ const rx = this.state.storage.read()
518
+ const treeProofPromise = MerkleTree.proof(this.state, rx, {
519
+ block: null,
520
+ hash: null,
521
+ seek: null,
522
+ upgrade: {
523
+ start: 0,
524
+ length: proof.upgrade.length
525
+ }
526
+ })
527
+
528
+ rx.tryFlush()
529
+
530
+ const treeProof = await treeProofPromise
531
+
532
+ const verifyBatch = MerkleTree.verifyFullyRemote(this.state, await treeProof.settle())
533
+ this._verifyBatchUpgrade(verifyBatch, this.header.manifest)
534
+ } catch {
535
+ return true
536
+ }
537
+
538
+ // both proofs are valid, now check if they forked
539
+ if (b4a.equals(localTreeHash, remoteTreeHash)) return false
540
+
505
541
  await this.state.mutex.lock()
506
542
 
507
543
  try {
508
544
  const tx = this.state.createWriteBatch()
509
- if (this.header.manifest === null && proof.manifest) {
510
- this._setManifest(tx, proof.manifest, null)
511
- }
545
+
546
+ this.header.frozen = true
547
+
548
+ tx.setAuth({
549
+ key: this.header.key,
550
+ discoveryKey: this.discoveryKey,
551
+ manifest: this.header.manifest,
552
+ keyPair: this.header.keyPair,
553
+ frozen: true
554
+ })
512
555
 
513
556
  await this.state.flush()
514
557
  } finally {
515
558
  this.state.mutex.unlock()
516
559
  }
517
560
 
518
- const remoteTreeHash = crypto.tree(proof.upgrade.nodes)
519
- const localTreeHash = crypto.tree(await MerkleTree.getRootsFromStorage(this.storage, proof.upgrade.length))
520
-
521
- if (b4a.equals(localTreeHash, remoteTreeHash)) return false
522
-
561
+ // tmp log so we can see these
562
+ console.log('[hypercore] conflict detected in ' + this.id + ' (writable=' + !!this.header.keyPair + ',quorum=' + this.header.manifest.quorum + ')')
523
563
  await this._onconflict(proof)
524
564
  return true
525
565
  }
@@ -148,7 +148,7 @@ class MerkleTreeBatch {
148
148
  return caps.treeSignableCompat(this.hash(), this.length, this.fork, noHeader)
149
149
  }
150
150
 
151
- get (index, error) {
151
+ get (index) {
152
152
  if (index >= this.length * 2) {
153
153
  return null
154
154
  }
@@ -157,7 +157,7 @@ class MerkleTreeBatch {
157
157
  if (n.index === index) return n
158
158
  }
159
159
 
160
- return MerkleTree.get(this.session, index, error)
160
+ return getTreeNodeFromStorage(this.session.storage, index)
161
161
  }
162
162
 
163
163
  // deprecated, use sssion proof instead
@@ -267,9 +267,9 @@ class MerkleTreeBatch {
267
267
  }
268
268
 
269
269
  byteRange (index) {
270
- const readBatch = this.storage.read()
271
- const range = getByteRange(this, index, readBatch)
272
- readBatch.tryFlush()
270
+ const rx = this.storage.read()
271
+ const range = getByteRange(this, index, rx)
272
+ rx.tryFlush()
273
273
 
274
274
  return range
275
275
  }
@@ -277,9 +277,9 @@ class MerkleTreeBatch {
277
277
  byteOffset (index) {
278
278
  if (index === 2 * this.length) return this.byteLength
279
279
 
280
- const readBatch = this.storage.read()
281
- const offset = getByteOffset(this, index, readBatch)
282
- readBatch.tryFlush()
280
+ const rx = this.storage.read()
281
+ const offset = getByteOffset(this, index, rx)
282
+ rx.tryFlush()
283
283
 
284
284
  return offset
285
285
  }
@@ -347,7 +347,7 @@ class ReorgBatch extends MerkleTreeBatch {
347
347
  const left = n.get(ite.leftChild())
348
348
  if (!left) break
349
349
 
350
- const existing = await MerkleTree.get(this.session, left.index, false)
350
+ const existing = await getTreeNodeFromStorage(this.session.storage, left.index)
351
351
  if (!existing || !b4a.equals(existing.hash, left.hash)) {
352
352
  diff = left
353
353
  } else {
@@ -413,7 +413,7 @@ class ByteSeeker {
413
413
  const ite = flat.iterator(node.index)
414
414
 
415
415
  while ((ite.index & 1) !== 0) {
416
- const l = await MerkleTree.get(this.session, ite.leftChild(), false)
416
+ const l = await getTreeNodeFromStorage(this.session.storage, ite.leftChild())
417
417
 
418
418
  if (l) {
419
419
  const size = getUnpaddedSize(l, this.padding, ite)
@@ -530,51 +530,27 @@ class MerkleTree {
530
530
  static getRootsFromStorage (storage, length) {
531
531
  const indexes = flat.fullRoots(2 * length)
532
532
  const roots = new Array(indexes.length)
533
- const readBatch = storage.read()
533
+ const rx = storage.read()
534
534
 
535
535
  for (let i = 0; i < indexes.length; i++) {
536
- roots[i] = readBatch.getTreeNode(indexes[i], true)
536
+ roots[i] = getTreeNodeOrError(rx, indexes[i])
537
537
  }
538
538
 
539
- readBatch.tryFlush()
539
+ rx.tryFlush()
540
540
 
541
541
  return Promise.all(roots)
542
542
  }
543
543
 
544
- static getNeededNodes (session, length, start, end) {
545
- const nodes = new Map()
546
- const head = length * 2
547
-
548
- for (let i = start; i < end; i++) {
549
- const ite = flat.iterator(i * 2)
550
-
551
- while (true) {
552
- if (nodes.has(ite.index)) break
553
- nodes.set(ite.index, this.get(session, ite.index, true))
554
-
555
- const sibling = ite.sibling()
556
-
557
- ite.parent()
558
- if (ite.contains(head)) break
559
-
560
- if (nodes.has(sibling)) break
561
- nodes.set(sibling, this.get(session, sibling, true))
562
- }
563
- }
564
-
565
- return Promise.all([...nodes.values()])
566
- }
567
-
568
544
  static async upgradeable (session, length) {
569
545
  const indexes = flat.fullRoots(2 * length)
570
546
  const roots = new Array(indexes.length)
571
- const readBatch = session.storage.read()
547
+ const rx = session.storage.read()
572
548
 
573
549
  for (let i = 0; i < indexes.length; i++) {
574
- roots[i] = readBatch.getTreeNode(indexes[i], false)
550
+ roots[i] = rx.getTreeNode(indexes[i])
575
551
  }
576
552
 
577
- readBatch.tryFlush()
553
+ rx.tryFlush()
578
554
 
579
555
  for (const node of await Promise.all(roots)) {
580
556
  if (node === null) return false
@@ -587,10 +563,8 @@ class MerkleTree {
587
563
  return new ByteSeeker(session, bytes, padding)
588
564
  }
589
565
 
590
- static get (session, index, error = true, readBatch = null) {
591
- if (readBatch) return readBatch.getTreeNode(index, error)
592
-
593
- return getTreeNode(session.storage, index, error)
566
+ static get (session, index) {
567
+ return getTreeNodeFromStorage(session.storage, index)
594
568
  }
595
569
 
596
570
  static async truncate (session, length, batch, fork = batch.fork) {
@@ -602,7 +576,7 @@ class MerkleTree {
602
576
  if (i < batch.roots.length && batch.roots[i].index === root) continue
603
577
 
604
578
  while (batch.roots.length > i) batch.roots.pop()
605
- batch.roots.push(unslabNode(await this.get(session, root)))
579
+ batch.roots.push(unslabNode(await getTreeNodeFromStorageOrError(session.storage, root)))
606
580
  }
607
581
 
608
582
  while (batch.roots.length > fullRoots.length) {
@@ -630,7 +604,7 @@ class MerkleTree {
630
604
  }
631
605
 
632
606
  for (const root of batch.roots) {
633
- const existing = await MerkleTree.get(session, root.index, false)
607
+ const existing = await getTreeNodeFromStorage(session.storage, root.index)
634
608
  if (existing && b4a.equals(existing.hash, root.hash)) continue
635
609
  batch._updateDiffRoot(root)
636
610
  break
@@ -679,7 +653,7 @@ class MerkleTree {
679
653
  }
680
654
 
681
655
  if (unverified) {
682
- const verified = await MerkleTree.get(session, unverified.index)
656
+ const verified = await getTreeNodeFromStorageOrError(session.storage, unverified.index)
683
657
  if (!b4a.equals(verified.hash, unverified.hash)) {
684
658
  throw INVALID_CHECKSUM('Invalid checksum at node ' + unverified.index)
685
659
  }
@@ -730,16 +704,16 @@ module.exports = {
730
704
  MerkleTree
731
705
  }
732
706
 
733
- async function getNodeSize (index, readBatch) {
734
- return (await readBatch.getTreeNode(index, true)).size
707
+ async function getNodeSize (index, rx) {
708
+ return (await getTreeNodeOrError(rx, index)).size
735
709
  }
736
710
 
737
- async function getByteOffsetSession (session, index, readBatch) {
711
+ async function getByteOffsetSession (session, index, rx) {
738
712
  if (index === 2 * session.length) return session.byteLength
739
713
 
740
- const treeNodes = readBatch === null
714
+ const treeNodes = rx === null
741
715
  ? await getByteOffsetBatchFlush(session.roots, index, session.storage.read())
742
- : await getByteOffsetBatch(session.roots, index, readBatch)
716
+ : await getByteOffsetBatch(session.roots, index, rx)
743
717
 
744
718
  let offset = 0
745
719
  for (const node of treeNodes) offset += node.size
@@ -747,10 +721,10 @@ async function getByteOffsetSession (session, index, readBatch) {
747
721
  return offset
748
722
  }
749
723
 
750
- async function getByteOffset (tree, index, readBatch) {
724
+ async function getByteOffset (tree, index, rx) {
751
725
  if (index === 2 * tree.length) return tree.byteLength
752
726
 
753
- const treeNodes = await getByteOffsetBatch(tree.roots, index, readBatch)
727
+ const treeNodes = await getByteOffsetBatch(tree.roots, index, rx)
754
728
 
755
729
  let offset = 0
756
730
  for (const node of treeNodes) offset += node.size
@@ -758,13 +732,13 @@ async function getByteOffset (tree, index, readBatch) {
758
732
  return offset
759
733
  }
760
734
 
761
- function getByteOffsetBatchFlush (roots, index, readBatch) {
762
- const treeNodes = getByteOffsetBatch(roots, index, readBatch)
763
- readBatch.tryFlush()
735
+ function getByteOffsetBatchFlush (roots, index, rx) {
736
+ const treeNodes = getByteOffsetBatch(roots, index, rx)
737
+ rx.tryFlush()
764
738
  return treeNodes
765
739
  }
766
740
 
767
- function getByteOffsetBatch (roots, index, readBatch) {
741
+ function getByteOffsetBatch (roots, index, rx) {
768
742
  if ((index & 1) === 1) index = flat.leftSpan(index)
769
743
 
770
744
  let head = 0
@@ -785,7 +759,7 @@ function getByteOffsetBatch (roots, index, readBatch) {
785
759
  if (index < ite.index) {
786
760
  ite.leftChild()
787
761
  } else {
788
- promises.push(readBatch.getTreeNode(ite.leftChild(), true))
762
+ promises.push(getTreeNodeOrError(rx, ite.leftChild()))
789
763
  ite.sibling()
790
764
  }
791
765
  }
@@ -796,14 +770,14 @@ function getByteOffsetBatch (roots, index, readBatch) {
796
770
  throw ASSERTION('Failed to find offset')
797
771
  }
798
772
 
799
- function getByteRange (tree, index, readBatch) {
773
+ function getByteRange (tree, index, rx) {
800
774
  const head = 2 * tree.length
801
775
  if (((index & 1) === 0 ? index : flat.rightSpan(index)) >= head) {
802
776
  throw BAD_ARGUMENT('Index is out of bounds')
803
777
  }
804
778
 
805
- const offset = getByteOffset(tree, index, readBatch)
806
- const size = getNodeSize(index, readBatch)
779
+ const offset = getByteOffset(tree, index, rx)
780
+ const size = getNodeSize(index, rx)
807
781
 
808
782
  return Promise.all([offset, size])
809
783
  }
@@ -935,8 +909,7 @@ async function seekFromHead (session, head, bytes, padding) {
935
909
 
936
910
  for (let i = 0; i < roots.length; i++) {
937
911
  const root = roots[i]
938
- const node = await MerkleTree.get(session, root, false)
939
- if (node === null) throw new Error('Tree node missing')
912
+ const node = await getTreeNodeFromStorage(session.storage, root)
940
913
  const size = getUnpaddedSize(node, padding, null)
941
914
 
942
915
  if (bytes === size) return root
@@ -959,7 +932,7 @@ async function seekTrustedTree (session, root, bytes, padding) {
959
932
  const ite = flat.iterator(root)
960
933
 
961
934
  while ((ite.index & 1) !== 0) {
962
- const l = await MerkleTree.get(session, ite.leftChild(), false)
935
+ const l = await getTreeNodeFromStorage(session.storage, ite.leftChild())
963
936
 
964
937
  if (l) {
965
938
  const size = getUnpaddedSize(l, padding, ite)
@@ -986,8 +959,7 @@ async function seekUntrustedTree (session, root, bytes, padding) {
986
959
 
987
960
  bytes -= offset
988
961
 
989
- const node = await MerkleTree.get(session, root, false)
990
- if (node === null) throw new Error('Tree node missing')
962
+ const node = await getTreeNodeFromStorageOrError(session.storage, root)
991
963
 
992
964
  if (getUnpaddedSize(node, padding, null) <= bytes) throw INVALID_OPERATION('Invalid seek')
993
965
 
@@ -998,41 +970,41 @@ async function seekUntrustedTree (session, root, bytes, padding) {
998
970
  // Note, that all these methods are sync as we can statically infer which nodes
999
971
  // are needed for the remote to verify given they arguments they passed us
1000
972
 
1001
- function seekProof (session, batch, seekRoot, root, p) {
973
+ function seekProof (session, rx, seekRoot, root, p) {
1002
974
  const ite = flat.iterator(seekRoot)
1003
975
 
1004
976
  p.seek = []
1005
- p.seek.push(MerkleTree.get(session, ite.index, true, batch))
977
+ p.seek.push(getTreeNodeOrError(rx, ite.index))
1006
978
 
1007
979
  while (ite.index !== root) {
1008
980
  ite.sibling()
1009
- p.seek.push(MerkleTree.get(session, ite.index, true, batch))
981
+ p.seek.push(getTreeNodeOrError(rx, ite.index))
1010
982
  ite.parent()
1011
983
  }
1012
984
  }
1013
985
 
1014
- function blockAndSeekProof (session, batch, node, seek, seekRoot, root, p) {
1015
- if (!node) return seekProof(session, batch, seekRoot, root, p)
986
+ function blockAndSeekProof (session, rx, node, seek, seekRoot, root, p) {
987
+ if (!node) return seekProof(session, rx, seekRoot, root, p)
1016
988
 
1017
989
  const ite = flat.iterator(node.index)
1018
990
 
1019
991
  p.node = []
1020
- if (!node.value) p.node.push(MerkleTree.get(session, ite.index, true, batch))
992
+ if (!node.value) p.node.push(getTreeNodeOrError(rx, ite.index))
1021
993
 
1022
994
  while (ite.index !== root) {
1023
995
  ite.sibling()
1024
996
 
1025
997
  if (seek && ite.contains(seekRoot) && ite.index !== seekRoot) {
1026
- seekProof(session, batch, seekRoot, ite.index, p)
998
+ seekProof(session, rx, seekRoot, ite.index, p)
1027
999
  } else {
1028
- p.node.push(MerkleTree.get(session, ite.index, true, batch))
1000
+ p.node.push(getTreeNodeOrError(rx, ite.index))
1029
1001
  }
1030
1002
 
1031
1003
  ite.parent()
1032
1004
  }
1033
1005
  }
1034
1006
 
1035
- function upgradeProof (session, batch, node, seek, from, to, subTree, p) {
1007
+ function upgradeProof (session, rx, node, seek, from, to, subTree, p) {
1036
1008
  if (from === 0) p.upgrade = []
1037
1009
 
1038
1010
  for (const ite = flat.iterator(0); ite.fullRoot(to); ite.nextTree()) {
@@ -1052,9 +1024,9 @@ function upgradeProof (session, batch, node, seek, from, to, subTree, p) {
1052
1024
  ite.sibling()
1053
1025
  if (ite.index > target) {
1054
1026
  if (p.node === null && p.seek === null && ite.contains(subTree)) {
1055
- blockAndSeekProof(session, batch, node, seek, subTree, ite.index, p)
1027
+ blockAndSeekProof(session, rx, node, seek, subTree, ite.index, p)
1056
1028
  } else {
1057
- p.upgrade.push(batch.getTreeNode(ite.index, true))
1029
+ p.upgrade.push(getTreeNodeOrError(rx, ite.index))
1058
1030
  }
1059
1031
  }
1060
1032
  ite.parent()
@@ -1070,16 +1042,16 @@ function upgradeProof (session, batch, node, seek, from, to, subTree, p) {
1070
1042
  // if the subtree included is a child of this tree, include that one
1071
1043
  // instead of a dup node
1072
1044
  if (p.node === null && p.seek === null && ite.contains(subTree)) {
1073
- blockAndSeekProof(session, batch, node, seek, subTree, ite.index, p)
1045
+ blockAndSeekProof(session, rx, node, seek, subTree, ite.index, p)
1074
1046
  continue
1075
1047
  }
1076
1048
 
1077
1049
  // add root (can be optimised since the root might be in tree.roots)
1078
- p.upgrade.push(MerkleTree.get(session, ite.index, true, batch))
1050
+ p.upgrade.push(getTreeNodeOrError(rx, ite.index))
1079
1051
  }
1080
1052
  }
1081
1053
 
1082
- function additionalUpgradeProof (session, batch, from, to, p) {
1054
+ function additionalUpgradeProof (session, rx, from, to, p) {
1083
1055
  if (from === 0) p.additionalUpgrade = []
1084
1056
 
1085
1057
  for (const ite = flat.iterator(0); ite.fullRoot(to); ite.nextTree()) {
@@ -1098,7 +1070,7 @@ function additionalUpgradeProof (session, batch, from, to, p) {
1098
1070
  while (ite.index !== root) {
1099
1071
  ite.sibling()
1100
1072
  if (ite.index > target) {
1101
- p.additionalUpgrade.push(MerkleTree.get(session, ite.index, true, batch))
1073
+ p.additionalUpgrade.push(getTreeNodeOrError(rx, ite.index))
1102
1074
  }
1103
1075
  ite.parent()
1104
1076
  }
@@ -1111,7 +1083,7 @@ function additionalUpgradeProof (session, batch, from, to, p) {
1111
1083
  }
1112
1084
 
1113
1085
  // add root (can be optimised since the root is in tree.roots)
1114
- p.additionalUpgrade.push(MerkleTree.get(session, ite.index, true, batch))
1086
+ p.additionalUpgrade.push(getTreeNodeOrError(rx, ite.index))
1115
1087
  }
1116
1088
  }
1117
1089
 
@@ -1163,17 +1135,30 @@ function normalizeIndexed (block, hash) {
1163
1135
  return null
1164
1136
  }
1165
1137
 
1166
- function getTreeNode (storage, index, error) {
1167
- const batch = storage.read()
1168
- const node = batch.getTreeNode(index, error)
1169
- batch.tryFlush()
1138
+ async function getTreeNodeOrError (rx, index) {
1139
+ const node = await rx.getTreeNode(index)
1140
+ if (node === null) throw INVALID_OPERATION('Expected tree node ' + index + ' from storage, got (nil)')
1141
+ return node
1142
+ }
1143
+
1144
+ function getTreeNodeFromStorageOrError (storage, index) {
1145
+ const rx = storage.read()
1146
+ const p = getTreeNodeOrError(rx, index)
1147
+ rx.tryFlush()
1148
+ return p
1149
+ }
1150
+
1151
+ function getTreeNodeFromStorage (storage, index) {
1152
+ const rx = storage.read()
1153
+ const node = rx.getTreeNode(index)
1154
+ rx.tryFlush()
1170
1155
  return node
1171
1156
  }
1172
1157
 
1173
1158
  function hasTreeNode (storage, index) {
1174
- const batch = storage.read()
1175
- const has = batch.hasTreeNode(index)
1176
- batch.tryFlush()
1159
+ const rx = storage.read()
1160
+ const has = rx.hasTreeNode(index)
1161
+ rx.tryFlush()
1177
1162
  return has
1178
1163
  }
1179
1164
 
@@ -1197,7 +1182,7 @@ async function settleProof (p) {
1197
1182
  }
1198
1183
 
1199
1184
  // tree can be either the merkle tree or a merkle tree batch
1200
- async function generateProof (session, readBatch, block, hash, seek, upgrade) {
1185
+ async function generateProof (session, rx, block, hash, seek, upgrade) {
1201
1186
  // Important that this does not throw inbetween making the promise arrays
1202
1187
  // and finalise being called, otherwise there will be lingering promises in the background
1203
1188
 
@@ -1228,14 +1213,14 @@ async function generateProof (session, readBatch, block, hash, seek, upgrade) {
1228
1213
  if (node !== null && (!upgrade || node.lastIndex < upgrade.start)) {
1229
1214
  subTree = nodesToRoot(node.index, node.nodes, to)
1230
1215
  const seekRoot = seek ? await seekUntrustedTree(session, subTree, seek.bytes, seek.padding) : head
1231
- blockAndSeekProof(session, readBatch, node, seek, seekRoot, subTree, p.pending)
1216
+ blockAndSeekProof(session, rx, node, seek, seekRoot, subTree, p.pending)
1232
1217
  } else if ((node || seek) && upgrade) {
1233
1218
  subTree = seek ? await seekFromHead(session, to, seek.bytes, seek.padding) : node.index
1234
1219
  }
1235
1220
 
1236
1221
  if (upgrade) {
1237
- upgradeProof(session, readBatch, node, seek, from, to, subTree, p.pending)
1238
- if (head > to) additionalUpgradeProof(session, readBatch, to, head, p.pending)
1222
+ upgradeProof(session, rx, node, seek, from, to, subTree, p.pending)
1223
+ if (head > to) additionalUpgradeProof(session, rx, to, head, p.pending)
1239
1224
  }
1240
1225
 
1241
1226
  return p
package/lib/replicator.js CHANGED
@@ -475,6 +475,8 @@ class Peer {
475
475
  }
476
476
 
477
477
  broadcastRange (start, length, drop) {
478
+ if (!this.isActive()) return
479
+
478
480
  if (drop) this._unclearLocalRange(start, length)
479
481
  else this._clearLocalRange(start, length)
480
482
 
@@ -779,6 +781,10 @@ class Peer {
779
781
  // sync from now on, so safe to delete from the map
780
782
  this.remoteRequests.delete(req.msg.id)
781
783
 
784
+ if (!this.isActive() && proof.block !== null) {
785
+ return
786
+ }
787
+
782
788
  if (proof === null) {
783
789
  if (req.msg.manifest && this.core.header.manifest) {
784
790
  const manifest = this.core.header.manifest
@@ -1389,7 +1395,7 @@ class Peer {
1389
1395
  }
1390
1396
 
1391
1397
  isActive () {
1392
- if (this.paused || this.removed) return false
1398
+ if (this.paused || this.removed || this.core.header.frozen) return false
1393
1399
  return true
1394
1400
  }
1395
1401
 
@@ -2120,6 +2126,8 @@ module.exports = class Replicator {
2120
2126
  }
2121
2127
 
2122
2128
  _onwant (peer, start, length) {
2129
+ if (!peer.isActive()) return
2130
+
2123
2131
  const contig = Math.min(this.core.state.length, this.core.header.hints.contiguousLength)
2124
2132
 
2125
2133
  if (start + length < contig || (this.core.state.length === contig)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore",
3
- "version": "11.0.43",
3
+ "version": "11.0.45",
4
4
  "description": "Hypercore is a secure, distributed append-only log",
5
5
  "main": "index.js",
6
6
  "scripts": {