hypercore 10.0.0-alpha.9 → 10.2.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/README.md +154 -36
- package/index.js +579 -213
- package/lib/bitfield.js +110 -42
- package/lib/block-encryption.js +3 -2
- package/lib/block-store.js +10 -5
- package/lib/caps.js +32 -0
- package/lib/core.js +189 -47
- package/lib/download.js +22 -0
- package/lib/errors.js +50 -0
- package/lib/info.js +24 -0
- package/lib/merkle-tree.js +182 -106
- package/lib/messages.js +249 -168
- package/lib/oplog.js +6 -5
- package/lib/remote-bitfield.js +28 -7
- package/lib/replicator.js +1415 -624
- package/lib/streams.js +56 -0
- package/package.json +23 -16
- 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 -90
- package/test/bitfield.js +0 -71
- package/test/core.js +0 -290
- package/test/encodings.js +0 -18
- package/test/encryption.js +0 -121
- 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 -372
- package/test/sessions.js +0 -173
- package/test/user-data.js +0 -47
package/lib/core.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
const hypercoreCrypto = require('hypercore-crypto')
|
|
2
|
+
const b4a = require('b4a')
|
|
2
3
|
const Oplog = require('./oplog')
|
|
3
4
|
const Mutex = require('./mutex')
|
|
4
5
|
const MerkleTree = require('./merkle-tree')
|
|
5
6
|
const BlockStore = require('./block-store')
|
|
6
7
|
const Bitfield = require('./bitfield')
|
|
7
|
-
const {
|
|
8
|
+
const { BAD_ARGUMENT, STORAGE_EMPTY, STORAGE_CONFLICT, INVALID_SIGNATURE } = require('./errors')
|
|
9
|
+
const m = require('./messages')
|
|
8
10
|
|
|
9
11
|
module.exports = class Core {
|
|
10
|
-
constructor (header, crypto, oplog, tree, blocks, bitfield,
|
|
12
|
+
constructor (header, crypto, oplog, tree, blocks, bitfield, auth, legacy, onupdate) {
|
|
11
13
|
this.onupdate = onupdate
|
|
12
14
|
this.header = header
|
|
13
15
|
this.crypto = crypto
|
|
@@ -15,7 +17,7 @@ module.exports = class Core {
|
|
|
15
17
|
this.tree = tree
|
|
16
18
|
this.blocks = blocks
|
|
17
19
|
this.bitfield = bitfield
|
|
18
|
-
this.
|
|
20
|
+
this.defaultAuth = auth
|
|
19
21
|
this.truncating = 0
|
|
20
22
|
|
|
21
23
|
this._maxOplogSize = 65536
|
|
@@ -23,6 +25,7 @@ module.exports = class Core {
|
|
|
23
25
|
this._verifies = null
|
|
24
26
|
this._verifiesFlushed = null
|
|
25
27
|
this._mutex = new Mutex()
|
|
28
|
+
this._legacy = legacy
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
static async open (storage, opts = {}) {
|
|
@@ -34,42 +37,51 @@ module.exports = class Core {
|
|
|
34
37
|
try {
|
|
35
38
|
return await this.resume(oplogFile, treeFile, bitfieldFile, dataFile, opts)
|
|
36
39
|
} catch (err) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
oplogFile.close(done)
|
|
41
|
-
treeFile.close(done)
|
|
42
|
-
bitfieldFile.close(done)
|
|
43
|
-
dataFile.close(done)
|
|
44
|
-
|
|
45
|
-
function done () {
|
|
46
|
-
if (--missing === 0) reject(err)
|
|
47
|
-
}
|
|
48
|
-
})
|
|
40
|
+
await closeAll(oplogFile, treeFile, bitfieldFile, dataFile)
|
|
41
|
+
throw err
|
|
49
42
|
}
|
|
50
43
|
}
|
|
51
44
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
static createAuth (crypto, { publicKey, secretKey }, opts = {}) {
|
|
46
|
+
if (secretKey && !crypto.validateKeyPair({ publicKey, secretKey })) {
|
|
47
|
+
throw BAD_ARGUMENT('Invalid key pair')
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const sign = opts.sign
|
|
51
|
+
? opts.sign
|
|
52
|
+
: secretKey
|
|
53
|
+
? (signable) => crypto.sign(signable, secretKey)
|
|
54
|
+
: undefined
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
sign,
|
|
58
|
+
verify (signable, signature) {
|
|
59
|
+
return crypto.verify(signable, signature, publicKey)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
static async resume (oplogFile, treeFile, bitfieldFile, dataFile, opts) {
|
|
59
|
-
|
|
65
|
+
let overwrite = opts.overwrite === true
|
|
66
|
+
|
|
67
|
+
const force = opts.force === true
|
|
60
68
|
const createIfMissing = opts.createIfMissing !== false
|
|
61
69
|
const crypto = opts.crypto || hypercoreCrypto
|
|
62
70
|
|
|
63
71
|
const oplog = new Oplog(oplogFile, {
|
|
64
|
-
headerEncoding:
|
|
65
|
-
entryEncoding:
|
|
72
|
+
headerEncoding: m.oplog.header,
|
|
73
|
+
entryEncoding: m.oplog.entry
|
|
66
74
|
})
|
|
67
75
|
|
|
68
76
|
let { header, entries } = await oplog.open()
|
|
69
77
|
|
|
70
|
-
if (
|
|
78
|
+
if (force && opts.keyPair && header && header.signer && !b4a.equals(header.signer.publicKey, opts.keyPair.publicKey)) {
|
|
79
|
+
overwrite = true
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!header || overwrite) {
|
|
71
83
|
if (!createIfMissing) {
|
|
72
|
-
throw
|
|
84
|
+
throw STORAGE_EMPTY('No Hypercore is stored here')
|
|
73
85
|
}
|
|
74
86
|
|
|
75
87
|
header = {
|
|
@@ -84,14 +96,15 @@ module.exports = class Core {
|
|
|
84
96
|
signer: opts.keyPair || crypto.keyPair(),
|
|
85
97
|
hints: {
|
|
86
98
|
reorgs: []
|
|
87
|
-
}
|
|
99
|
+
},
|
|
100
|
+
contiguousLength: 0
|
|
88
101
|
}
|
|
89
102
|
|
|
90
103
|
await oplog.flush(header)
|
|
91
104
|
}
|
|
92
105
|
|
|
93
|
-
if (opts.keyPair && !header.signer.publicKey
|
|
94
|
-
throw
|
|
106
|
+
if (opts.keyPair && !b4a.equals(header.signer.publicKey, opts.keyPair.publicKey)) {
|
|
107
|
+
throw STORAGE_CONFLICT('Another Hypercore is stored here')
|
|
95
108
|
}
|
|
96
109
|
|
|
97
110
|
const tree = await MerkleTree.open(treeFile, { crypto, ...header.tree })
|
|
@@ -102,9 +115,18 @@ module.exports = class Core {
|
|
|
102
115
|
await tree.clear()
|
|
103
116
|
await blocks.clear()
|
|
104
117
|
await bitfield.clear()
|
|
118
|
+
entries = []
|
|
119
|
+
} else if (bitfield.resumed && header.tree.length === 0) {
|
|
120
|
+
// If this was an old bitfield, reset it since it loads based on disk size atm (TODO: change that)
|
|
121
|
+
await bitfield.clear()
|
|
105
122
|
}
|
|
106
123
|
|
|
107
|
-
|
|
124
|
+
// compat from earlier version that do not store contig length
|
|
125
|
+
if (header.contiguousLength === 0) {
|
|
126
|
+
while (bitfield.get(header.contiguousLength)) header.contiguousLength++
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const auth = opts.auth || this.createAuth(crypto, header.signer)
|
|
108
130
|
|
|
109
131
|
for (const e of entries) {
|
|
110
132
|
if (e.userData) {
|
|
@@ -118,7 +140,8 @@ module.exports = class Core {
|
|
|
118
140
|
}
|
|
119
141
|
|
|
120
142
|
if (e.bitfield) {
|
|
121
|
-
bitfield.setRange(e.bitfield.start, e.bitfield.length)
|
|
143
|
+
bitfield.setRange(e.bitfield.start, e.bitfield.length, !e.bitfield.drop)
|
|
144
|
+
updateContig(header, e.bitfield, bitfield)
|
|
122
145
|
}
|
|
123
146
|
|
|
124
147
|
if (e.treeUpgrade) {
|
|
@@ -135,7 +158,7 @@ module.exports = class Core {
|
|
|
135
158
|
}
|
|
136
159
|
}
|
|
137
160
|
|
|
138
|
-
return new this(header, crypto, oplog, tree, blocks, bitfield,
|
|
161
|
+
return new this(header, crypto, oplog, tree, blocks, bitfield, auth, !!opts.legacy, opts.onupdate || noop)
|
|
139
162
|
}
|
|
140
163
|
|
|
141
164
|
_shouldFlush () {
|
|
@@ -176,7 +199,7 @@ module.exports = class Core {
|
|
|
176
199
|
|
|
177
200
|
for (const u of this.header.userData) {
|
|
178
201
|
if (u.key !== key) continue
|
|
179
|
-
if (value &&
|
|
202
|
+
if (value && b4a.equals(u.value, value)) return
|
|
180
203
|
empty = false
|
|
181
204
|
break
|
|
182
205
|
}
|
|
@@ -200,13 +223,13 @@ module.exports = class Core {
|
|
|
200
223
|
}
|
|
201
224
|
}
|
|
202
225
|
|
|
203
|
-
async truncate (length, fork,
|
|
226
|
+
async truncate (length, fork, auth = this.defaultAuth) {
|
|
204
227
|
this.truncating++
|
|
205
228
|
await this._mutex.lock()
|
|
206
229
|
|
|
207
230
|
try {
|
|
208
231
|
const batch = await this.tree.truncate(length, fork)
|
|
209
|
-
batch.signature = await sign(batch.signable())
|
|
232
|
+
batch.signature = await auth.sign(batch.signable())
|
|
210
233
|
await this._truncate(batch, null)
|
|
211
234
|
} finally {
|
|
212
235
|
this.truncating--
|
|
@@ -214,19 +237,63 @@ module.exports = class Core {
|
|
|
214
237
|
}
|
|
215
238
|
}
|
|
216
239
|
|
|
217
|
-
async
|
|
240
|
+
async clear (start, end) {
|
|
241
|
+
await this._mutex.lock()
|
|
242
|
+
|
|
243
|
+
const entry = {
|
|
244
|
+
userData: null,
|
|
245
|
+
treeNodes: null,
|
|
246
|
+
treeUpgrade: null,
|
|
247
|
+
bitfield: {
|
|
248
|
+
start,
|
|
249
|
+
length: end - start,
|
|
250
|
+
drop: true
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
await this.oplog.append([entry], false)
|
|
255
|
+
|
|
256
|
+
this.bitfield.setRange(start, end - start, false)
|
|
257
|
+
|
|
258
|
+
if (start < this.header.contiguousLength) {
|
|
259
|
+
this.header.contiguousLength = start
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
start = this.bitfield.lastSet(start) + 1
|
|
263
|
+
end = this.bitfield.firstSet(end)
|
|
264
|
+
|
|
265
|
+
if (end === -1) end = this.tree.length
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
const offset = await this.tree.byteOffset(start * 2)
|
|
269
|
+
const [byteEnd, byteEndLength] = await this.tree.byteRange((end - 1) * 2)
|
|
270
|
+
const length = (byteEnd + byteEndLength) - offset
|
|
271
|
+
|
|
272
|
+
await this.blocks.clear(offset, length)
|
|
273
|
+
|
|
274
|
+
this.onupdate(0, entry.bitfield, null, null)
|
|
275
|
+
|
|
276
|
+
if (this._shouldFlush()) await this._flushOplog()
|
|
277
|
+
} finally {
|
|
278
|
+
this._mutex.unlock()
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async append (values, auth = this.defaultAuth, hooks = {}) {
|
|
218
283
|
await this._mutex.lock()
|
|
219
284
|
|
|
220
285
|
try {
|
|
221
286
|
if (hooks.preappend) await hooks.preappend(values)
|
|
222
287
|
|
|
223
|
-
if (!values.length)
|
|
288
|
+
if (!values.length) {
|
|
289
|
+
return { length: this.tree.length, byteLength: this.tree.byteLength }
|
|
290
|
+
}
|
|
224
291
|
|
|
225
292
|
const batch = this.tree.batch()
|
|
226
293
|
for (const val of values) batch.append(val)
|
|
227
294
|
|
|
228
295
|
const hash = batch.hash()
|
|
229
|
-
batch.signature = await sign(batch.signable(hash))
|
|
296
|
+
batch.signature = await auth.sign(this._legacy ? batch.signableLegacy(hash) : batch.signable(hash))
|
|
230
297
|
|
|
231
298
|
const entry = {
|
|
232
299
|
userData: null,
|
|
@@ -239,7 +306,8 @@ module.exports = class Core {
|
|
|
239
306
|
}
|
|
240
307
|
}
|
|
241
308
|
|
|
242
|
-
await this._appendBlocks(values)
|
|
309
|
+
const byteLength = await this._appendBlocks(values)
|
|
310
|
+
|
|
243
311
|
await this.oplog.append([entry], false)
|
|
244
312
|
|
|
245
313
|
this.bitfield.setRange(batch.ancestors, batch.length - batch.ancestors, true)
|
|
@@ -248,21 +316,28 @@ module.exports = class Core {
|
|
|
248
316
|
this.header.tree.length = batch.length
|
|
249
317
|
this.header.tree.rootHash = hash
|
|
250
318
|
this.header.tree.signature = batch.signature
|
|
251
|
-
|
|
319
|
+
|
|
320
|
+
const status = 0b0001 | updateContig(this.header, entry.bitfield, this.bitfield)
|
|
321
|
+
this.onupdate(status, entry.bitfield, null, null)
|
|
252
322
|
|
|
253
323
|
if (this._shouldFlush()) await this._flushOplog()
|
|
254
324
|
|
|
255
|
-
return batch.
|
|
325
|
+
return { length: batch.length, byteLength }
|
|
256
326
|
} finally {
|
|
257
327
|
this._mutex.unlock()
|
|
258
328
|
}
|
|
259
329
|
}
|
|
260
330
|
|
|
331
|
+
_signed (batch, hash, auth = this.defaultAuth) {
|
|
332
|
+
const signable = this._legacy ? batch.signableLegacy(hash) : batch.signable(hash)
|
|
333
|
+
return auth.verify(signable, batch.signature)
|
|
334
|
+
}
|
|
335
|
+
|
|
261
336
|
async _verifyExclusive ({ batch, bitfield, value, from }) {
|
|
262
337
|
// TODO: move this to tree.js
|
|
263
338
|
const hash = batch.hash()
|
|
264
|
-
if (!batch.signature || !this.
|
|
265
|
-
throw
|
|
339
|
+
if (!batch.signature || !this._signed(batch, hash)) {
|
|
340
|
+
throw INVALID_SIGNATURE('Proof contains an invalid signature')
|
|
266
341
|
}
|
|
267
342
|
|
|
268
343
|
await this._mutex.lock()
|
|
@@ -281,14 +356,21 @@ module.exports = class Core {
|
|
|
281
356
|
|
|
282
357
|
await this.oplog.append([entry], false)
|
|
283
358
|
|
|
284
|
-
|
|
359
|
+
let status = 0b0001
|
|
360
|
+
|
|
361
|
+
if (bitfield) {
|
|
362
|
+
this.bitfield.set(bitfield.start, true)
|
|
363
|
+
status |= updateContig(this.header, bitfield, this.bitfield)
|
|
364
|
+
}
|
|
365
|
+
|
|
285
366
|
batch.commit()
|
|
286
367
|
|
|
287
368
|
this.header.tree.fork = batch.fork
|
|
288
369
|
this.header.tree.length = batch.length
|
|
289
370
|
this.header.tree.rootHash = batch.rootHash
|
|
290
371
|
this.header.tree.signature = batch.signature
|
|
291
|
-
|
|
372
|
+
|
|
373
|
+
this.onupdate(status, bitfield, value, from)
|
|
292
374
|
|
|
293
375
|
if (this._shouldFlush()) await this._flushOplog()
|
|
294
376
|
} finally {
|
|
@@ -335,9 +417,16 @@ module.exports = class Core {
|
|
|
335
417
|
continue
|
|
336
418
|
}
|
|
337
419
|
|
|
338
|
-
|
|
420
|
+
let status = 0
|
|
421
|
+
|
|
422
|
+
if (bitfield) {
|
|
423
|
+
this.bitfield.set(bitfield.start, true)
|
|
424
|
+
status = updateContig(this.header, bitfield, this.bitfield)
|
|
425
|
+
}
|
|
426
|
+
|
|
339
427
|
batch.commit()
|
|
340
|
-
|
|
428
|
+
|
|
429
|
+
this.onupdate(status, bitfield, value, from)
|
|
341
430
|
}
|
|
342
431
|
|
|
343
432
|
if (this._shouldFlush()) await this._flushOplog()
|
|
@@ -415,13 +504,15 @@ module.exports = class Core {
|
|
|
415
504
|
addReorgHint(this.header.hints.reorgs, this.tree, batch)
|
|
416
505
|
batch.commit()
|
|
417
506
|
|
|
418
|
-
const
|
|
507
|
+
const contigStatus = updateContig(this.header, entry.bitfield, this.bitfield)
|
|
508
|
+
const status = ((batch.length > batch.ancestors) ? 0b0011 : 0b0010) | contigStatus
|
|
419
509
|
|
|
420
510
|
this.header.tree.fork = batch.fork
|
|
421
511
|
this.header.tree.length = batch.length
|
|
422
512
|
this.header.tree.rootHash = batch.hash()
|
|
423
513
|
this.header.tree.signature = batch.signature
|
|
424
|
-
|
|
514
|
+
|
|
515
|
+
this.onupdate(status, entry.bitfield, null, from)
|
|
425
516
|
|
|
426
517
|
// TODO: there is a bug in the merkle tree atm where it cannot handle unflushed
|
|
427
518
|
// truncates if we append or download anything after the truncation point later on
|
|
@@ -442,6 +533,36 @@ module.exports = class Core {
|
|
|
442
533
|
}
|
|
443
534
|
}
|
|
444
535
|
|
|
536
|
+
function updateContig (header, upd, bitfield) {
|
|
537
|
+
const end = upd.start + upd.length
|
|
538
|
+
|
|
539
|
+
let c = header.contiguousLength
|
|
540
|
+
|
|
541
|
+
if (upd.drop) {
|
|
542
|
+
// If we dropped a block in the current contig range, "downgrade" it
|
|
543
|
+
if (c <= end && c > upd.start) {
|
|
544
|
+
c = upd.start
|
|
545
|
+
}
|
|
546
|
+
} else {
|
|
547
|
+
if (c <= end && c >= upd.start) {
|
|
548
|
+
c = end
|
|
549
|
+
while (bitfield.get(c)) c++
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
if (c === header.contiguousLength) {
|
|
554
|
+
return 0b0000
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
if (c > header.contiguousLength) {
|
|
558
|
+
header.contiguousLength = c
|
|
559
|
+
return 0b0100
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
header.contiguousLength = c
|
|
563
|
+
return 0b1000
|
|
564
|
+
}
|
|
565
|
+
|
|
445
566
|
function addReorgHint (list, tree, batch) {
|
|
446
567
|
if (tree.length === 0 || tree.fork === batch.fork) return
|
|
447
568
|
|
|
@@ -465,4 +586,25 @@ function updateUserData (list, key, value) {
|
|
|
465
586
|
if (value) list.push({ key, value })
|
|
466
587
|
}
|
|
467
588
|
|
|
589
|
+
function closeAll (...storages) {
|
|
590
|
+
let missing = 1
|
|
591
|
+
let error = null
|
|
592
|
+
|
|
593
|
+
return new Promise((resolve, reject) => {
|
|
594
|
+
for (const s of storages) {
|
|
595
|
+
missing++
|
|
596
|
+
s.close(done)
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
done(null)
|
|
600
|
+
|
|
601
|
+
function done (err) {
|
|
602
|
+
if (err) error = err
|
|
603
|
+
if (--missing) return
|
|
604
|
+
if (error) reject(error)
|
|
605
|
+
else resolve()
|
|
606
|
+
}
|
|
607
|
+
})
|
|
608
|
+
}
|
|
609
|
+
|
|
468
610
|
function noop () {}
|
package/lib/download.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module.exports = class Download {
|
|
2
|
+
constructor (req) {
|
|
3
|
+
this.req = req
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
async done () {
|
|
7
|
+
return (await this.req).promise
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Deprecated. Use `range.done()`.
|
|
12
|
+
*/
|
|
13
|
+
downloaded () {
|
|
14
|
+
return this.done()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
destroy () {
|
|
18
|
+
this.req.then(req => req.context && req.context.detach(req), noop)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function noop () {}
|
package/lib/errors.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module.exports = class HypercoreError extends Error {
|
|
2
|
+
constructor (msg, code, fn = HypercoreError) {
|
|
3
|
+
super(`${code}: ${msg}`)
|
|
4
|
+
this.code = code
|
|
5
|
+
|
|
6
|
+
if (Error.captureStackTrace) {
|
|
7
|
+
Error.captureStackTrace(this, fn)
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get name () {
|
|
12
|
+
return 'HypercoreError'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static BAD_ARGUMENT (msg) {
|
|
16
|
+
return new HypercoreError(msg, 'BAD_ARGUMENT', HypercoreError.BAD_ARGUMENT)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static STORAGE_EMPTY (msg) {
|
|
20
|
+
return new HypercoreError(msg, 'STORAGE_EMPTY', HypercoreError.STORAGE_EMPTY)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static STORAGE_CONFLICT (msg) {
|
|
24
|
+
return new HypercoreError(msg, 'STORAGE_CONFLICT', HypercoreError.STORAGE_CONFLICT)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static INVALID_SIGNATURE (msg) {
|
|
28
|
+
return new HypercoreError(msg, 'INVALID_SIGNATURE', HypercoreError.INVALID_SIGNATURE)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static INVALID_CAPABILITY (msg) {
|
|
32
|
+
return new HypercoreError(msg, 'INVALID_CAPABILITY', HypercoreError.INVALID_CAPABILITY)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static SNAPSHOT_NOT_AVAILABLE (msg = 'Snapshot is not available') {
|
|
36
|
+
return new HypercoreError(msg, 'SNAPSHOT_NOT_AVAILABLE', HypercoreError.SNAPSHOT_NOT_AVAILABLE)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static REQUEST_CANCELLED (msg = 'Request was cancelled') {
|
|
40
|
+
return new HypercoreError(msg, 'REQUEST_CANCELLED', HypercoreError.REQUEST_CANCELLED)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static SESSION_NOT_WRITABLE (msg = 'Session is not writable') {
|
|
44
|
+
return new HypercoreError(msg, 'SESSION_NOT_WRITABLE', HypercoreError.SESSION_NOT_WRITABLE)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static SESSION_CLOSED (msg = 'Session is closed') {
|
|
48
|
+
return new HypercoreError(msg, 'SESSION_CLOSED', HypercoreError.SESSION_CLOSED)
|
|
49
|
+
}
|
|
50
|
+
}
|
package/lib/info.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module.exports = class Info {
|
|
2
|
+
constructor (opts = {}) {
|
|
3
|
+
this.length = opts.length || 0
|
|
4
|
+
this.contiguousLength = opts.contiguousLength || 0
|
|
5
|
+
this.byteLength = opts.byteLength || 0
|
|
6
|
+
this.padding = opts.padding || 0
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static async from (core, padding, snapshot) {
|
|
10
|
+
return new Info({
|
|
11
|
+
key: core.key,
|
|
12
|
+
discoveryKey: core.discoveryKey,
|
|
13
|
+
length: snapshot
|
|
14
|
+
? snapshot.length
|
|
15
|
+
: core.tree.length,
|
|
16
|
+
contiguousLength: core.header.contiguousLength,
|
|
17
|
+
byteLength: snapshot
|
|
18
|
+
? snapshot.byteLength
|
|
19
|
+
: (core.tree.byteLength - (core.tree.length * padding)),
|
|
20
|
+
fork: core.tree.fork,
|
|
21
|
+
padding
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
}
|