hypercore 10.24.1 → 10.24.3
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 +5 -2
- package/lib/batch.js +66 -13
- package/lib/core.js +3 -3
- package/lib/merkle-tree.js +4 -4
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -135,7 +135,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
static key (manifest, { compat } = {}) {
|
|
138
|
-
return compat ? manifest.signer.publicKey : manifestHash(manifest)
|
|
138
|
+
return compat ? manifest.signer.publicKey : manifestHash(createManifest(manifest))
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
static discoveryKey (key) {
|
|
@@ -960,6 +960,9 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
960
960
|
async append (blocks, opts = {}) {
|
|
961
961
|
if (this._batch && this !== this._batch.session) throw BATCH_UNFLUSHED()
|
|
962
962
|
|
|
963
|
+
// if a batched append, run unlocked as it already locked...
|
|
964
|
+
const lock = !this._batch
|
|
965
|
+
|
|
963
966
|
if (this.opened === false) await this.opening
|
|
964
967
|
|
|
965
968
|
const { keyPair = this.keyPair, signature = null } = opts
|
|
@@ -979,7 +982,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
979
982
|
}
|
|
980
983
|
}
|
|
981
984
|
|
|
982
|
-
return this.core.append(buffers, { keyPair, signature, preappend })
|
|
985
|
+
return this.core.append(buffers, { lock, keyPair, signature, preappend })
|
|
983
986
|
}
|
|
984
987
|
|
|
985
988
|
async treeHash (length) {
|
package/lib/batch.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { BLOCK_NOT_AVAILABLE, SESSION_CLOSED } = require('hypercore-errors')
|
|
2
2
|
const EventEmitter = require('events')
|
|
3
3
|
const c = require('compact-encoding')
|
|
4
|
+
const b4a = require('b4a')
|
|
4
5
|
|
|
5
6
|
module.exports = class HypercoreBatch extends EventEmitter {
|
|
6
7
|
constructor (session, autoClose) {
|
|
@@ -19,6 +20,7 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
19
20
|
this._byteLength = 0
|
|
20
21
|
this._sessionLength = 0
|
|
21
22
|
this._sessionByteLength = 0
|
|
23
|
+
this._sessionBatch = null
|
|
22
24
|
this._flushing = null
|
|
23
25
|
|
|
24
26
|
this.opening = this.ready().catch(noop)
|
|
@@ -65,6 +67,7 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
65
67
|
if (this.opened) return
|
|
66
68
|
this._sessionLength = this.session.length
|
|
67
69
|
this._sessionByteLength = this.session.byteLength
|
|
70
|
+
this._sessionBatch = this.session.createTreeBatch()
|
|
68
71
|
this.fork = this.session.fork
|
|
69
72
|
this.opened = true
|
|
70
73
|
this.emit('ready')
|
|
@@ -73,6 +76,7 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
73
76
|
async update (opts) {
|
|
74
77
|
if (this.opened === false) await this.ready()
|
|
75
78
|
await this.session.update(opts)
|
|
79
|
+
await this._catchup()
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
setUserData (key, value, opts) {
|
|
@@ -149,7 +153,7 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
149
153
|
if (!length && length !== 0) length = this.length + blocks.length
|
|
150
154
|
|
|
151
155
|
const maxLength = this.length + blocks.length
|
|
152
|
-
const b = this.
|
|
156
|
+
const b = this._sessionBatch.clone()
|
|
153
157
|
const len = Math.min(length, this.length)
|
|
154
158
|
|
|
155
159
|
if (len < this._sessionLength || length > maxLength) return null
|
|
@@ -185,6 +189,7 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
185
189
|
await this.session.truncate(newLength, { fork, force: true, ...opts })
|
|
186
190
|
this._sessionLength = this.session.length
|
|
187
191
|
this._sessionByteLength = this.session.byteLength
|
|
192
|
+
this._sessionBatch = this.session.createTreeBatch()
|
|
188
193
|
} else {
|
|
189
194
|
for (let i = newLength - length; i < this._appends.length; i++) this._byteLength -= this._appends[i].byteLength
|
|
190
195
|
this._appends.length = newLength - length
|
|
@@ -230,34 +235,82 @@ module.exports = class HypercoreBatch extends EventEmitter {
|
|
|
230
235
|
if (this.opened === false) await this.opening
|
|
231
236
|
if (this.closing) throw SESSION_CLOSED()
|
|
232
237
|
|
|
233
|
-
const { length = this.
|
|
238
|
+
const { length = this.length, keyPair = this.session.keyPair, signature = null } = opts
|
|
234
239
|
|
|
235
240
|
while (this._flushing) await this._flushing
|
|
236
241
|
this._flushing = this._flush(length, keyPair, signature)
|
|
237
242
|
|
|
243
|
+
let flushed = false
|
|
244
|
+
|
|
238
245
|
try {
|
|
239
|
-
await this._flushing
|
|
246
|
+
flushed = await this._flushing
|
|
240
247
|
} finally {
|
|
241
248
|
this._flushing = null
|
|
242
249
|
}
|
|
243
250
|
|
|
244
251
|
if (this.autoClose) await this.close()
|
|
252
|
+
|
|
253
|
+
return flushed
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async _catchup () {
|
|
257
|
+
if (this.core.tree.length === this._sessionLength) return true
|
|
258
|
+
|
|
259
|
+
const batchLength = this._sessionLength + this._appends.length
|
|
260
|
+
|
|
261
|
+
if (this.core.tree.length > batchLength) return false
|
|
262
|
+
|
|
263
|
+
const b = this.createTreeBatch()
|
|
264
|
+
|
|
265
|
+
for (const root of this.core.tree.roots) {
|
|
266
|
+
const batchRoot = await b.get(root.index)
|
|
267
|
+
|
|
268
|
+
if (batchRoot === null) continue // in the shared tree
|
|
269
|
+
if (batchRoot.size !== root.size || !b4a.equals(batchRoot.hash, root.hash)) {
|
|
270
|
+
// TODO: type this error
|
|
271
|
+
throw new Error('Batch is uncommitable due to a conflict at ' + root.index)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const offset = this._sessionLength + this._appends.length - this.core.tree.length
|
|
276
|
+
for (let i = 0; i < offset; i++) this._byteLength -= this._appends[i]
|
|
277
|
+
|
|
278
|
+
this._sessionLength = this.session.length
|
|
279
|
+
this._sessionByteLength = this.session.byteLength
|
|
280
|
+
this._sessionBatch = this.session.createTreeBatch()
|
|
281
|
+
this._appends = this._appends.slice(this._appends.length - offset)
|
|
282
|
+
|
|
283
|
+
return true
|
|
245
284
|
}
|
|
246
285
|
|
|
247
286
|
async _flush (length, keyPair, signature) { // TODO: make this safe to interact with a parallel truncate...
|
|
248
|
-
if (this._appends.length === 0) return
|
|
287
|
+
if (this._appends.length === 0) return true
|
|
288
|
+
if (!(await this._catchup())) return false
|
|
289
|
+
|
|
290
|
+
await this.core._mutex.lock()
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
const flushingLength = Math.min(length - this._sessionLength, this._appends.length)
|
|
294
|
+
if (flushingLength <= 0) return true
|
|
295
|
+
|
|
296
|
+
const blocks = flushingLength < this._appends.length ? this._appends.slice(0, flushingLength) : this._appends
|
|
297
|
+
|
|
298
|
+
const info = await this.session.append(blocks, { keyPair, signature })
|
|
299
|
+
const delta = info.byteLength - this._sessionByteLength
|
|
249
300
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
const delta = info.byteLength - this._sessionByteLength
|
|
301
|
+
this._sessionLength = info.length
|
|
302
|
+
this._sessionByteLength = info.byteLength
|
|
303
|
+
this._sessionBatch = this.session.createTreeBatch()
|
|
254
304
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
305
|
+
this._appends = this._appends.slice(flushingLength)
|
|
306
|
+
this._byteLength -= delta
|
|
307
|
+
|
|
308
|
+
this.emit('flush')
|
|
309
|
+
} finally {
|
|
310
|
+
this.core._mutex.unlock()
|
|
311
|
+
}
|
|
259
312
|
|
|
260
|
-
|
|
313
|
+
return true
|
|
261
314
|
}
|
|
262
315
|
|
|
263
316
|
close () {
|
package/lib/core.js
CHANGED
|
@@ -432,8 +432,8 @@ module.exports = class Core {
|
|
|
432
432
|
})
|
|
433
433
|
}
|
|
434
434
|
|
|
435
|
-
async append (values, { signature, keyPair = this.header.keyPair, preappend } = {}) {
|
|
436
|
-
await this._mutex.lock()
|
|
435
|
+
async append (values, { lock, signature, keyPair = this.header.keyPair, preappend } = {}) {
|
|
436
|
+
if (lock) await this._mutex.lock()
|
|
437
437
|
|
|
438
438
|
// upsert compat manifest
|
|
439
439
|
if (this.verifier === null && keyPair) this.setManifest(null, keyPair)
|
|
@@ -479,7 +479,7 @@ module.exports = class Core {
|
|
|
479
479
|
|
|
480
480
|
return { length: batch.length, byteLength }
|
|
481
481
|
} finally {
|
|
482
|
-
this._mutex.unlock()
|
|
482
|
+
if (lock) this._mutex.unlock()
|
|
483
483
|
}
|
|
484
484
|
}
|
|
485
485
|
|
package/lib/merkle-tree.js
CHANGED
|
@@ -92,14 +92,14 @@ class MerkleTreeBatch {
|
|
|
92
92
|
return null
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
if (index < this.treeLength * 2) {
|
|
96
|
-
return this.tree.get(index)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
95
|
for (const n of this.nodes) {
|
|
100
96
|
if (n.index === index) return n
|
|
101
97
|
}
|
|
102
98
|
|
|
99
|
+
if (index < this.treeLength * 2) {
|
|
100
|
+
return this.tree.get(index)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
103
|
return null
|
|
104
104
|
}
|
|
105
105
|
|