hypercore 10.0.0-alpha.5 → 10.0.0-alpha.50
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/README.md +68 -5
- package/index.js +594 -173
- package/lib/bitfield.js +9 -5
- package/lib/block-encryption.js +68 -0
- package/lib/block-store.js +3 -1
- package/lib/caps.js +32 -0
- package/lib/core.js +88 -27
- package/lib/errors.js +50 -0
- package/lib/merkle-tree.js +186 -113
- package/lib/messages.js +249 -168
- package/lib/oplog.js +4 -3
- package/lib/replicator.js +1385 -616
- package/lib/streams.js +56 -0
- package/package.json +18 -9
- package/.github/workflows/test-node.yml +0 -23
- package/CHANGELOG.md +0 -37
- package/UPGRADE.md +0 -9
- package/examples/announce.js +0 -19
- package/examples/basic.js +0 -10
- package/examples/http.js +0 -123
- package/examples/lookup.js +0 -20
- package/lib/extensions.js +0 -76
- package/lib/protocol.js +0 -524
- package/lib/random-iterator.js +0 -46
- package/test/basic.js +0 -78
- package/test/bitfield.js +0 -71
- package/test/core.js +0 -290
- package/test/encodings.js +0 -18
- package/test/extension.js +0 -71
- package/test/helpers/index.js +0 -23
- package/test/merkle-tree.js +0 -518
- package/test/mutex.js +0 -137
- package/test/oplog.js +0 -399
- package/test/preload.js +0 -72
- package/test/replicate.js +0 -333
- package/test/sessions.js +0 -173
- package/test/user-data.js +0 -47
package/lib/merkle-tree.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const flat = require('flat-tree')
|
|
2
2
|
const crypto = require('hypercore-crypto')
|
|
3
|
-
const
|
|
3
|
+
const c = require('compact-encoding')
|
|
4
|
+
const b4a = require('b4a')
|
|
5
|
+
const caps = require('./caps')
|
|
4
6
|
|
|
5
|
-
const BLANK_HASH =
|
|
6
|
-
const OLD_TREE =
|
|
7
|
+
const BLANK_HASH = b4a.alloc(32)
|
|
8
|
+
const OLD_TREE = b4a.from([5, 2, 87, 2, 0, 0, 40, 7, 66, 76, 65, 75, 69, 50, 98])
|
|
7
9
|
|
|
8
10
|
class NodeQueue {
|
|
9
11
|
constructor (nodes, extra = null) {
|
|
@@ -56,11 +58,11 @@ class MerkleTreeBatch {
|
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
signable (hash = this.hash()) {
|
|
59
|
-
return
|
|
61
|
+
return caps.treeSignable(hash, this.length, this.fork)
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
return
|
|
64
|
+
signableLegacy (hash = this.hash()) {
|
|
65
|
+
return caps.treeSignableLegacy(hash, this.length, this.fork)
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
append (buf) {
|
|
@@ -212,9 +214,9 @@ class ReorgBatch extends MerkleTreeBatch {
|
|
|
212
214
|
if (this.want === null) return true
|
|
213
215
|
|
|
214
216
|
const nodes = []
|
|
215
|
-
const root =
|
|
217
|
+
const root = verifyTree(proof, this.tree.crypto, nodes)
|
|
216
218
|
|
|
217
|
-
if (root === null || !root.hash
|
|
219
|
+
if (root === null || !b4a.equals(root.hash, this.diff.hash)) return false
|
|
218
220
|
|
|
219
221
|
this.nodes.push(...nodes)
|
|
220
222
|
return this._update(nodes)
|
|
@@ -226,13 +228,14 @@ class ReorgBatch extends MerkleTreeBatch {
|
|
|
226
228
|
|
|
227
229
|
let diff = null
|
|
228
230
|
const ite = flat.iterator(this.diff.index)
|
|
231
|
+
const startingDiff = this.diff
|
|
229
232
|
|
|
230
233
|
while ((ite.index & 1) !== 0) {
|
|
231
234
|
const left = n.get(ite.leftChild())
|
|
232
235
|
if (!left) break
|
|
233
236
|
|
|
234
237
|
const existing = await this.tree.get(left.index, false)
|
|
235
|
-
if (!existing || !existing.hash
|
|
238
|
+
if (!existing || !b4a.equals(existing.hash, left.hash)) {
|
|
236
239
|
diff = left
|
|
237
240
|
} else {
|
|
238
241
|
diff = n.get(ite.sibling())
|
|
@@ -241,20 +244,19 @@ class ReorgBatch extends MerkleTreeBatch {
|
|
|
241
244
|
|
|
242
245
|
if ((this.diff.index & 1) === 0) return true
|
|
243
246
|
if (diff === null) return false
|
|
247
|
+
if (startingDiff !== this.diff) return false
|
|
244
248
|
|
|
245
249
|
return this._updateDiffRoot(diff)
|
|
246
250
|
}
|
|
247
251
|
|
|
248
252
|
_updateDiffRoot (diff) {
|
|
253
|
+
if (this.want === null) return true
|
|
254
|
+
|
|
249
255
|
const spans = flat.spans(diff.index)
|
|
250
256
|
const start = spans[0] / 2
|
|
251
257
|
const end = Math.min(this.treeLength, spans[1] / 2 + 1)
|
|
252
258
|
const len = end - start
|
|
253
259
|
|
|
254
|
-
if (this.diff !== null && len >= this.want.end - this.want.start) {
|
|
255
|
-
return false
|
|
256
|
-
}
|
|
257
|
-
|
|
258
260
|
this.ancestors = start
|
|
259
261
|
this.diff = diff
|
|
260
262
|
|
|
@@ -272,11 +274,15 @@ class ReorgBatch extends MerkleTreeBatch {
|
|
|
272
274
|
}
|
|
273
275
|
|
|
274
276
|
class ByteSeeker {
|
|
275
|
-
constructor (tree, bytes) {
|
|
277
|
+
constructor (tree, bytes, padding = 0) {
|
|
276
278
|
this.tree = tree
|
|
277
279
|
this.bytes = bytes
|
|
278
|
-
this.
|
|
279
|
-
|
|
280
|
+
this.padding = padding
|
|
281
|
+
|
|
282
|
+
const size = tree.byteLength - (tree.length * padding)
|
|
283
|
+
|
|
284
|
+
this.start = bytes >= size ? tree.length : 0
|
|
285
|
+
this.end = bytes < size ? tree.length : 0
|
|
280
286
|
}
|
|
281
287
|
|
|
282
288
|
nodes () {
|
|
@@ -287,12 +293,12 @@ class ByteSeeker {
|
|
|
287
293
|
if (!bytes) return [0, 0]
|
|
288
294
|
|
|
289
295
|
for (const node of this.tree.roots) { // all async ticks happen once we find the root so safe
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
296
|
+
let size = node.size
|
|
297
|
+
if (this.padding > 0) size -= this.padding * flat.countLeaves(node.index)
|
|
293
298
|
|
|
294
|
-
if (bytes
|
|
295
|
-
|
|
299
|
+
if (bytes === size) return [flat.rightSpan(node.index) + 2, 0]
|
|
300
|
+
if (bytes > size) {
|
|
301
|
+
bytes -= size
|
|
296
302
|
continue
|
|
297
303
|
}
|
|
298
304
|
|
|
@@ -301,9 +307,12 @@ class ByteSeeker {
|
|
|
301
307
|
while ((ite.index & 1) !== 0) {
|
|
302
308
|
const l = await this.tree.get(ite.leftChild(), false)
|
|
303
309
|
if (l) {
|
|
304
|
-
|
|
305
|
-
if (
|
|
306
|
-
|
|
310
|
+
let size = l.size
|
|
311
|
+
if (this.padding > 0) size -= this.padding * ite.countLeaves()
|
|
312
|
+
|
|
313
|
+
if (size === bytes) return [ite.rightSpan() + 2, 0]
|
|
314
|
+
if (size > bytes) continue
|
|
315
|
+
bytes -= size
|
|
307
316
|
ite.sibling()
|
|
308
317
|
} else {
|
|
309
318
|
ite.parent()
|
|
@@ -347,7 +356,7 @@ module.exports = class MerkleTree {
|
|
|
347
356
|
}
|
|
348
357
|
|
|
349
358
|
addNode (node) {
|
|
350
|
-
if (node.size === 0 && node.hash
|
|
359
|
+
if (node.size === 0 && b4a.equals(node.hash, BLANK_HASH)) node = blankNode(node.index)
|
|
351
360
|
this.unflushed.set(node.index, node)
|
|
352
361
|
}
|
|
353
362
|
|
|
@@ -355,8 +364,8 @@ module.exports = class MerkleTree {
|
|
|
355
364
|
return new MerkleTreeBatch(this)
|
|
356
365
|
}
|
|
357
366
|
|
|
358
|
-
seek (bytes) {
|
|
359
|
-
return new ByteSeeker(this, bytes)
|
|
367
|
+
seek (bytes, padding) {
|
|
368
|
+
return new ByteSeeker(this, bytes, padding)
|
|
360
369
|
}
|
|
361
370
|
|
|
362
371
|
hash () {
|
|
@@ -364,11 +373,33 @@ module.exports = class MerkleTree {
|
|
|
364
373
|
}
|
|
365
374
|
|
|
366
375
|
signable (hash = this.hash()) {
|
|
367
|
-
return
|
|
376
|
+
return caps.treeSignable(hash, this.length, this.fork)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
getRoots (length) {
|
|
380
|
+
const indexes = flat.fullRoots(2 * length)
|
|
381
|
+
const roots = new Array(indexes.length)
|
|
382
|
+
|
|
383
|
+
for (let i = 0; i < indexes.length; i++) {
|
|
384
|
+
roots[i] = this.get(indexes[i], true)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return Promise.all(roots)
|
|
368
388
|
}
|
|
369
389
|
|
|
370
|
-
|
|
371
|
-
|
|
390
|
+
async upgradeable (length) {
|
|
391
|
+
const indexes = flat.fullRoots(2 * length)
|
|
392
|
+
const roots = new Array(indexes.length)
|
|
393
|
+
|
|
394
|
+
for (let i = 0; i < indexes.length; i++) {
|
|
395
|
+
roots[i] = this.get(indexes[i], false)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
for (const node of await Promise.all(roots)) {
|
|
399
|
+
if (node === null) return false
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return true
|
|
372
403
|
}
|
|
373
404
|
|
|
374
405
|
get (index, error = true) {
|
|
@@ -433,17 +464,23 @@ module.exports = class MerkleTree {
|
|
|
433
464
|
// TODO: write neighbors together etc etc
|
|
434
465
|
// TODO: bench loading a full disk page and copy to that instead
|
|
435
466
|
return new Promise((resolve, reject) => {
|
|
436
|
-
const slab =
|
|
467
|
+
const slab = b4a.allocUnsafe(40 * this.flushing.size)
|
|
437
468
|
|
|
438
469
|
let error = null
|
|
439
470
|
let missing = this.flushing.size + 1
|
|
440
471
|
let offset = 0
|
|
441
472
|
|
|
442
473
|
for (const node of this.flushing.values()) {
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
474
|
+
const state = {
|
|
475
|
+
start: 0,
|
|
476
|
+
end: 40,
|
|
477
|
+
buffer: slab.subarray(offset, offset += 40)
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
c.uint64.encode(state, node.size)
|
|
481
|
+
c.raw.encode(state, node.hash)
|
|
482
|
+
|
|
483
|
+
this.storage.write(node.index * 40, state.buffer, done)
|
|
447
484
|
}
|
|
448
485
|
|
|
449
486
|
done(null)
|
|
@@ -510,8 +547,8 @@ module.exports = class MerkleTree {
|
|
|
510
547
|
|
|
511
548
|
let unverified = null
|
|
512
549
|
|
|
513
|
-
if (proof.block || proof.seek) {
|
|
514
|
-
unverified =
|
|
550
|
+
if (proof.block || proof.hash || proof.seek) {
|
|
551
|
+
unverified = verifyTree(proof, this.crypto, batch.nodes)
|
|
515
552
|
}
|
|
516
553
|
|
|
517
554
|
if (!verifyUpgrade(proof, unverified, batch)) {
|
|
@@ -520,7 +557,7 @@ module.exports = class MerkleTree {
|
|
|
520
557
|
|
|
521
558
|
for (const root of batch.roots) {
|
|
522
559
|
const existing = await this.get(root.index, false)
|
|
523
|
-
if (existing && existing.hash
|
|
560
|
+
if (existing && b4a.equals(existing.hash, root.hash)) continue
|
|
524
561
|
batch._updateDiffRoot(root)
|
|
525
562
|
break
|
|
526
563
|
}
|
|
@@ -538,7 +575,7 @@ module.exports = class MerkleTree {
|
|
|
538
575
|
async verify (proof) {
|
|
539
576
|
const batch = new MerkleTreeBatch(this)
|
|
540
577
|
|
|
541
|
-
let unverified =
|
|
578
|
+
let unverified = verifyTree(proof, this.crypto, batch.nodes)
|
|
542
579
|
|
|
543
580
|
if (proof.upgrade) {
|
|
544
581
|
if (verifyUpgrade(proof, unverified, batch)) {
|
|
@@ -548,7 +585,7 @@ module.exports = class MerkleTree {
|
|
|
548
585
|
|
|
549
586
|
if (unverified) {
|
|
550
587
|
const verified = await this.get(unverified.index)
|
|
551
|
-
if (!verified.hash
|
|
588
|
+
if (!b4a.equals(verified.hash, unverified.hash)) {
|
|
552
589
|
throw new Error('Invalid checksum at node ' + unverified.index)
|
|
553
590
|
}
|
|
554
591
|
}
|
|
@@ -556,89 +593,102 @@ module.exports = class MerkleTree {
|
|
|
556
593
|
return batch
|
|
557
594
|
}
|
|
558
595
|
|
|
559
|
-
async proof ({ block, seek, upgrade }) {
|
|
596
|
+
async proof ({ block, hash, seek, upgrade }) {
|
|
560
597
|
// Important that this does not throw inbetween making the promise arrays
|
|
561
598
|
// and finalise being called, otherwise there will be lingering promises in the background
|
|
562
599
|
|
|
563
|
-
const signature = this.signature
|
|
564
600
|
const fork = this.fork
|
|
601
|
+
const signature = this.signature
|
|
565
602
|
const head = 2 * this.length
|
|
566
603
|
const from = upgrade ? upgrade.start * 2 : 0
|
|
567
604
|
const to = upgrade ? from + upgrade.length * 2 : head
|
|
605
|
+
const node = normalizeIndexed(block, hash)
|
|
568
606
|
|
|
569
607
|
if (from >= to || to > head) {
|
|
570
608
|
throw new Error('Invalid upgrade')
|
|
571
609
|
}
|
|
572
|
-
if (seek &&
|
|
573
|
-
throw new Error('Cannot both do a seek and block request when upgrading')
|
|
610
|
+
if (seek && upgrade && node !== null && node.index >= from) {
|
|
611
|
+
throw new Error('Cannot both do a seek and block/hash request when upgrading')
|
|
574
612
|
}
|
|
575
613
|
|
|
576
614
|
let subTree = head
|
|
577
615
|
|
|
578
616
|
const p = {
|
|
579
|
-
|
|
617
|
+
node: null,
|
|
580
618
|
seek: null,
|
|
581
619
|
upgrade: null,
|
|
582
620
|
additionalUpgrade: null
|
|
583
621
|
}
|
|
584
622
|
|
|
585
|
-
if (
|
|
586
|
-
subTree = nodesToRoot(
|
|
623
|
+
if (node !== null && (!upgrade || node.lastIndex < upgrade.start)) {
|
|
624
|
+
subTree = nodesToRoot(node.index, node.nodes, to)
|
|
587
625
|
const seekRoot = seek ? await seekUntrustedTree(this, subTree, seek.bytes) : head
|
|
588
|
-
blockAndSeekProof(this,
|
|
589
|
-
} else if ((
|
|
590
|
-
subTree = seek ? await seekFromHead(this, to, seek.bytes) :
|
|
626
|
+
blockAndSeekProof(this, node, seek, seekRoot, subTree, p)
|
|
627
|
+
} else if ((node || seek) && upgrade) {
|
|
628
|
+
subTree = seek ? await seekFromHead(this, to, seek.bytes) : node.index
|
|
591
629
|
}
|
|
592
630
|
|
|
593
631
|
if (upgrade) {
|
|
594
|
-
upgradeProof(this,
|
|
632
|
+
upgradeProof(this, node, seek, from, to, subTree, p)
|
|
595
633
|
if (head > to) additionalUpgradeProof(this, to, head, p)
|
|
596
634
|
}
|
|
597
635
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
if (block) {
|
|
602
|
-
const nodes = await Promise.all(p.block)
|
|
636
|
+
const [pNode, pSeek, pUpgrade, pAdditional] = await settleProof(p)
|
|
637
|
+
const result = { fork, block: null, hash: null, seek: null, upgrade: null }
|
|
603
638
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
639
|
+
if (block) {
|
|
640
|
+
result.block = {
|
|
641
|
+
index: block.index,
|
|
642
|
+
value: null, // populated upstream, alloc it here for simplicity
|
|
643
|
+
nodes: pNode
|
|
609
644
|
}
|
|
610
|
-
|
|
611
|
-
|
|
645
|
+
} else if (hash) {
|
|
646
|
+
result.hash = {
|
|
647
|
+
index: hash.index,
|
|
648
|
+
nodes: pNode
|
|
649
|
+
}
|
|
650
|
+
}
|
|
612
651
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
652
|
+
if (seek && pSeek !== null) {
|
|
653
|
+
result.seek = {
|
|
654
|
+
bytes: seek.bytes,
|
|
655
|
+
nodes: pSeek
|
|
617
656
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
signature
|
|
628
|
-
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
if (upgrade) {
|
|
660
|
+
result.upgrade = {
|
|
661
|
+
start: upgrade.start,
|
|
662
|
+
length: upgrade.length,
|
|
663
|
+
nodes: pUpgrade,
|
|
664
|
+
additionalNodes: pAdditional || [],
|
|
665
|
+
signature
|
|
629
666
|
}
|
|
667
|
+
}
|
|
630
668
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
669
|
+
return result
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// Successor to .nodes()
|
|
673
|
+
async missingNodes (index) {
|
|
674
|
+
const head = 2 * this.length
|
|
675
|
+
const ite = flat.iterator(index)
|
|
676
|
+
|
|
677
|
+
// See iterator.rightSpan()
|
|
678
|
+
const iteRightSpan = ite.index + ite.factor / 2 - 1
|
|
679
|
+
// If the index is not in the current tree, we do not know how many missing nodes there are...
|
|
680
|
+
if (iteRightSpan >= head) return 0
|
|
681
|
+
|
|
682
|
+
let cnt = 0
|
|
683
|
+
while (!ite.contains(head) && (await this.get(ite.index, false)) === null) {
|
|
684
|
+
cnt++
|
|
685
|
+
ite.parent()
|
|
639
686
|
}
|
|
687
|
+
|
|
688
|
+
return cnt
|
|
640
689
|
}
|
|
641
690
|
|
|
691
|
+
// Deprecated
|
|
642
692
|
async nodes (index) {
|
|
643
693
|
const head = 2 * this.length
|
|
644
694
|
const ite = flat.iterator(index)
|
|
@@ -693,7 +743,7 @@ module.exports = class MerkleTree {
|
|
|
693
743
|
await new Promise((resolve, reject) => {
|
|
694
744
|
storage.read(0, OLD_TREE.length, (err, buf) => {
|
|
695
745
|
if (err) return resolve()
|
|
696
|
-
if (
|
|
746
|
+
if (b4a.equals(buf, OLD_TREE)) return reject(new Error('Storage contains an incompatible merkle tree'))
|
|
697
747
|
resolve()
|
|
698
748
|
})
|
|
699
749
|
})
|
|
@@ -713,8 +763,14 @@ module.exports = class MerkleTree {
|
|
|
713
763
|
|
|
714
764
|
// All the methods needed for proof verification
|
|
715
765
|
|
|
716
|
-
function
|
|
717
|
-
|
|
766
|
+
function verifyTree ({ block, hash, seek }, crypto, nodes) {
|
|
767
|
+
const untrustedNode = block
|
|
768
|
+
? { index: 2 * block.index, value: block.value, nodes: block.nodes }
|
|
769
|
+
: hash
|
|
770
|
+
? { index: hash.index, value: null, nodes: hash.nodes }
|
|
771
|
+
: null
|
|
772
|
+
|
|
773
|
+
if (untrustedNode === null && (!seek || !seek.nodes.length)) return null
|
|
718
774
|
|
|
719
775
|
let root = null
|
|
720
776
|
|
|
@@ -734,12 +790,12 @@ function verifyBlock ({ block, seek }, crypto, nodes) {
|
|
|
734
790
|
}
|
|
735
791
|
}
|
|
736
792
|
|
|
737
|
-
if (
|
|
793
|
+
if (untrustedNode === null) return root
|
|
738
794
|
|
|
739
|
-
const ite = flat.iterator(
|
|
740
|
-
const blockHash =
|
|
795
|
+
const ite = flat.iterator(untrustedNode.index)
|
|
796
|
+
const blockHash = untrustedNode.value && blockNode(crypto, ite.index, untrustedNode.value)
|
|
741
797
|
|
|
742
|
-
const q = new NodeQueue(
|
|
798
|
+
const q = new NodeQueue(untrustedNode.nodes, root)
|
|
743
799
|
|
|
744
800
|
root = blockHash || q.shift(ite.index)
|
|
745
801
|
nodes.push(root)
|
|
@@ -888,13 +944,13 @@ function seekProof (tree, seekRoot, root, p) {
|
|
|
888
944
|
}
|
|
889
945
|
}
|
|
890
946
|
|
|
891
|
-
function blockAndSeekProof (tree,
|
|
892
|
-
if (!
|
|
947
|
+
function blockAndSeekProof (tree, node, seek, seekRoot, root, p) {
|
|
948
|
+
if (!node) return seekProof(tree, seekRoot, root, p)
|
|
893
949
|
|
|
894
|
-
const ite = flat.iterator(
|
|
950
|
+
const ite = flat.iterator(node.index)
|
|
895
951
|
|
|
896
|
-
p.
|
|
897
|
-
if (!
|
|
952
|
+
p.node = []
|
|
953
|
+
if (!node.value) p.node.push(tree.get(ite.index))
|
|
898
954
|
|
|
899
955
|
while (ite.index !== root) {
|
|
900
956
|
ite.sibling()
|
|
@@ -902,14 +958,14 @@ function blockAndSeekProof (tree, block, seek, seekRoot, root, p) {
|
|
|
902
958
|
if (seek && ite.contains(seekRoot) && ite.index !== seekRoot) {
|
|
903
959
|
seekProof(tree, seekRoot, ite.index, p)
|
|
904
960
|
} else {
|
|
905
|
-
p.
|
|
961
|
+
p.node.push(tree.get(ite.index))
|
|
906
962
|
}
|
|
907
963
|
|
|
908
964
|
ite.parent()
|
|
909
965
|
}
|
|
910
966
|
}
|
|
911
967
|
|
|
912
|
-
function upgradeProof (tree,
|
|
968
|
+
function upgradeProof (tree, node, seek, from, to, subTree, p) {
|
|
913
969
|
if (from === 0) p.upgrade = []
|
|
914
970
|
|
|
915
971
|
for (const ite = flat.iterator(0); ite.fullRoot(to); ite.nextTree()) {
|
|
@@ -928,8 +984,8 @@ function upgradeProof (tree, block, seek, from, to, subTree, p) {
|
|
|
928
984
|
while (ite.index !== root) {
|
|
929
985
|
ite.sibling()
|
|
930
986
|
if (ite.index > target) {
|
|
931
|
-
if (p.
|
|
932
|
-
blockAndSeekProof(tree,
|
|
987
|
+
if (p.node === null && p.seek === null && ite.contains(subTree)) {
|
|
988
|
+
blockAndSeekProof(tree, node, seek, subTree, ite.index, p)
|
|
933
989
|
} else {
|
|
934
990
|
p.upgrade.push(tree.get(ite.index))
|
|
935
991
|
}
|
|
@@ -946,8 +1002,8 @@ function upgradeProof (tree, block, seek, from, to, subTree, p) {
|
|
|
946
1002
|
|
|
947
1003
|
// if the subtree included is a child of this tree, include that one
|
|
948
1004
|
// instead of a dup node
|
|
949
|
-
if (p.
|
|
950
|
-
blockAndSeekProof(tree,
|
|
1005
|
+
if (p.node === null && p.seek === null && ite.contains(subTree)) {
|
|
1006
|
+
blockAndSeekProof(tree, node, seek, subTree, ite.index, p)
|
|
951
1007
|
continue
|
|
952
1008
|
}
|
|
953
1009
|
|
|
@@ -1038,10 +1094,10 @@ function getStoredNode (storage, index, error) {
|
|
|
1038
1094
|
return
|
|
1039
1095
|
}
|
|
1040
1096
|
|
|
1041
|
-
const hash = data.
|
|
1042
|
-
const size =
|
|
1097
|
+
const hash = data.subarray(8)
|
|
1098
|
+
const size = c.decode(c.uint64, data)
|
|
1043
1099
|
|
|
1044
|
-
if (size === 0 &&
|
|
1100
|
+
if (size === 0 && b4a.compare(hash, BLANK_HASH) === 0) {
|
|
1045
1101
|
if (error) reject(new Error('Could not load node: ' + index))
|
|
1046
1102
|
else resolve(null)
|
|
1047
1103
|
return
|
|
@@ -1087,10 +1143,27 @@ function log2 (n) {
|
|
|
1087
1143
|
return res
|
|
1088
1144
|
}
|
|
1089
1145
|
|
|
1090
|
-
function
|
|
1091
|
-
|
|
1092
|
-
hash.
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1146
|
+
function normalizeIndexed (block, hash) {
|
|
1147
|
+
if (block) return { value: true, index: block.index * 2, nodes: block.nodes, lastIndex: block.index }
|
|
1148
|
+
if (hash) return { value: false, index: hash.index, nodes: hash.nodes, lastIndex: flat.rightSpan(hash.index) / 2 }
|
|
1149
|
+
return null
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
async function settleProof (p) {
|
|
1153
|
+
const result = [
|
|
1154
|
+
p.node && Promise.all(p.node),
|
|
1155
|
+
p.seek && Promise.all(p.seek),
|
|
1156
|
+
p.upgrade && Promise.all(p.upgrade),
|
|
1157
|
+
p.additionalUpgrade && Promise.all(p.additionalUpgrade)
|
|
1158
|
+
]
|
|
1159
|
+
|
|
1160
|
+
try {
|
|
1161
|
+
return await Promise.all(result)
|
|
1162
|
+
} catch (err) {
|
|
1163
|
+
if (p.node) await Promise.allSettled(p.node)
|
|
1164
|
+
if (p.seek) await Promise.allSettled(p.seek)
|
|
1165
|
+
if (p.upgrade) await Promise.allSettled(p.upgrade)
|
|
1166
|
+
if (p.additionalUpgrade) await Promise.allSettled(p.additionalUpgrade)
|
|
1167
|
+
throw err
|
|
1168
|
+
}
|
|
1096
1169
|
}
|