hypercore 10.20.0 → 10.20.2
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 +1 -0
- package/lib/core.js +22 -13
- package/lib/merkle-tree.js +1 -0
- package/lib/oplog.js +2 -1
- package/lib/replicator.js +6 -2
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -840,6 +840,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
840
840
|
const cleared = (opts && opts.diff) ? { blocks: 0 } : null
|
|
841
841
|
|
|
842
842
|
if (start >= end) return cleared
|
|
843
|
+
if (start >= this.length) return cleared
|
|
843
844
|
|
|
844
845
|
await this.core.clear(start, end, cleared)
|
|
845
846
|
|
package/lib/core.js
CHANGED
|
@@ -22,6 +22,7 @@ module.exports = class Core {
|
|
|
22
22
|
this.bitfield = bitfield
|
|
23
23
|
this.defaultAuth = auth
|
|
24
24
|
this.truncating = 0
|
|
25
|
+
this.closed = false
|
|
25
26
|
|
|
26
27
|
this._maxOplogSize = 65536
|
|
27
28
|
this._autoFlush = 1
|
|
@@ -222,7 +223,7 @@ module.exports = class Core {
|
|
|
222
223
|
|
|
223
224
|
this.tree.signature = signature || auth.sign(this.tree.signable())
|
|
224
225
|
|
|
225
|
-
if (signature && !this.
|
|
226
|
+
if (signature && !this._verifyBatch(this.tree)) {
|
|
226
227
|
// TODO: how to handle signature failure?
|
|
227
228
|
this.tree.signature = null
|
|
228
229
|
throw INVALID_SIGNATURE('Clone was provided with an invalid signature')
|
|
@@ -335,8 +336,8 @@ module.exports = class Core {
|
|
|
335
336
|
if (start >= end || start >= this.tree.length) return
|
|
336
337
|
|
|
337
338
|
const offset = await this.tree.byteOffset(start * 2)
|
|
338
|
-
const
|
|
339
|
-
const length =
|
|
339
|
+
const endOffset = await this.tree.byteOffset(end * 2)
|
|
340
|
+
const length = endOffset - offset
|
|
340
341
|
|
|
341
342
|
const before = cleared ? await Info.bytesUsed(this.blocks.storage) : null
|
|
342
343
|
|
|
@@ -422,17 +423,18 @@ module.exports = class Core {
|
|
|
422
423
|
}
|
|
423
424
|
}
|
|
424
425
|
|
|
425
|
-
|
|
426
|
+
_verifyBatch (batch) {
|
|
427
|
+
const hash = batch.hash()
|
|
426
428
|
const signable = this._legacy ? batch.signableLegacy(hash) : batch.signable(hash)
|
|
427
|
-
|
|
428
|
-
}
|
|
429
|
+
const auth = this.defaultAuth
|
|
429
430
|
|
|
430
|
-
|
|
431
|
-
// TODO: move this to tree.js
|
|
432
|
-
const hash = batch.hash()
|
|
433
|
-
if (!batch.signature || !this._signed(batch, hash)) {
|
|
431
|
+
if (!batch.signature || !auth.verify(signable, batch.signature, batch)) {
|
|
434
432
|
throw INVALID_SIGNATURE('Proof contains an invalid signature')
|
|
435
433
|
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
async _verifyExclusive ({ batch, bitfield, value, from }) {
|
|
437
|
+
this._verifyBatch(batch)
|
|
436
438
|
|
|
437
439
|
await this._mutex.lock()
|
|
438
440
|
|
|
@@ -540,9 +542,7 @@ module.exports = class Core {
|
|
|
540
542
|
|
|
541
543
|
const batch = this.tree.verifyFullyRemote(proof)
|
|
542
544
|
|
|
543
|
-
|
|
544
|
-
throw INVALID_SIGNATURE('Proof contains an invalid signature with no input from us')
|
|
545
|
-
}
|
|
545
|
+
this._verifyBatch(batch)
|
|
546
546
|
|
|
547
547
|
const remoteTreeHash = this.crypto.tree(proof.upgrade.nodes)
|
|
548
548
|
const localTreeHash = this.crypto.tree(await this.tree.getRoots(proof.upgrade.length))
|
|
@@ -553,6 +553,14 @@ module.exports = class Core {
|
|
|
553
553
|
return true
|
|
554
554
|
}
|
|
555
555
|
|
|
556
|
+
async verifyReorg (proof) {
|
|
557
|
+
const batch = await this.tree.reorg(proof)
|
|
558
|
+
|
|
559
|
+
this._verifyBatch(batch)
|
|
560
|
+
|
|
561
|
+
return batch
|
|
562
|
+
}
|
|
563
|
+
|
|
556
564
|
async verify (proof, from) {
|
|
557
565
|
// We cannot apply "other forks" atm.
|
|
558
566
|
// We should probably still try and they are likely super similar for non upgrades
|
|
@@ -639,6 +647,7 @@ module.exports = class Core {
|
|
|
639
647
|
}
|
|
640
648
|
|
|
641
649
|
async close () {
|
|
650
|
+
this.closed = true
|
|
642
651
|
await this._mutex.destroy()
|
|
643
652
|
await Promise.allSettled([
|
|
644
653
|
this.oplog.close(),
|
package/lib/merkle-tree.js
CHANGED
package/lib/oplog.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const cenc = require('compact-encoding')
|
|
2
2
|
const b4a = require('b4a')
|
|
3
3
|
const { crc32 } = require('crc-universal')
|
|
4
|
-
const { OPLOG_CORRUPT } = require('hypercore-errors')
|
|
4
|
+
const { OPLOG_CORRUPT, OPLOG_HEADER_OVERFLOW } = require('hypercore-errors')
|
|
5
5
|
|
|
6
6
|
module.exports = class Oplog {
|
|
7
7
|
constructor (storage, { pageSize = 4096, headerEncoding = cenc.raw, entryEncoding = cenc.raw, readonly = false } = {}) {
|
|
@@ -155,6 +155,7 @@ module.exports = class Oplog {
|
|
|
155
155
|
const bit = (this._headers[i] + 1) & 1
|
|
156
156
|
|
|
157
157
|
this.headerEncoding.preencode(state, header)
|
|
158
|
+
if (state.end > this._pageSize) throw OPLOG_HEADER_OVERFLOW()
|
|
158
159
|
state.buffer = b4a.allocUnsafe(state.end)
|
|
159
160
|
this.headerEncoding.encode(state, header)
|
|
160
161
|
this._addHeader(state, state.end - 8, bit, 0)
|
package/lib/replicator.js
CHANGED
|
@@ -560,6 +560,7 @@ class Peer {
|
|
|
560
560
|
proof = await this._getProof(msg)
|
|
561
561
|
} catch (err) { // TODO: better error handling here, ie custom errors
|
|
562
562
|
safetyCatch(err)
|
|
563
|
+
if (this.replicator.core.closed) throw err // just an extra safety check...
|
|
563
564
|
}
|
|
564
565
|
}
|
|
565
566
|
|
|
@@ -1004,6 +1005,7 @@ module.exports = class Replicator {
|
|
|
1004
1005
|
this.onupload = onupload
|
|
1005
1006
|
this.peers = []
|
|
1006
1007
|
this.findingPeers = 0 // updateable from the outside
|
|
1008
|
+
this.destroyed = false
|
|
1007
1009
|
|
|
1008
1010
|
this._attached = new Set()
|
|
1009
1011
|
this._inflight = new InflightTracker()
|
|
@@ -1524,6 +1526,7 @@ module.exports = class Replicator {
|
|
|
1524
1526
|
}
|
|
1525
1527
|
|
|
1526
1528
|
async _onreorgdata (peer, req, data) {
|
|
1529
|
+
const newBatch = data.upgrade && await this.core.verifyReorg(data)
|
|
1527
1530
|
const f = this._addReorg(data.fork, peer)
|
|
1528
1531
|
|
|
1529
1532
|
if (f === null) {
|
|
@@ -1536,7 +1539,7 @@ module.exports = class Replicator {
|
|
|
1536
1539
|
if (f.batch) {
|
|
1537
1540
|
await f.batch.update(data)
|
|
1538
1541
|
} else if (data.upgrade) {
|
|
1539
|
-
f.batch =
|
|
1542
|
+
f.batch = newBatch
|
|
1540
1543
|
|
|
1541
1544
|
// Remove "older" reorgs in progress as we just verified this one.
|
|
1542
1545
|
this._clearOldReorgs(f.fork)
|
|
@@ -1711,7 +1714,7 @@ module.exports = class Replicator {
|
|
|
1711
1714
|
protomux.stream.opened.then((opened) => {
|
|
1712
1715
|
this._ifAvailable--
|
|
1713
1716
|
|
|
1714
|
-
if (opened) makePeer()
|
|
1717
|
+
if (opened && !this.destroyed) makePeer()
|
|
1715
1718
|
else if (session) session.close().catch(noop)
|
|
1716
1719
|
this._checkUpgradeIfAvailable()
|
|
1717
1720
|
})
|
|
@@ -1725,6 +1728,7 @@ module.exports = class Replicator {
|
|
|
1725
1728
|
}
|
|
1726
1729
|
|
|
1727
1730
|
destroy () {
|
|
1731
|
+
this.destroyed = true
|
|
1728
1732
|
for (const peer of this.peers) {
|
|
1729
1733
|
this.detachFrom(peer.protomux)
|
|
1730
1734
|
peer.channel.close()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hypercore",
|
|
3
|
-
"version": "10.20.
|
|
3
|
+
"version": "10.20.2",
|
|
4
4
|
"description": "Hypercore is a secure, distributed append-only log",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"fast-fifo": "^1.3.0",
|
|
45
45
|
"flat-tree": "^1.9.0",
|
|
46
46
|
"hypercore-crypto": "^3.2.1",
|
|
47
|
-
"hypercore-errors": "^1.
|
|
47
|
+
"hypercore-errors": "^1.1.0",
|
|
48
48
|
"is-options": "^1.0.1",
|
|
49
49
|
"protomux": "^3.5.0",
|
|
50
50
|
"quickbit-universal": "^2.1.1",
|