hypercore 10.0.0-alpha.35 → 10.0.0-alpha.38
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 +93 -26
- package/lib/core.js +7 -4
- package/lib/errors.js +42 -0
- package/lib/merkle-tree.js +2 -4
- package/lib/replicator.js +103 -121
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -15,6 +15,7 @@ const Replicator = require('./lib/replicator')
|
|
|
15
15
|
const Core = require('./lib/core')
|
|
16
16
|
const BlockEncryption = require('./lib/block-encryption')
|
|
17
17
|
const { ReadStream, WriteStream } = require('./lib/streams')
|
|
18
|
+
const { BAD_ARGUMENT, SESSION_CLOSED, SESSION_NOT_WRITABLE, SNAPSHOT_NOT_AVAILABLE } = require('./lib/errors')
|
|
18
19
|
|
|
19
20
|
const promises = Symbol.for('hypercore.promises')
|
|
20
21
|
const inspect = Symbol.for('nodejs.util.inspect.custom')
|
|
@@ -39,7 +40,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
39
40
|
if (!opts) opts = {}
|
|
40
41
|
|
|
41
42
|
if (!opts.crypto && key && key.byteLength !== 32) {
|
|
42
|
-
throw
|
|
43
|
+
throw BAD_ARGUMENT('Hypercore key should be 32 bytes')
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
if (!storage) storage = opts.storage
|
|
@@ -64,6 +65,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
64
65
|
this.writable = false
|
|
65
66
|
this.opened = false
|
|
66
67
|
this.closed = false
|
|
68
|
+
this.snapshotted = !!opts.snapshot
|
|
67
69
|
this.sessions = opts._sessions || [this]
|
|
68
70
|
this.auth = opts.auth || null
|
|
69
71
|
this.autoClose = !!opts.autoClose
|
|
@@ -73,7 +75,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
73
75
|
this.opening.catch(noop)
|
|
74
76
|
|
|
75
77
|
this._preappend = preappend.bind(this)
|
|
76
|
-
this._snapshot =
|
|
78
|
+
this._snapshot = null
|
|
77
79
|
this._findingPeers = 0
|
|
78
80
|
}
|
|
79
81
|
|
|
@@ -83,15 +85,40 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
83
85
|
while (indent.length < opts.indentationLvl) indent += ' '
|
|
84
86
|
}
|
|
85
87
|
|
|
88
|
+
let peers = ''
|
|
89
|
+
const min = Math.min(this.peers.length, 5)
|
|
90
|
+
|
|
91
|
+
for (let i = 0; i < min; i++) {
|
|
92
|
+
const peer = this.peers[i]
|
|
93
|
+
|
|
94
|
+
peers += indent + ' Peer(\n'
|
|
95
|
+
peers += indent + ' remotePublicKey: ' + opts.stylize(toHex(peer.remotePublicKey), 'string') + '\n'
|
|
96
|
+
peers += indent + ' remoteLength: ' + opts.stylize(peer.remoteLength, 'number') + '\n'
|
|
97
|
+
peers += indent + ' remoteFork: ' + opts.stylize(peer.remoteFork, 'number') + '\n'
|
|
98
|
+
peers += indent + ' remoteCanUpgrade: ' + opts.stylize(peer.remoteCanUpgrade, 'boolean') + '\n'
|
|
99
|
+
peers += indent + ' )' + '\n'
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (this.peers.length > 5) {
|
|
103
|
+
peers += indent + ' ... and ' + (this.peers.length - 5) + ' more\n'
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (peers) peers = '[\n' + peers + indent + ' ]'
|
|
107
|
+
else peers = '[ ' + opts.stylize(0, 'number') + ' ]'
|
|
108
|
+
|
|
86
109
|
return this.constructor.name + '(\n' +
|
|
87
|
-
indent + ' key: ' + opts.stylize(
|
|
110
|
+
indent + ' key: ' + opts.stylize(toHex(this.key), 'string') + '\n' +
|
|
88
111
|
indent + ' discoveryKey: ' + opts.stylize(toHex(this.discoveryKey), 'string') + '\n' +
|
|
89
112
|
indent + ' opened: ' + opts.stylize(this.opened, 'boolean') + '\n' +
|
|
113
|
+
indent + ' closed: ' + opts.stylize(this.closed, 'boolean') + '\n' +
|
|
114
|
+
indent + ' snapshotted: ' + opts.stylize(this.snapshotted, 'boolean') + '\n' +
|
|
90
115
|
indent + ' writable: ' + opts.stylize(this.writable, 'boolean') + '\n' +
|
|
91
|
-
indent + ' sessions: ' + opts.stylize(this.sessions.length, 'number') + '\n' +
|
|
92
|
-
indent + ' peers: [ ' + opts.stylize(this.peers.length, 'number') + ' ]\n' +
|
|
93
116
|
indent + ' length: ' + opts.stylize(this.length, 'number') + '\n' +
|
|
94
117
|
indent + ' byteLength: ' + opts.stylize(this.byteLength, 'number') + '\n' +
|
|
118
|
+
indent + ' fork: ' + opts.stylize(this.fork, 'number') + '\n' +
|
|
119
|
+
indent + ' sessions: [ ' + opts.stylize(this.sessions.length, 'number') + ' ]\n' +
|
|
120
|
+
indent + ' activeRequests: [ ' + opts.stylize(this.activeRequests.length, 'number') + ' ]\n' +
|
|
121
|
+
indent + ' peers: ' + peers + '\n' +
|
|
95
122
|
indent + ')'
|
|
96
123
|
}
|
|
97
124
|
|
|
@@ -114,7 +141,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
114
141
|
noiseStream = new NoiseSecretStream(isInitiator, null, opts)
|
|
115
142
|
outerStream = noiseStream.rawStream
|
|
116
143
|
}
|
|
117
|
-
if (!noiseStream) throw
|
|
144
|
+
if (!noiseStream) throw BAD_ARGUMENT('Invalid stream')
|
|
118
145
|
|
|
119
146
|
if (!noiseStream.userData) {
|
|
120
147
|
const protocol = new Protomux(noiseStream)
|
|
@@ -144,15 +171,15 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
144
171
|
}
|
|
145
172
|
}
|
|
146
173
|
|
|
147
|
-
snapshot () {
|
|
148
|
-
return this.session({
|
|
174
|
+
snapshot (opts) {
|
|
175
|
+
return this.session({ ...opts, snapshot: true })
|
|
149
176
|
}
|
|
150
177
|
|
|
151
178
|
session (opts = {}) {
|
|
152
179
|
if (this.closing) {
|
|
153
180
|
// This makes the closing logic alot easier. If this turns out to be a problem
|
|
154
181
|
// in practive, open an issue and we'll try to make a solution for it.
|
|
155
|
-
throw
|
|
182
|
+
throw SESSION_CLOSED('Cannot make sessions on a closing core')
|
|
156
183
|
}
|
|
157
184
|
|
|
158
185
|
const Clz = opts.class || Hypercore
|
|
@@ -170,6 +197,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
170
197
|
|
|
171
198
|
_passCapabilities (o) {
|
|
172
199
|
if (!this.auth) this.auth = o.auth
|
|
200
|
+
|
|
173
201
|
this.crypto = o.crypto
|
|
174
202
|
this.key = o.key
|
|
175
203
|
this.core = o.core
|
|
@@ -177,6 +205,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
177
205
|
this.encryption = o.encryption
|
|
178
206
|
this.writable = !!(this.auth && this.auth.sign)
|
|
179
207
|
this.autoClose = o.autoClose
|
|
208
|
+
|
|
209
|
+
if (this.snapshotted && this.core && !this._snapshot) this._updateSnapshot()
|
|
180
210
|
}
|
|
181
211
|
|
|
182
212
|
async _openFromExisting (from, opts) {
|
|
@@ -280,6 +310,19 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
280
310
|
}
|
|
281
311
|
}
|
|
282
312
|
|
|
313
|
+
_updateSnapshot () {
|
|
314
|
+
const prev = this._snapshot
|
|
315
|
+
const next = this._snapshot = {
|
|
316
|
+
length: this.core.tree.length,
|
|
317
|
+
byteLength: this.core.tree.byteLength,
|
|
318
|
+
fork: this.core.tree.fork,
|
|
319
|
+
compatLength: this.core.tree.length
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (!prev) return true
|
|
323
|
+
return prev.length !== next.length || prev.fork !== next.fork
|
|
324
|
+
}
|
|
325
|
+
|
|
283
326
|
close () {
|
|
284
327
|
if (this.closing) return this.closing
|
|
285
328
|
this.closing = this._close()
|
|
@@ -329,6 +372,13 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
329
372
|
const noiseStream = protocolStream.noiseStream
|
|
330
373
|
const protocol = noiseStream.userData
|
|
331
374
|
|
|
375
|
+
// If the user wants to, we can make this replication run in a session
|
|
376
|
+
// that way the core wont close "under them" during replication
|
|
377
|
+
if (opts.session) {
|
|
378
|
+
const s = this.session()
|
|
379
|
+
protocolStream.on('close', () => s.close().catch(noop))
|
|
380
|
+
}
|
|
381
|
+
|
|
332
382
|
if (this.opened) {
|
|
333
383
|
this.replicator.attachTo(protocol)
|
|
334
384
|
} else {
|
|
@@ -355,9 +405,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
355
405
|
}
|
|
356
406
|
|
|
357
407
|
get fork () {
|
|
358
|
-
return this.
|
|
359
|
-
? this._snapshot.fork
|
|
360
|
-
: (this.core === null ? 0 : this.core.tree.fork)
|
|
408
|
+
return this.core === null ? 0 : this.core.tree.fork
|
|
361
409
|
}
|
|
362
410
|
|
|
363
411
|
get peers () {
|
|
@@ -386,21 +434,33 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
386
434
|
|
|
387
435
|
_oncoreupdate (status, bitfield, value, from) {
|
|
388
436
|
if (status !== 0) {
|
|
437
|
+
const truncated = (status & 0b10) !== 0
|
|
438
|
+
const appended = (status & 0b01) !== 0
|
|
439
|
+
|
|
440
|
+
if (truncated) {
|
|
441
|
+
this.replicator.ontruncate(bitfield.start)
|
|
442
|
+
}
|
|
443
|
+
|
|
389
444
|
for (let i = 0; i < this.sessions.length; i++) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
445
|
+
const s = this.sessions[i]
|
|
446
|
+
|
|
447
|
+
if (truncated) {
|
|
448
|
+
if (s.cache) s.cache.clear()
|
|
449
|
+
s.emit('truncate', bitfield.start, this.core.tree.fork)
|
|
450
|
+
// If snapshotted, make sure to update our compat so we can fail gets
|
|
451
|
+
if (s._snapshot && bitfield.start < s._snapshot.compatLength) s._snapshot.compatLength = bitfield.start
|
|
393
452
|
}
|
|
394
|
-
|
|
395
|
-
|
|
453
|
+
|
|
454
|
+
if (appended) {
|
|
455
|
+
s.emit('append')
|
|
396
456
|
}
|
|
397
457
|
}
|
|
398
458
|
|
|
399
|
-
this.replicator.
|
|
459
|
+
this.replicator.onupgrade()
|
|
400
460
|
}
|
|
401
461
|
|
|
402
462
|
if (bitfield) {
|
|
403
|
-
this.replicator.
|
|
463
|
+
this.replicator.onhave(bitfield.start, bitfield.length, bitfield.drop)
|
|
404
464
|
}
|
|
405
465
|
|
|
406
466
|
if (value) {
|
|
@@ -457,15 +517,21 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
457
517
|
|
|
458
518
|
async update (opts) {
|
|
459
519
|
if (this.opened === false) await this.opening
|
|
520
|
+
if (this.closing !== null) return false
|
|
460
521
|
|
|
461
522
|
// TODO: add an option where a writer can bootstrap it's state from the network also
|
|
462
|
-
if (this.writable
|
|
523
|
+
if (this.writable) {
|
|
524
|
+
if (!this.snapshotted) return false
|
|
525
|
+
return this._updateSnapshot()
|
|
526
|
+
}
|
|
463
527
|
|
|
464
528
|
const activeRequests = (opts && opts.activeRequests) || this.activeRequests
|
|
465
529
|
const req = this.replicator.addUpgrade(activeRequests)
|
|
466
530
|
|
|
467
|
-
|
|
468
|
-
|
|
531
|
+
if (!this.snapshotted) return req.promise
|
|
532
|
+
if (!(await req.promise)) return false
|
|
533
|
+
|
|
534
|
+
return this._updateSnapshot()
|
|
469
535
|
}
|
|
470
536
|
|
|
471
537
|
async seek (bytes, opts) {
|
|
@@ -476,7 +542,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
476
542
|
const offset = await s.update()
|
|
477
543
|
if (offset) return offset
|
|
478
544
|
|
|
479
|
-
if (this.closing !== null) throw
|
|
545
|
+
if (this.closing !== null) throw SESSION_CLOSED()
|
|
480
546
|
|
|
481
547
|
const activeRequests = (opts && opts.activeRequests) || this.activeRequests
|
|
482
548
|
const req = this.replicator.addSeek(activeRequests, s)
|
|
@@ -492,7 +558,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
492
558
|
|
|
493
559
|
async get (index, opts) {
|
|
494
560
|
if (this.opened === false) await this.opening
|
|
495
|
-
if (this.closing !== null) throw
|
|
561
|
+
if (this.closing !== null) throw SESSION_CLOSED()
|
|
562
|
+
if (this._snapshot !== null && index >= this._snapshot.compatLength) throw SNAPSHOT_NOT_AVAILABLE()
|
|
496
563
|
|
|
497
564
|
const c = this.cache && this.cache.get(index)
|
|
498
565
|
if (c) return c
|
|
@@ -567,7 +634,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
567
634
|
|
|
568
635
|
async truncate (newLength = 0, fork = -1) {
|
|
569
636
|
if (this.opened === false) await this.opening
|
|
570
|
-
if (this.writable === false) throw
|
|
637
|
+
if (this.writable === false) throw SESSION_NOT_WRITABLE()
|
|
571
638
|
|
|
572
639
|
if (fork === -1) fork = this.core.tree.fork + 1
|
|
573
640
|
await this.core.truncate(newLength, fork, this.auth)
|
|
@@ -578,7 +645,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
578
645
|
|
|
579
646
|
async append (blocks) {
|
|
580
647
|
if (this.opened === false) await this.opening
|
|
581
|
-
if (this.writable === false) throw
|
|
648
|
+
if (this.writable === false) throw SESSION_NOT_WRITABLE()
|
|
582
649
|
|
|
583
650
|
blocks = Array.isArray(blocks) ? blocks : [blocks]
|
|
584
651
|
|
package/lib/core.js
CHANGED
|
@@ -5,6 +5,7 @@ const Mutex = require('./mutex')
|
|
|
5
5
|
const MerkleTree = require('./merkle-tree')
|
|
6
6
|
const BlockStore = require('./block-store')
|
|
7
7
|
const Bitfield = require('./bitfield')
|
|
8
|
+
const { BAD_ARGUMENT, STORAGE_EMPTY, STORAGE_CONFLICT, INVALID_SIGNATURE } = require('./errors')
|
|
8
9
|
const m = require('./messages')
|
|
9
10
|
|
|
10
11
|
module.exports = class Core {
|
|
@@ -52,7 +53,9 @@ module.exports = class Core {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
static createAuth (crypto, { publicKey, secretKey }, opts = {}) {
|
|
55
|
-
if (secretKey && !crypto.validateKeyPair({ publicKey, secretKey }))
|
|
56
|
+
if (secretKey && !crypto.validateKeyPair({ publicKey, secretKey })) {
|
|
57
|
+
throw BAD_ARGUMENT('Invalid key pair')
|
|
58
|
+
}
|
|
56
59
|
|
|
57
60
|
const sign = opts.sign
|
|
58
61
|
? opts.sign
|
|
@@ -88,7 +91,7 @@ module.exports = class Core {
|
|
|
88
91
|
|
|
89
92
|
if (!header || overwrite) {
|
|
90
93
|
if (!createIfMissing) {
|
|
91
|
-
throw
|
|
94
|
+
throw STORAGE_EMPTY('No Hypercore is stored here')
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
header = {
|
|
@@ -110,7 +113,7 @@ module.exports = class Core {
|
|
|
110
113
|
}
|
|
111
114
|
|
|
112
115
|
if (opts.keyPair && !b4a.equals(header.signer.publicKey, opts.keyPair.publicKey)) {
|
|
113
|
-
throw
|
|
116
|
+
throw STORAGE_CONFLICT('Another Hypercore is stored here')
|
|
114
117
|
}
|
|
115
118
|
|
|
116
119
|
const tree = await MerkleTree.open(treeFile, { crypto, ...header.tree })
|
|
@@ -290,7 +293,7 @@ module.exports = class Core {
|
|
|
290
293
|
// TODO: move this to tree.js
|
|
291
294
|
const hash = batch.hash()
|
|
292
295
|
if (!batch.signature || !this._signed(batch, hash)) {
|
|
293
|
-
throw
|
|
296
|
+
throw INVALID_SIGNATURE('Proof contains an invalid signature')
|
|
294
297
|
}
|
|
295
298
|
|
|
296
299
|
await this._mutex.lock()
|
package/lib/errors.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module.exports = class HypercoreError extends Error {
|
|
2
|
+
constructor (msg, code) {
|
|
3
|
+
super(msg)
|
|
4
|
+
this.code = code
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
static BAD_ARGUMENT (msg) {
|
|
8
|
+
return new HypercoreError(msg, 'BAD_ARGUMENT')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static STORAGE_EMPTY (msg) {
|
|
12
|
+
return new HypercoreError(msg, 'STORAGE_EMPTY')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static STORAGE_CONFLICT (msg) {
|
|
16
|
+
return new HypercoreError(msg, 'STORAGE_CONFLICT')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static INVALID_SIGNATURE (msg) {
|
|
20
|
+
return new HypercoreError(msg, 'INVALID_SIGNATURE')
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static INVALID_CAPABILITY (msg) {
|
|
24
|
+
return new HypercoreError(msg, 'INVALID_CAPABILITY')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static SNAPSHOT_NOT_AVAILABLE (msg = 'Snapshot is not available') {
|
|
28
|
+
return new HypercoreError(msg, 'SNAPSHOT_NOT_AVAILABLE')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static REQUEST_CANCELLED (msg = 'Request was cancelled') {
|
|
32
|
+
return new HypercoreError(msg, 'REQUEST_CANCELLED')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static SESSION_NOT_WRITABLE (msg = 'Session is not writable') {
|
|
36
|
+
return new HypercoreError(msg, 'SESSION_NOT_WRITABLE')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static SESSION_CLOSED (msg = 'Session is closed') {
|
|
40
|
+
return new HypercoreError(msg, 'SESSION_CLOSED')
|
|
41
|
+
}
|
|
42
|
+
}
|
package/lib/merkle-tree.js
CHANGED
|
@@ -228,6 +228,7 @@ class ReorgBatch extends MerkleTreeBatch {
|
|
|
228
228
|
|
|
229
229
|
let diff = null
|
|
230
230
|
const ite = flat.iterator(this.diff.index)
|
|
231
|
+
const startingDiff = this.diff
|
|
231
232
|
|
|
232
233
|
while ((ite.index & 1) !== 0) {
|
|
233
234
|
const left = n.get(ite.leftChild())
|
|
@@ -243,6 +244,7 @@ class ReorgBatch extends MerkleTreeBatch {
|
|
|
243
244
|
|
|
244
245
|
if ((this.diff.index & 1) === 0) return true
|
|
245
246
|
if (diff === null) return false
|
|
247
|
+
if (startingDiff !== this.diff) return false
|
|
246
248
|
|
|
247
249
|
return this._updateDiffRoot(diff)
|
|
248
250
|
}
|
|
@@ -255,10 +257,6 @@ class ReorgBatch extends MerkleTreeBatch {
|
|
|
255
257
|
const end = Math.min(this.treeLength, spans[1] / 2 + 1)
|
|
256
258
|
const len = end - start
|
|
257
259
|
|
|
258
|
-
if (this.diff !== null && len >= this.want.end - this.want.start) {
|
|
259
|
-
return false
|
|
260
|
-
}
|
|
261
|
-
|
|
262
260
|
this.ancestors = start
|
|
263
261
|
this.diff = diff
|
|
264
262
|
|
package/lib/replicator.js
CHANGED
|
@@ -2,6 +2,7 @@ const b4a = require('b4a')
|
|
|
2
2
|
const safetyCatch = require('safety-catch')
|
|
3
3
|
const RandomIterator = require('random-array-iterator')
|
|
4
4
|
const RemoteBitfield = require('./remote-bitfield')
|
|
5
|
+
const { REQUEST_CANCELLED, INVALID_CAPABILITY, SNAPSHOT_NOT_AVAILABLE } = require('./errors')
|
|
5
6
|
const m = require('./messages')
|
|
6
7
|
const caps = require('./caps')
|
|
7
8
|
|
|
@@ -19,6 +20,7 @@ class Attachable {
|
|
|
19
20
|
session,
|
|
20
21
|
sindex: 0,
|
|
21
22
|
rindex: 0,
|
|
23
|
+
snapshot: true,
|
|
22
24
|
resolve: null,
|
|
23
25
|
reject: null,
|
|
24
26
|
promise: null
|
|
@@ -34,11 +36,11 @@ class Attachable {
|
|
|
34
36
|
return r
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
detach (r) {
|
|
39
|
+
detach (r, err = null) {
|
|
38
40
|
if (r.context !== this) return false
|
|
39
41
|
|
|
40
42
|
this._detach(r)
|
|
41
|
-
this._cancel(r)
|
|
43
|
+
this._cancel(r, err)
|
|
42
44
|
this.gc()
|
|
43
45
|
|
|
44
46
|
return true
|
|
@@ -60,8 +62,8 @@ class Attachable {
|
|
|
60
62
|
if (this.refs.length === 0) this._unref()
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
_cancel (r) {
|
|
64
|
-
r.reject(
|
|
65
|
+
_cancel (r, err) {
|
|
66
|
+
r.reject(err || REQUEST_CANCELLED())
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
_unref () {
|
|
@@ -84,10 +86,9 @@ class Attachable {
|
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
class BlockRequest extends Attachable {
|
|
87
|
-
constructor (tracker,
|
|
89
|
+
constructor (tracker, index) {
|
|
88
90
|
super()
|
|
89
91
|
|
|
90
|
-
this.fork = fork
|
|
91
92
|
this.index = index
|
|
92
93
|
this.inflight = []
|
|
93
94
|
this.queued = false
|
|
@@ -96,15 +97,14 @@ class BlockRequest extends Attachable {
|
|
|
96
97
|
|
|
97
98
|
_unref () {
|
|
98
99
|
if (this.inflight.length > 0) return
|
|
99
|
-
this.tracker.remove(this.
|
|
100
|
+
this.tracker.remove(this.index)
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
class RangeRequest extends Attachable {
|
|
104
|
-
constructor (ranges,
|
|
105
|
+
constructor (ranges, start, end, linear, blocks) {
|
|
105
106
|
super()
|
|
106
107
|
|
|
107
|
-
this.fork = fork
|
|
108
108
|
this.start = start
|
|
109
109
|
this.end = end
|
|
110
110
|
this.linear = linear
|
|
@@ -149,10 +149,9 @@ class UpgradeRequest extends Attachable {
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
class SeekRequest extends Attachable {
|
|
152
|
-
constructor (seeks,
|
|
152
|
+
constructor (seeks, seeker) {
|
|
153
153
|
super()
|
|
154
154
|
|
|
155
|
-
this.fork = fork
|
|
156
155
|
this.seeker = seeker
|
|
157
156
|
this.inflight = []
|
|
158
157
|
this.seeks = seeks
|
|
@@ -200,87 +199,40 @@ class InflightTracker {
|
|
|
200
199
|
}
|
|
201
200
|
|
|
202
201
|
class BlockTracker {
|
|
203
|
-
constructor (
|
|
204
|
-
this.
|
|
205
|
-
this._fork = core.tree.fork
|
|
206
|
-
|
|
207
|
-
this._indexed = new Map()
|
|
208
|
-
this._additional = []
|
|
202
|
+
constructor () {
|
|
203
|
+
this._map = new Map()
|
|
209
204
|
}
|
|
210
205
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
yield * this._additional
|
|
206
|
+
[Symbol.iterator] () {
|
|
207
|
+
return this._map.values()
|
|
214
208
|
}
|
|
215
209
|
|
|
216
210
|
isEmpty () {
|
|
217
|
-
return this.
|
|
211
|
+
return this._map.size === 0
|
|
218
212
|
}
|
|
219
213
|
|
|
220
|
-
has (
|
|
221
|
-
return this.
|
|
214
|
+
has (index) {
|
|
215
|
+
return this._map.has(index)
|
|
222
216
|
}
|
|
223
217
|
|
|
224
|
-
get (
|
|
225
|
-
|
|
226
|
-
for (const b of this._additional) {
|
|
227
|
-
if (b.index === index && b.fork === fork) return b
|
|
228
|
-
}
|
|
229
|
-
return null
|
|
218
|
+
get (index) {
|
|
219
|
+
return this._map.get(index) || null
|
|
230
220
|
}
|
|
231
221
|
|
|
232
|
-
add (
|
|
233
|
-
|
|
234
|
-
if (this._fork !== this._core.tree.fork) this.update(this._core.tree.fork)
|
|
235
|
-
|
|
236
|
-
let b = this.get(fork, index)
|
|
222
|
+
add (index) {
|
|
223
|
+
let b = this._map.get(index)
|
|
237
224
|
if (b) return b
|
|
238
225
|
|
|
239
|
-
b = new BlockRequest(this,
|
|
240
|
-
|
|
241
|
-
if (fork === this._fork) this._indexed.set(index, b)
|
|
242
|
-
else this._additional.push(b)
|
|
226
|
+
b = new BlockRequest(this, index)
|
|
227
|
+
this._map.set(index, b)
|
|
243
228
|
|
|
244
229
|
return b
|
|
245
230
|
}
|
|
246
231
|
|
|
247
|
-
remove (
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
return b || null
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
for (let i = 0; i < this._additional.length; i++) {
|
|
255
|
-
const b = this._additional[i]
|
|
256
|
-
if (b.index !== index || b.fork !== fork) continue
|
|
257
|
-
if (i === this._additional.length - 1) this._additional.pop()
|
|
258
|
-
else this._additional[i] = this._additional.pop()
|
|
259
|
-
return b
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return null
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
update (fork) {
|
|
266
|
-
if (this._fork === fork) return
|
|
267
|
-
|
|
268
|
-
const additional = this._additional
|
|
269
|
-
this._additional = []
|
|
270
|
-
|
|
271
|
-
for (const b of this._indexed.values()) {
|
|
272
|
-
// TODO: this is only needed cause we hot patch the fork ids below, revert that later
|
|
273
|
-
if (b.fork !== this._fork) additional.push(b)
|
|
274
|
-
else this._additional.push(b)
|
|
275
|
-
}
|
|
276
|
-
this._indexed.clear()
|
|
277
|
-
|
|
278
|
-
for (const b of additional) {
|
|
279
|
-
if (b.fork === fork) this._indexed.set(b.index, b)
|
|
280
|
-
else this._additional.push(b)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
this._fork = fork
|
|
232
|
+
remove (index) {
|
|
233
|
+
const b = this.get(index)
|
|
234
|
+
this._map.delete(index)
|
|
235
|
+
return b
|
|
284
236
|
}
|
|
285
237
|
}
|
|
286
238
|
|
|
@@ -290,6 +242,7 @@ class Peer {
|
|
|
290
242
|
this.replicator = replicator
|
|
291
243
|
this.stream = protomux.stream
|
|
292
244
|
this.protomux = protomux
|
|
245
|
+
this.remotePublicKey = this.stream.remotePublicKey
|
|
293
246
|
|
|
294
247
|
this.channel = channel
|
|
295
248
|
this.channel.userData = this
|
|
@@ -387,7 +340,7 @@ class Peer {
|
|
|
387
340
|
const expected = caps.replicate(this.stream.isInitiator === false, this.replicator.key, this.stream.handshakeHash)
|
|
388
341
|
|
|
389
342
|
if (b4a.equals(capability, expected) !== true) { // TODO: change this to a rejection instead, less leakage
|
|
390
|
-
throw
|
|
343
|
+
throw INVALID_CAPABILITY('Remote sent an invalid replication capability')
|
|
391
344
|
}
|
|
392
345
|
|
|
393
346
|
if (this.remoteOpened === true) return
|
|
@@ -425,7 +378,7 @@ class Peer {
|
|
|
425
378
|
|
|
426
379
|
async onsync ({ fork, length, remoteLength, canUpgrade, uploading, downloading }) {
|
|
427
380
|
const lengthChanged = length !== this.remoteLength
|
|
428
|
-
const sameFork =
|
|
381
|
+
const sameFork = fork === this.core.tree.fork
|
|
429
382
|
|
|
430
383
|
this.remoteSynced = true
|
|
431
384
|
this.remoteFork = fork
|
|
@@ -468,12 +421,11 @@ class Peer {
|
|
|
468
421
|
}
|
|
469
422
|
|
|
470
423
|
async _updateCanUpgradeAndSync () {
|
|
471
|
-
const
|
|
472
|
-
const fork = this.core.tree.fork
|
|
424
|
+
const { length, fork } = this.core.tree
|
|
473
425
|
|
|
474
426
|
const canUpgrade = await this._canUpgrade(this.remoteLength, this.remoteFork)
|
|
475
427
|
|
|
476
|
-
if (this.syncsProcessing > 0 ||
|
|
428
|
+
if (this.syncsProcessing > 0 || length !== this.core.tree.length || fork !== this.core.tree.fork) {
|
|
477
429
|
return
|
|
478
430
|
}
|
|
479
431
|
if (canUpgrade === this.canUpgrade) {
|
|
@@ -632,19 +584,19 @@ class Peer {
|
|
|
632
584
|
this.replicator.updatePeer(this)
|
|
633
585
|
}
|
|
634
586
|
|
|
635
|
-
_makeRequest (
|
|
587
|
+
_makeRequest (needsUpgrade) {
|
|
636
588
|
if (needsUpgrade === true && this.replicator._shouldUpgrade(this) === false) {
|
|
637
589
|
return null
|
|
638
590
|
}
|
|
639
591
|
|
|
640
|
-
if (needsUpgrade === false &&
|
|
592
|
+
if (needsUpgrade === false && this.replicator._autoUpgrade(this) === true) {
|
|
641
593
|
needsUpgrade = true
|
|
642
594
|
}
|
|
643
595
|
|
|
644
596
|
return {
|
|
645
597
|
peer: this,
|
|
646
598
|
id: 0,
|
|
647
|
-
fork,
|
|
599
|
+
fork: this.remoteFork,
|
|
648
600
|
block: null,
|
|
649
601
|
hash: null,
|
|
650
602
|
seek: null,
|
|
@@ -655,7 +607,7 @@ class Peer {
|
|
|
655
607
|
}
|
|
656
608
|
|
|
657
609
|
_requestUpgrade (u) {
|
|
658
|
-
const req = this._makeRequest(
|
|
610
|
+
const req = this._makeRequest(true)
|
|
659
611
|
if (req === null) return false
|
|
660
612
|
|
|
661
613
|
this._send(req)
|
|
@@ -664,8 +616,12 @@ class Peer {
|
|
|
664
616
|
}
|
|
665
617
|
|
|
666
618
|
_requestSeek (s) {
|
|
667
|
-
|
|
668
|
-
|
|
619
|
+
const { length, fork } = this.core.tree
|
|
620
|
+
|
|
621
|
+
if (fork !== this.remoteFork) return false
|
|
622
|
+
|
|
623
|
+
if (s.seeker.start >= length) {
|
|
624
|
+
const req = this._makeRequest(true)
|
|
669
625
|
|
|
670
626
|
// We need an upgrade for the seek, if non can be provided, skip
|
|
671
627
|
if (req === null) return false
|
|
@@ -689,14 +645,14 @@ class Peer {
|
|
|
689
645
|
if (this.core.bitfield.get(index) === true) continue
|
|
690
646
|
|
|
691
647
|
// Check if this block is currently inflight - if so pick another
|
|
692
|
-
const b = this.replicator._blocks.get(
|
|
648
|
+
const b = this.replicator._blocks.get(index)
|
|
693
649
|
if (b !== null && b.inflight.length > 0) continue
|
|
694
650
|
|
|
695
651
|
// Block is not inflight, but we only want the hash, check if that is inflight
|
|
696
|
-
const h = this.replicator._hashes.add(
|
|
652
|
+
const h = this.replicator._hashes.add(index)
|
|
697
653
|
if (h.inflight.length > 0) continue
|
|
698
654
|
|
|
699
|
-
const req = this._makeRequest(
|
|
655
|
+
const req = this._makeRequest(false)
|
|
700
656
|
|
|
701
657
|
req.hash = { index: 2 * index, nodes: 0 }
|
|
702
658
|
req.seek = { bytes: s.seeker.bytes }
|
|
@@ -717,9 +673,11 @@ class Peer {
|
|
|
717
673
|
}
|
|
718
674
|
|
|
719
675
|
_requestBlock (b) {
|
|
720
|
-
|
|
676
|
+
const { length, fork } = this.core.tree
|
|
677
|
+
|
|
678
|
+
if (this.remoteBitfield.get(b.index) === false || fork !== this.remoteFork) return false
|
|
721
679
|
|
|
722
|
-
const req = this._makeRequest(b.
|
|
680
|
+
const req = this._makeRequest(b.index >= length)
|
|
723
681
|
if (req === null) return false
|
|
724
682
|
|
|
725
683
|
req.block = { index: b.index, nodes: 0 }
|
|
@@ -731,8 +689,10 @@ class Peer {
|
|
|
731
689
|
}
|
|
732
690
|
|
|
733
691
|
_requestRange (r) {
|
|
692
|
+
const { length, fork } = this.core.tree
|
|
693
|
+
|
|
734
694
|
const end = Math.min(r.end === -1 ? this.remoteLength : r.end, this.remoteLength)
|
|
735
|
-
if (end < r.start ||
|
|
695
|
+
if (end < r.start || fork !== this.remoteFork) return false
|
|
736
696
|
|
|
737
697
|
const len = end - r.start
|
|
738
698
|
const off = r.start + (r.linear ? 0 : Math.floor(Math.random() * len))
|
|
@@ -750,10 +710,10 @@ class Peer {
|
|
|
750
710
|
if (this.remoteBitfield.get(index) === false) continue
|
|
751
711
|
if (this.core.bitfield.get(index) === true) continue
|
|
752
712
|
|
|
753
|
-
const b = this.replicator._blocks.add(
|
|
713
|
+
const b = this.replicator._blocks.add(index)
|
|
754
714
|
if (b.inflight.length > 0) continue
|
|
755
715
|
|
|
756
|
-
const req = this._makeRequest(
|
|
716
|
+
const req = this._makeRequest(index >= length)
|
|
757
717
|
|
|
758
718
|
// If the request cannot be satisfied, dealloc the block request if no one is subscribed to it
|
|
759
719
|
if (req === null) {
|
|
@@ -773,7 +733,7 @@ class Peer {
|
|
|
773
733
|
}
|
|
774
734
|
|
|
775
735
|
_requestForkProof (f) {
|
|
776
|
-
const req = this._makeRequest(
|
|
736
|
+
const req = this._makeRequest(false)
|
|
777
737
|
|
|
778
738
|
req.upgrade = { start: 0, length: this.remoteLength }
|
|
779
739
|
|
|
@@ -796,7 +756,7 @@ class Peer {
|
|
|
796
756
|
|
|
797
757
|
if (this.remoteBitfield.get(index) === false) continue
|
|
798
758
|
|
|
799
|
-
const req = this._makeRequest(
|
|
759
|
+
const req = this._makeRequest(false)
|
|
800
760
|
|
|
801
761
|
req.hash = { index: 2 * index, nodes: f.batch.want.nodes }
|
|
802
762
|
|
|
@@ -821,8 +781,12 @@ class Peer {
|
|
|
821
781
|
}
|
|
822
782
|
|
|
823
783
|
try {
|
|
824
|
-
if (req.block !== null && req.fork === fork)
|
|
825
|
-
|
|
784
|
+
if (req.block !== null && req.fork === fork) {
|
|
785
|
+
req.block.nodes = await this.core.tree.missingNodes(2 * req.block.index)
|
|
786
|
+
}
|
|
787
|
+
if (req.hash !== null && req.fork === fork) {
|
|
788
|
+
req.hash.nodes = await this.core.tree.missingNodes(req.hash.index)
|
|
789
|
+
}
|
|
826
790
|
} catch (err) {
|
|
827
791
|
this.stream.destroy(err)
|
|
828
792
|
return
|
|
@@ -845,8 +809,8 @@ module.exports = class Replicator {
|
|
|
845
809
|
this.findingPeers = 0 // updateable from the outside
|
|
846
810
|
|
|
847
811
|
this._inflight = new InflightTracker()
|
|
848
|
-
this._blocks = new BlockTracker(
|
|
849
|
-
this._hashes = new BlockTracker(
|
|
812
|
+
this._blocks = new BlockTracker()
|
|
813
|
+
this._hashes = new BlockTracker()
|
|
850
814
|
|
|
851
815
|
this._queued = []
|
|
852
816
|
|
|
@@ -869,14 +833,34 @@ module.exports = class Replicator {
|
|
|
869
833
|
for (const peer of this.peers) peer.protomux.uncork()
|
|
870
834
|
}
|
|
871
835
|
|
|
872
|
-
|
|
836
|
+
// Called externally when a range of new blocks has been processed/removed
|
|
837
|
+
onhave (start, length, drop = false) {
|
|
873
838
|
for (const peer of this.peers) peer.broadcastRange(start, length, drop)
|
|
874
839
|
}
|
|
875
840
|
|
|
876
|
-
|
|
841
|
+
// Called externally when a truncation upgrade has been processed
|
|
842
|
+
ontruncate (newLength) {
|
|
843
|
+
const notify = []
|
|
844
|
+
|
|
845
|
+
for (const blk of this._blocks) {
|
|
846
|
+
if (blk.index < newLength) continue
|
|
847
|
+
notify.push(blk)
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
for (const blk of notify) {
|
|
851
|
+
for (const r of blk.refs) {
|
|
852
|
+
if (r.snapshot === false) continue
|
|
853
|
+
blk.detach(r, SNAPSHOT_NOT_AVAILABLE())
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
// Called externally when a upgrade has been processed
|
|
859
|
+
onupgrade () {
|
|
877
860
|
for (const peer of this.peers) peer.signalUpgrade()
|
|
878
861
|
if (this._blocks.isEmpty() === false) this._resolveBlocksLocally()
|
|
879
862
|
if (this._upgrade !== null) this._resolveUpgradeRequest(null)
|
|
863
|
+
if (this._ranges.length !== 0 || this._seeks.length !== 0) this._updateNonPrimary()
|
|
880
864
|
}
|
|
881
865
|
|
|
882
866
|
addUpgrade (session) {
|
|
@@ -901,8 +885,8 @@ module.exports = class Replicator {
|
|
|
901
885
|
return ref
|
|
902
886
|
}
|
|
903
887
|
|
|
904
|
-
addBlock (session, index
|
|
905
|
-
const b = this._blocks.add(
|
|
888
|
+
addBlock (session, index) {
|
|
889
|
+
const b = this._blocks.add(index)
|
|
906
890
|
const ref = b.attach(session)
|
|
907
891
|
|
|
908
892
|
this._queueBlock(b)
|
|
@@ -912,7 +896,7 @@ module.exports = class Replicator {
|
|
|
912
896
|
}
|
|
913
897
|
|
|
914
898
|
addSeek (session, seeker) {
|
|
915
|
-
const s = new SeekRequest(this._seeks,
|
|
899
|
+
const s = new SeekRequest(this._seeks, seeker)
|
|
916
900
|
const ref = s.attach(session)
|
|
917
901
|
|
|
918
902
|
this._seeks.push(s)
|
|
@@ -927,7 +911,7 @@ module.exports = class Replicator {
|
|
|
927
911
|
if (length === -1 || start + length > blocks.length) length = blocks.length - start
|
|
928
912
|
}
|
|
929
913
|
|
|
930
|
-
const r = new RangeRequest(this._ranges,
|
|
914
|
+
const r = new RangeRequest(this._ranges, start, length === -1 ? -1 : start + length, linear, blocks)
|
|
931
915
|
const ref = r.attach(session)
|
|
932
916
|
|
|
933
917
|
this._ranges.push(r)
|
|
@@ -940,13 +924,13 @@ module.exports = class Replicator {
|
|
|
940
924
|
}
|
|
941
925
|
|
|
942
926
|
cancel (ref) {
|
|
943
|
-
ref.context.detach(ref)
|
|
927
|
+
ref.context.detach(ref, null)
|
|
944
928
|
}
|
|
945
929
|
|
|
946
930
|
clearRequests (session) {
|
|
947
931
|
while (session.length > 0) {
|
|
948
932
|
const ref = session[session.length - 1]
|
|
949
|
-
ref.context.detach(ref)
|
|
933
|
+
ref.context.detach(ref, null)
|
|
950
934
|
}
|
|
951
935
|
|
|
952
936
|
this.updateAll()
|
|
@@ -1046,7 +1030,7 @@ module.exports = class Replicator {
|
|
|
1046
1030
|
}
|
|
1047
1031
|
|
|
1048
1032
|
_autoUpgrade (peer) {
|
|
1049
|
-
return this._upgrade !== null && this._shouldUpgrade(peer)
|
|
1033
|
+
return this._upgrade !== null && peer.remoteFork === this.core.tree.fork && this._shouldUpgrade(peer)
|
|
1050
1034
|
}
|
|
1051
1035
|
|
|
1052
1036
|
_addPeer (peer) {
|
|
@@ -1099,12 +1083,12 @@ module.exports = class Replicator {
|
|
|
1099
1083
|
// Currently the block tracker does not support deletes during iteration, so we make
|
|
1100
1084
|
// sure to clear them afterwards.
|
|
1101
1085
|
for (const b of clear) {
|
|
1102
|
-
this._blocks.remove(b.
|
|
1086
|
+
this._blocks.remove(b.index)
|
|
1103
1087
|
}
|
|
1104
1088
|
}
|
|
1105
1089
|
|
|
1106
|
-
_resolveBlockRequest (tracker,
|
|
1107
|
-
const b = tracker.remove(
|
|
1090
|
+
_resolveBlockRequest (tracker, index, value, req) {
|
|
1091
|
+
const b = tracker.remove(index)
|
|
1108
1092
|
if (b === null) return false
|
|
1109
1093
|
|
|
1110
1094
|
removeInflight(b.inflight, req)
|
|
@@ -1130,7 +1114,7 @@ module.exports = class Replicator {
|
|
|
1130
1114
|
_clearInflightBlock (tracker, req) {
|
|
1131
1115
|
const isBlock = tracker === this._blocks
|
|
1132
1116
|
const index = isBlock === true ? req.block.index : req.hash.index / 2
|
|
1133
|
-
const b = tracker.get(
|
|
1117
|
+
const b = tracker.get(index)
|
|
1134
1118
|
|
|
1135
1119
|
if (b === null || removeInflight(b.inflight, req) === false) return
|
|
1136
1120
|
|
|
@@ -1251,11 +1235,11 @@ module.exports = class Replicator {
|
|
|
1251
1235
|
|
|
1252
1236
|
_ondata (peer, req, data) {
|
|
1253
1237
|
if (data.block !== null) {
|
|
1254
|
-
this._resolveBlockRequest(this._blocks, data.
|
|
1238
|
+
this._resolveBlockRequest(this._blocks, data.block.index, data.block.value, req)
|
|
1255
1239
|
}
|
|
1256
1240
|
|
|
1257
1241
|
if (data.hash !== null && (data.hash.index & 1) === 0) {
|
|
1258
|
-
this._resolveBlockRequest(this._hashes, data.
|
|
1242
|
+
this._resolveBlockRequest(this._hashes, data.hash.index / 2, null, req)
|
|
1259
1243
|
}
|
|
1260
1244
|
|
|
1261
1245
|
if (this._upgrade !== null) {
|
|
@@ -1286,14 +1270,14 @@ module.exports = class Replicator {
|
|
|
1286
1270
|
|
|
1287
1271
|
if (f.batch) {
|
|
1288
1272
|
await f.batch.update(data)
|
|
1289
|
-
} else {
|
|
1273
|
+
} else if (data.upgrade) {
|
|
1290
1274
|
f.batch = await this.core.tree.reorg(data)
|
|
1291
1275
|
|
|
1292
1276
|
// Remove "older" reorgs in progress as we just verified this one.
|
|
1293
1277
|
this._clearOldReorgs(f.fork)
|
|
1294
1278
|
}
|
|
1295
1279
|
|
|
1296
|
-
if (f.batch.finished) {
|
|
1280
|
+
if (f.batch && f.batch.finished) {
|
|
1297
1281
|
if (this._addUpgradeMaybe() !== null) {
|
|
1298
1282
|
await this._applyReorg(f)
|
|
1299
1283
|
}
|
|
@@ -1302,6 +1286,7 @@ module.exports = class Replicator {
|
|
|
1302
1286
|
this.updateAll()
|
|
1303
1287
|
}
|
|
1304
1288
|
|
|
1289
|
+
// Never throws, allowed to run in the background
|
|
1305
1290
|
async _applyReorg (f) {
|
|
1306
1291
|
// TODO: more optimal here to check if potentially a better reorg
|
|
1307
1292
|
// is available, ie higher fork, and request that one first.
|
|
@@ -1330,13 +1315,10 @@ module.exports = class Replicator {
|
|
|
1330
1315
|
|
|
1331
1316
|
// TODO: all the remaining is a tmp workaround until we have a flag/way for ANY_FORK
|
|
1332
1317
|
for (const r of this._ranges) {
|
|
1333
|
-
r.fork = this.core.tree.fork
|
|
1334
1318
|
r.start = r.userStart
|
|
1335
1319
|
r.end = r.userEnd
|
|
1336
1320
|
}
|
|
1337
|
-
|
|
1338
|
-
for (const b of this._blocks) b.fork = this.core.tree.fork
|
|
1339
|
-
this._blocks.update(this.core.tree.fork)
|
|
1321
|
+
|
|
1340
1322
|
this.updateAll()
|
|
1341
1323
|
}
|
|
1342
1324
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hypercore",
|
|
3
|
-
"version": "10.0.0-alpha.
|
|
3
|
+
"version": "10.0.0-alpha.38",
|
|
4
4
|
"description": "Hypercore 10",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"brittle": "^2.0.0",
|
|
55
55
|
"hyperswarm": "next",
|
|
56
|
-
"random-access-memory": "^
|
|
56
|
+
"random-access-memory": "^4.1.0",
|
|
57
57
|
"standard": "^16.0.3",
|
|
58
58
|
"tmp-promise": "^3.0.2"
|
|
59
59
|
},
|