hypercore 10.30.4 → 10.31.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/index.js +15 -6
- package/lib/batch.js +39 -16
- package/lib/block-store.js +3 -2
- package/lib/core.js +8 -7
- package/lib/merkle-tree.js +70 -76
- package/lib/replicator.js +15 -6
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -391,7 +391,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
391
391
|
eagerUpgrade: true,
|
|
392
392
|
allowFork: opts.allowFork !== false,
|
|
393
393
|
onpeerupdate: this._onpeerupdate.bind(this),
|
|
394
|
-
onupload: this._onupload.bind(this)
|
|
394
|
+
onupload: this._onupload.bind(this),
|
|
395
|
+
oninvalid: this._oninvalid.bind(this)
|
|
395
396
|
})
|
|
396
397
|
|
|
397
398
|
this.replicator.findingPeers += this._findingPeers
|
|
@@ -589,7 +590,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
589
590
|
}
|
|
590
591
|
|
|
591
592
|
get contiguousLength () {
|
|
592
|
-
return this.core === null ? 0 : this.core.header.hints.contiguousLength
|
|
593
|
+
return this.core === null ? 0 : Math.min(this.core.tree.length, this.core.header.hints.contiguousLength)
|
|
593
594
|
}
|
|
594
595
|
|
|
595
596
|
get contiguousByteLength () {
|
|
@@ -624,6 +625,12 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
624
625
|
}
|
|
625
626
|
}
|
|
626
627
|
|
|
628
|
+
_oninvalid (err, req, res, from) {
|
|
629
|
+
for (let i = 0; i < this.sessions.length; i++) {
|
|
630
|
+
this.sessions[i].emit('verification-error', err, req, res, from)
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
627
634
|
async _oncoreconflict (proof, from) {
|
|
628
635
|
await this.replicator.onconflict(from)
|
|
629
636
|
|
|
@@ -800,14 +807,15 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
800
807
|
return true
|
|
801
808
|
}
|
|
802
809
|
|
|
803
|
-
batch ({ checkout = -1, autoClose = true, session = true } = {}) {
|
|
804
|
-
return new Batch(session ? this.session() : this, checkout, autoClose)
|
|
810
|
+
batch ({ checkout = -1, autoClose = true, session = true, restore = false } = {}) {
|
|
811
|
+
return new Batch(session ? this.session() : this, checkout, autoClose, restore)
|
|
805
812
|
}
|
|
806
813
|
|
|
807
814
|
async seek (bytes, opts) {
|
|
808
815
|
if (this.opened === false) await this.opening
|
|
809
816
|
|
|
810
|
-
const
|
|
817
|
+
const tree = (opts && opts.tree) || this.core.tree
|
|
818
|
+
const s = tree.seek(bytes, this.padding)
|
|
811
819
|
|
|
812
820
|
const offset = await s.update()
|
|
813
821
|
if (offset) return offset
|
|
@@ -887,7 +895,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
887
895
|
let block
|
|
888
896
|
|
|
889
897
|
if (this.core.bitfield.get(index)) {
|
|
890
|
-
|
|
898
|
+
const tree = (opts && opts.tree) || this.core.tree
|
|
899
|
+
block = this.core.blocks.get(index, tree)
|
|
891
900
|
|
|
892
901
|
if (this.cache) this.cache.set(index, block)
|
|
893
902
|
} else {
|
package/lib/batch.js
CHANGED
|
@@ -4,7 +4,7 @@ const c = require('compact-encoding')
|
|
|
4
4
|
const b4a = require('b4a')
|
|
5
5
|
|
|
6
6
|
module.exports = class HypercoreBatch extends EventEmitter {
|
|
7
|
-
constructor (session, checkoutLength, autoClose) {
|
|
7
|
+
constructor (session, checkoutLength, autoClose, restore) {
|
|
8
8
|
super()
|
|
9
9
|
|
|
10
10
|
this.session = session
|
|
@@ -14,6 +14,7 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
14
14
|
this.closing = null
|
|
15
15
|
this.writable = true // always writable...
|
|
16
16
|
this.autoClose = autoClose
|
|
17
|
+
this.restore = restore
|
|
17
18
|
this.fork = 0
|
|
18
19
|
|
|
19
20
|
this._appends = []
|
|
@@ -41,7 +42,7 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
get indexedLength () {
|
|
44
|
-
return this._sessionLength
|
|
45
|
+
return Math.min(this._sessionLength, this.session.core === null ? 0 : this.session.core.tree.length)
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
get indexedByteLength () {
|
|
@@ -77,9 +78,18 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
77
78
|
this._sessionByteLength = batch.byteLength
|
|
78
79
|
this._sessionBatch = batch
|
|
79
80
|
} else {
|
|
80
|
-
this.
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
const last = this.restore ? this.session.core.bitfield.findFirst(false, this.session.length) : 0
|
|
82
|
+
|
|
83
|
+
if (last > this.session.length) {
|
|
84
|
+
const batch = await this.session.core.tree.restoreBatch(last)
|
|
85
|
+
this._sessionLength = batch.length
|
|
86
|
+
this._sessionByteLength = batch.byteLength - this.session.padding * batch.length
|
|
87
|
+
this._sessionBatch = batch
|
|
88
|
+
} else {
|
|
89
|
+
this._sessionLength = this.session.length
|
|
90
|
+
this._sessionByteLength = this.session.byteLength
|
|
91
|
+
this._sessionBatch = this.session.createTreeBatch()
|
|
92
|
+
}
|
|
83
93
|
}
|
|
84
94
|
|
|
85
95
|
this._appendsActual = this.session.encryption ? [] : this._appends
|
|
@@ -128,11 +138,11 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
128
138
|
return info
|
|
129
139
|
}
|
|
130
140
|
|
|
131
|
-
async seek (bytes, opts) {
|
|
141
|
+
async seek (bytes, opts = {}) {
|
|
132
142
|
if (this.opened === false) await this.opening
|
|
133
143
|
if (this.closing) throw SESSION_CLOSED()
|
|
134
144
|
|
|
135
|
-
if (bytes < this._sessionByteLength) return await this.session.seek(bytes, opts)
|
|
145
|
+
if (bytes < this._sessionByteLength) return await this.session.seek(bytes, { ...opts, tree: this._sessionBatch })
|
|
136
146
|
|
|
137
147
|
bytes -= this._sessionByteLength
|
|
138
148
|
|
|
@@ -154,7 +164,7 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
154
164
|
if (this.closing) throw SESSION_CLOSED()
|
|
155
165
|
|
|
156
166
|
const length = this._sessionLength
|
|
157
|
-
if (index < length) return this.session.get(index, opts)
|
|
167
|
+
if (index < length) return this.session.get(index, { ...opts, tree: this._sessionBatch })
|
|
158
168
|
|
|
159
169
|
const buffer = this._appends[index - length] || null
|
|
160
170
|
if (!buffer) throw BLOCK_NOT_AVAILABLE()
|
|
@@ -173,6 +183,11 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
173
183
|
}
|
|
174
184
|
}
|
|
175
185
|
|
|
186
|
+
async restoreBatch (length) {
|
|
187
|
+
if (this.opened === false) await this.opening
|
|
188
|
+
return this.session.core.tree.restoreBatch(length)
|
|
189
|
+
}
|
|
190
|
+
|
|
176
191
|
createTreeBatch (length, blocks = []) {
|
|
177
192
|
if (!length && length !== 0) length = this.length + blocks.length
|
|
178
193
|
|
|
@@ -293,10 +308,10 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
293
308
|
if (this.opened === false) await this.opening
|
|
294
309
|
if (this.closing) throw SESSION_CLOSED()
|
|
295
310
|
|
|
296
|
-
const { length = this.length, keyPair = this.session.keyPair, signature = null } = opts
|
|
311
|
+
const { length = this.length, keyPair = this.session.keyPair, signature = null, pending = !signature && !keyPair } = opts
|
|
297
312
|
|
|
298
313
|
while (this._flushing) await this._flushing
|
|
299
|
-
this._flushing = this._flush(length, keyPair, signature)
|
|
314
|
+
this._flushing = this._flush(length, keyPair, signature, pending)
|
|
300
315
|
|
|
301
316
|
let flushed = false
|
|
302
317
|
|
|
@@ -311,12 +326,9 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
311
326
|
return flushed
|
|
312
327
|
}
|
|
313
328
|
|
|
314
|
-
async _flush (length, keyPair, signature) { // TODO: make this safe to interact with a parallel truncate...
|
|
329
|
+
async _flush (length, keyPair, signature, pending) { // TODO: make this safe to interact with a parallel truncate...
|
|
315
330
|
if (this._sessionBatch.fork !== this.session.fork) return false // no truncs supported atm
|
|
316
331
|
|
|
317
|
-
const flushingLength = Math.min(length - this._sessionLength, this._appends.length)
|
|
318
|
-
if (flushingLength <= 0) return true
|
|
319
|
-
|
|
320
332
|
if (this.session.replicator._upgrade) {
|
|
321
333
|
for (const req of this.session.replicator._upgrade.inflight) {
|
|
322
334
|
// yield to the remote inflight upgrade, TODO: if the remote upgrade fails, retry flushing...
|
|
@@ -326,17 +338,28 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
326
338
|
}
|
|
327
339
|
}
|
|
328
340
|
|
|
341
|
+
const flushingLength = Math.min(length - this._sessionLength, this._appends.length)
|
|
342
|
+
if (flushingLength <= 0) {
|
|
343
|
+
if (this._sessionLength > this.core.tree.length && length > this.core.tree.length && !pending) {
|
|
344
|
+
const batch = await this.restoreBatch(length)
|
|
345
|
+
const info = await this.core.insertBatch(batch, [], { keyPair, signature, pending, treeLength: length })
|
|
346
|
+
return info !== null
|
|
347
|
+
}
|
|
348
|
+
return true
|
|
349
|
+
}
|
|
350
|
+
|
|
329
351
|
const batch = this.createTreeBatch(this._sessionLength + flushingLength)
|
|
330
352
|
if (batch === null) return false
|
|
331
353
|
|
|
332
|
-
const info = await this.core.insertBatch(batch, this._appendsActual, { keyPair, signature })
|
|
354
|
+
const info = await this.core.insertBatch(batch, this._appendsActual, { keyPair, signature, pending, treeLength: this._sessionLength })
|
|
333
355
|
if (info === null) return false
|
|
334
356
|
|
|
335
357
|
const delta = info.byteLength - this._sessionByteLength
|
|
358
|
+
const newBatch = info.length !== this.session.length ? await this.restoreBatch(info.length) : this.session.createTreeBatch()
|
|
336
359
|
|
|
337
360
|
this._sessionLength = info.length
|
|
338
361
|
this._sessionByteLength = info.byteLength
|
|
339
|
-
this._sessionBatch =
|
|
362
|
+
this._sessionBatch = newBatch
|
|
340
363
|
|
|
341
364
|
const same = this._appends === this._appendsActual
|
|
342
365
|
|
package/lib/block-store.js
CHANGED
|
@@ -6,8 +6,9 @@ module.exports = class BlockStore {
|
|
|
6
6
|
this.tree = tree
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
async get (i) {
|
|
10
|
-
|
|
9
|
+
async get (i, tree) {
|
|
10
|
+
if (!tree) tree = this.tree
|
|
11
|
+
const [offset, size] = await tree.byteRange(2 * i)
|
|
11
12
|
return this._read(offset, size)
|
|
12
13
|
}
|
|
13
14
|
|
package/lib/core.js
CHANGED
|
@@ -451,7 +451,7 @@ module.exports = class Core {
|
|
|
451
451
|
})
|
|
452
452
|
}
|
|
453
453
|
|
|
454
|
-
async insertBatch (batch, values, { signature, keyPair = this.header.keyPair } = {}) {
|
|
454
|
+
async insertBatch (batch, values, { signature, keyPair = this.header.keyPair, pending = false, treeLength = batch.treeLength } = {}) {
|
|
455
455
|
await this._mutex.lock()
|
|
456
456
|
|
|
457
457
|
try {
|
|
@@ -471,29 +471,30 @@ module.exports = class Core {
|
|
|
471
471
|
}
|
|
472
472
|
}
|
|
473
473
|
|
|
474
|
-
const
|
|
475
|
-
const adding = batch.length - batch.treeLength
|
|
474
|
+
const adding = batch.length - treeLength
|
|
476
475
|
|
|
477
476
|
batch.upgraded = batch.length > this.tree.length
|
|
478
477
|
batch.treeLength = this.tree.length
|
|
479
478
|
batch.ancestors = this.tree.length
|
|
480
|
-
if (batch.upgraded) batch.signature = signature || this.verifier.sign(batch, keyPair)
|
|
479
|
+
if (batch.upgraded && !pending) batch.signature = signature || this.verifier.sign(batch, keyPair)
|
|
481
480
|
|
|
482
481
|
let byteOffset = batch.byteLength
|
|
483
482
|
for (let i = 0; i < adding; i++) byteOffset -= values[i].byteLength
|
|
484
483
|
|
|
484
|
+
if (pending === true) batch.upgraded = false
|
|
485
|
+
|
|
485
486
|
const entry = {
|
|
486
487
|
userData: null,
|
|
487
488
|
treeNodes: batch.nodes,
|
|
488
489
|
treeUpgrade: batch.upgraded ? batch : null,
|
|
489
490
|
bitfield: {
|
|
490
491
|
drop: false,
|
|
491
|
-
start:
|
|
492
|
+
start: treeLength,
|
|
492
493
|
length: adding
|
|
493
494
|
}
|
|
494
495
|
}
|
|
495
496
|
|
|
496
|
-
await this.blocks.putBatch(
|
|
497
|
+
await this.blocks.putBatch(treeLength, adding > values.length ? values.slice(0, adding) : values, byteOffset)
|
|
497
498
|
await this.oplog.append([entry], false)
|
|
498
499
|
|
|
499
500
|
this.bitfield.setRange(entry.bitfield.start, entry.bitfield.length, true)
|
|
@@ -506,7 +507,7 @@ module.exports = class Core {
|
|
|
506
507
|
}
|
|
507
508
|
|
|
508
509
|
const status = (batch.upgraded ? 0b0001 : 0) | updateContig(this.header, entry.bitfield, this.bitfield)
|
|
509
|
-
this.onupdate(status, entry.bitfield, null, null)
|
|
510
|
+
if (!pending) this.onupdate(status, entry.bitfield, null, null)
|
|
510
511
|
|
|
511
512
|
if (this._shouldFlush()) await this._flushOplog()
|
|
512
513
|
} finally {
|
package/lib/merkle-tree.js
CHANGED
|
@@ -87,7 +87,7 @@ class MerkleTreeBatch {
|
|
|
87
87
|
return caps.treeSignableCompat(this.hash(), this.length, this.fork, noHeader)
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
get (index) {
|
|
90
|
+
get (index, error) {
|
|
91
91
|
if (index >= this.length * 2) {
|
|
92
92
|
return null
|
|
93
93
|
}
|
|
@@ -96,11 +96,7 @@ class MerkleTreeBatch {
|
|
|
96
96
|
if (n.index === index) return n
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
return this.tree.get(index)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return null
|
|
99
|
+
return this.tree.get(index, error)
|
|
104
100
|
}
|
|
105
101
|
|
|
106
102
|
proof ({ block, hash, seek, upgrade }) {
|
|
@@ -203,40 +199,17 @@ class MerkleTreeBatch {
|
|
|
203
199
|
this.tree.signature = this.signature
|
|
204
200
|
}
|
|
205
201
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
async byteOffset (index) {
|
|
211
|
-
if (2 * this.tree.length === index) return this.tree.byteLength
|
|
212
|
-
|
|
213
|
-
const ite = flat.iterator(index)
|
|
214
|
-
|
|
215
|
-
let treeOffset = 0
|
|
216
|
-
let isRight = false
|
|
217
|
-
let parent = null
|
|
218
|
-
|
|
219
|
-
for (const node of this.nodes) {
|
|
220
|
-
if (node.index === ite.index) {
|
|
221
|
-
if (isRight && parent) treeOffset += node.size - parent.size
|
|
222
|
-
parent = node
|
|
223
|
-
isRight = ite.isRight()
|
|
224
|
-
ite.parent()
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const r = this.roots.indexOf(parent)
|
|
229
|
-
if (r > -1) {
|
|
230
|
-
for (let i = 0; i < r; i++) {
|
|
231
|
-
treeOffset += this.roots[i].size
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return treeOffset
|
|
235
|
-
}
|
|
202
|
+
seek (bytes, padding) {
|
|
203
|
+
return new ByteSeeker(this, bytes, padding)
|
|
204
|
+
}
|
|
236
205
|
|
|
237
|
-
|
|
206
|
+
byteRange (index) {
|
|
207
|
+
return getByteRange(this, index)
|
|
208
|
+
}
|
|
238
209
|
|
|
239
|
-
|
|
210
|
+
byteOffset (index) {
|
|
211
|
+
if (index === 2 * this.tree.length) return this.tree.byteLength
|
|
212
|
+
return getByteOffset(this, index)
|
|
240
213
|
}
|
|
241
214
|
}
|
|
242
215
|
|
|
@@ -337,10 +310,6 @@ class ByteSeeker {
|
|
|
337
310
|
this.end = bytes < size ? tree.length : 0
|
|
338
311
|
}
|
|
339
312
|
|
|
340
|
-
nodes () {
|
|
341
|
-
return this.tree.nodes(this.start * 2)
|
|
342
|
-
}
|
|
343
|
-
|
|
344
313
|
async _seek (bytes) {
|
|
345
314
|
if (!bytes) return [0, 0]
|
|
346
315
|
|
|
@@ -357,6 +326,7 @@ class ByteSeeker {
|
|
|
357
326
|
|
|
358
327
|
while ((ite.index & 1) !== 0) {
|
|
359
328
|
const l = await this.tree.get(ite.leftChild(), false)
|
|
329
|
+
|
|
360
330
|
if (l) {
|
|
361
331
|
const size = getUnpaddedSize(l, this.padding, ite)
|
|
362
332
|
|
|
@@ -415,6 +385,22 @@ module.exports = class MerkleTree {
|
|
|
415
385
|
return new MerkleTreeBatch(this)
|
|
416
386
|
}
|
|
417
387
|
|
|
388
|
+
async restoreBatch (length) {
|
|
389
|
+
const batch = new MerkleTreeBatch(this)
|
|
390
|
+
if (length === this.length) return batch
|
|
391
|
+
|
|
392
|
+
const roots = await this.getRoots(length)
|
|
393
|
+
|
|
394
|
+
batch.roots = roots
|
|
395
|
+
batch.length = length
|
|
396
|
+
batch.byteLength = 0
|
|
397
|
+
batch.ancestors = length
|
|
398
|
+
|
|
399
|
+
for (const node of roots) batch.byteLength += node.size
|
|
400
|
+
|
|
401
|
+
return batch
|
|
402
|
+
}
|
|
403
|
+
|
|
418
404
|
seek (bytes, padding) {
|
|
419
405
|
return new ByteSeeker(this, bytes, padding)
|
|
420
406
|
}
|
|
@@ -706,42 +692,12 @@ module.exports = class MerkleTree {
|
|
|
706
692
|
return cnt
|
|
707
693
|
}
|
|
708
694
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
if (((index & 1) === 0 ? index : flat.rightSpan(index)) >= head) {
|
|
712
|
-
throw BAD_ARGUMENT('Index is out of bounds')
|
|
713
|
-
}
|
|
714
|
-
return [await this.byteOffset(index), (await this.get(index)).size]
|
|
695
|
+
byteRange (index) {
|
|
696
|
+
return getByteRange(this, index)
|
|
715
697
|
}
|
|
716
698
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
if ((index & 1) === 1) index = flat.leftSpan(index)
|
|
720
|
-
|
|
721
|
-
let head = 0
|
|
722
|
-
let offset = 0
|
|
723
|
-
|
|
724
|
-
for (const node of this.roots) { // all async ticks happen once we find the root so safe
|
|
725
|
-
head += 2 * ((node.index - head) + 1)
|
|
726
|
-
|
|
727
|
-
if (index >= head) {
|
|
728
|
-
offset += node.size
|
|
729
|
-
continue
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
const ite = flat.iterator(node.index)
|
|
733
|
-
|
|
734
|
-
while (ite.index !== index) {
|
|
735
|
-
if (index < ite.index) {
|
|
736
|
-
ite.leftChild()
|
|
737
|
-
} else {
|
|
738
|
-
offset += (await this.get(ite.leftChild())).size
|
|
739
|
-
ite.sibling()
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
return offset
|
|
744
|
-
}
|
|
699
|
+
byteOffset (index) {
|
|
700
|
+
return getByteOffset(this, index)
|
|
745
701
|
}
|
|
746
702
|
|
|
747
703
|
static async open (storage, opts = {}) {
|
|
@@ -766,6 +722,44 @@ module.exports = class MerkleTree {
|
|
|
766
722
|
}
|
|
767
723
|
}
|
|
768
724
|
|
|
725
|
+
async function getByteRange (tree, index) {
|
|
726
|
+
const head = 2 * tree.length
|
|
727
|
+
if (((index & 1) === 0 ? index : flat.rightSpan(index)) >= head) {
|
|
728
|
+
throw BAD_ARGUMENT('Index is out of bounds')
|
|
729
|
+
}
|
|
730
|
+
return [await tree.byteOffset(index), (await tree.get(index)).size]
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
async function getByteOffset (tree, index) {
|
|
734
|
+
if (index === 2 * tree.length) return tree.byteLength
|
|
735
|
+
if ((index & 1) === 1) index = flat.leftSpan(index)
|
|
736
|
+
|
|
737
|
+
let head = 0
|
|
738
|
+
let offset = 0
|
|
739
|
+
|
|
740
|
+
for (const node of tree.roots) { // all async ticks happen once we find the root so safe
|
|
741
|
+
head += 2 * ((node.index - head) + 1)
|
|
742
|
+
|
|
743
|
+
if (index >= head) {
|
|
744
|
+
offset += node.size
|
|
745
|
+
continue
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
const ite = flat.iterator(node.index)
|
|
749
|
+
|
|
750
|
+
while (ite.index !== index) {
|
|
751
|
+
if (index < ite.index) {
|
|
752
|
+
ite.leftChild()
|
|
753
|
+
} else {
|
|
754
|
+
offset += (await tree.get(ite.leftChild())).size
|
|
755
|
+
ite.sibling()
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
return offset
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
769
763
|
// All the methods needed for proof verification
|
|
770
764
|
|
|
771
765
|
function verifyTree ({ block, hash, seek }, crypto, nodes) {
|
package/lib/replicator.js
CHANGED
|
@@ -408,7 +408,7 @@ class Peer {
|
|
|
408
408
|
|
|
409
409
|
this.sendSync()
|
|
410
410
|
|
|
411
|
-
const contig = this.core.header.hints.contiguousLength
|
|
411
|
+
const contig = Math.min(this.core.tree.length, this.core.header.hints.contiguousLength)
|
|
412
412
|
if (contig > 0) {
|
|
413
413
|
this.broadcastRange(0, contig, false)
|
|
414
414
|
|
|
@@ -636,11 +636,11 @@ class Peer {
|
|
|
636
636
|
this.wireCancel.send({ request: id })
|
|
637
637
|
}
|
|
638
638
|
|
|
639
|
-
_checkIfConflict (
|
|
639
|
+
_checkIfConflict () {
|
|
640
640
|
this.paused = true
|
|
641
641
|
|
|
642
642
|
const length = Math.min(this.core.tree.length, this.remoteLength)
|
|
643
|
-
if (length === 0)
|
|
643
|
+
if (length === 0) return // pause and ignore
|
|
644
644
|
|
|
645
645
|
this.wireRequest.send({
|
|
646
646
|
id: 0, // TODO: use an more explicit id for this eventually...
|
|
@@ -675,7 +675,14 @@ class Peer {
|
|
|
675
675
|
this.replicator._removeInflight(req.id)
|
|
676
676
|
}
|
|
677
677
|
|
|
678
|
-
|
|
678
|
+
try {
|
|
679
|
+
if (reorg === true) return await this.replicator._onreorgdata(this, req, data)
|
|
680
|
+
} catch (err) {
|
|
681
|
+
safetyCatch(err)
|
|
682
|
+
this.paused = true
|
|
683
|
+
this.replicator.oninvalid(err, req, data, this)
|
|
684
|
+
return
|
|
685
|
+
}
|
|
679
686
|
|
|
680
687
|
this.dataProcessing++
|
|
681
688
|
|
|
@@ -690,9 +697,10 @@ class Peer {
|
|
|
690
697
|
|
|
691
698
|
if (err.code !== 'INVALID_OPERATION') {
|
|
692
699
|
// might be a fork, verify
|
|
693
|
-
this._checkIfConflict(
|
|
700
|
+
this._checkIfConflict()
|
|
694
701
|
}
|
|
695
702
|
this.replicator._onnodata(this, req)
|
|
703
|
+
this.replicator.oninvalid(err, req, data, this)
|
|
696
704
|
return
|
|
697
705
|
} finally {
|
|
698
706
|
this.dataProcessing--
|
|
@@ -1104,7 +1112,7 @@ class Peer {
|
|
|
1104
1112
|
}
|
|
1105
1113
|
|
|
1106
1114
|
module.exports = class Replicator {
|
|
1107
|
-
constructor (core, key, { eagerUpgrade = true, allowFork = true, onpeerupdate = noop, onupload = noop } = {}) {
|
|
1115
|
+
constructor (core, key, { eagerUpgrade = true, allowFork = true, onpeerupdate = noop, onupload = noop, oninvalid = noop } = {}) {
|
|
1108
1116
|
this.key = key
|
|
1109
1117
|
this.discoveryKey = core.crypto.discoveryKey(key)
|
|
1110
1118
|
this.core = core
|
|
@@ -1112,6 +1120,7 @@ module.exports = class Replicator {
|
|
|
1112
1120
|
this.allowFork = allowFork
|
|
1113
1121
|
this.onpeerupdate = onpeerupdate
|
|
1114
1122
|
this.onupload = onupload
|
|
1123
|
+
this.oninvalid = oninvalid
|
|
1115
1124
|
this.ondownloading = null // optional external hook for monitoring downloading status
|
|
1116
1125
|
this.peers = []
|
|
1117
1126
|
this.findingPeers = 0 // updateable from the outside
|