hypercore 11.16.2 → 11.17.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 +31 -29
- package/index.js +212 -127
- package/lib/audit.js +17 -6
- package/lib/bit-interlude.js +17 -7
- package/lib/bitfield.js +72 -52
- package/lib/caps.js +5 -1
- package/lib/copy-prologue.js +14 -10
- package/lib/core.js +109 -56
- package/lib/default-encryption.js +14 -28
- package/lib/download.js +10 -10
- package/lib/fully-remote-proof.js +3 -3
- package/lib/hotswap-queue.js +5 -5
- package/lib/info.js +4 -4
- package/lib/merkle-tree.js +143 -104
- package/lib/messages.js +163 -143
- package/lib/multisig.js +19 -12
- package/lib/mutex.js +9 -7
- package/lib/receiver-queue.js +6 -6
- package/lib/remote-bitfield.js +30 -32
- package/lib/replicator.js +383 -265
- package/lib/session-state.js +112 -75
- package/lib/streams.js +16 -16
- package/lib/verifier.js +69 -43
- package/package.json +5 -3
package/index.js
CHANGED
|
@@ -36,7 +36,7 @@ const inspect = Symbol.for('nodejs.util.inspect.custom')
|
|
|
36
36
|
const MAX_SUGGESTED_BLOCK_SIZE = 15 * 1024 * 1024
|
|
37
37
|
|
|
38
38
|
class Hypercore extends EventEmitter {
|
|
39
|
-
constructor
|
|
39
|
+
constructor(storage, key, opts) {
|
|
40
40
|
super()
|
|
41
41
|
|
|
42
42
|
if (isOptions(storage) && !storage.db) {
|
|
@@ -96,7 +96,7 @@ class Hypercore extends EventEmitter {
|
|
|
96
96
|
this.on('newListener', maybeAddMonitor)
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
[inspect]
|
|
99
|
+
[inspect](depth, opts) {
|
|
100
100
|
let indent = ''
|
|
101
101
|
if (typeof opts.indentationLvl === 'number') {
|
|
102
102
|
while (indent.length < opts.indentationLvl) indent += ' '
|
|
@@ -109,10 +109,15 @@ class Hypercore extends EventEmitter {
|
|
|
109
109
|
const peer = this.peers[i]
|
|
110
110
|
|
|
111
111
|
peers += indent + ' Peer(\n'
|
|
112
|
-
peers +=
|
|
112
|
+
peers +=
|
|
113
|
+
indent +
|
|
114
|
+
' remotePublicKey: ' +
|
|
115
|
+
opts.stylize(toHex(peer.remotePublicKey), 'string') +
|
|
116
|
+
'\n'
|
|
113
117
|
peers += indent + ' remoteLength: ' + opts.stylize(peer.remoteLength, 'number') + '\n'
|
|
114
118
|
peers += indent + ' remoteFork: ' + opts.stylize(peer.remoteFork, 'number') + '\n'
|
|
115
|
-
peers +=
|
|
119
|
+
peers +=
|
|
120
|
+
indent + ' remoteCanUpgrade: ' + opts.stylize(peer.remoteCanUpgrade, 'boolean') + '\n'
|
|
116
121
|
peers += indent + ' )' + '\n'
|
|
117
122
|
}
|
|
118
123
|
|
|
@@ -123,48 +128,89 @@ class Hypercore extends EventEmitter {
|
|
|
123
128
|
if (peers) peers = '[\n' + peers + indent + ' ]'
|
|
124
129
|
else peers = '[ ' + opts.stylize(0, 'number') + ' ]'
|
|
125
130
|
|
|
126
|
-
return
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
indent +
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
indent +
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
indent +
|
|
138
|
-
|
|
139
|
-
|
|
131
|
+
return (
|
|
132
|
+
this.constructor.name +
|
|
133
|
+
'(\n' +
|
|
134
|
+
indent +
|
|
135
|
+
' id: ' +
|
|
136
|
+
opts.stylize(this.id, 'string') +
|
|
137
|
+
'\n' +
|
|
138
|
+
indent +
|
|
139
|
+
' key: ' +
|
|
140
|
+
opts.stylize(toHex(this.key), 'string') +
|
|
141
|
+
'\n' +
|
|
142
|
+
indent +
|
|
143
|
+
' discoveryKey: ' +
|
|
144
|
+
opts.stylize(toHex(this.discoveryKey), 'string') +
|
|
145
|
+
'\n' +
|
|
146
|
+
indent +
|
|
147
|
+
' opened: ' +
|
|
148
|
+
opts.stylize(this.opened, 'boolean') +
|
|
149
|
+
'\n' +
|
|
150
|
+
indent +
|
|
151
|
+
' closed: ' +
|
|
152
|
+
opts.stylize(this.closed, 'boolean') +
|
|
153
|
+
'\n' +
|
|
154
|
+
indent +
|
|
155
|
+
' snapshotted: ' +
|
|
156
|
+
opts.stylize(this.snapshotted, 'boolean') +
|
|
157
|
+
'\n' +
|
|
158
|
+
indent +
|
|
159
|
+
' writable: ' +
|
|
160
|
+
opts.stylize(this.writable, 'boolean') +
|
|
161
|
+
'\n' +
|
|
162
|
+
indent +
|
|
163
|
+
' length: ' +
|
|
164
|
+
opts.stylize(this.length, 'number') +
|
|
165
|
+
'\n' +
|
|
166
|
+
indent +
|
|
167
|
+
' fork: ' +
|
|
168
|
+
opts.stylize(this.fork, 'number') +
|
|
169
|
+
'\n' +
|
|
170
|
+
indent +
|
|
171
|
+
' sessions: [ ' +
|
|
172
|
+
opts.stylize(this.sessions.length, 'number') +
|
|
173
|
+
' ]\n' +
|
|
174
|
+
indent +
|
|
175
|
+
' activeRequests: [ ' +
|
|
176
|
+
opts.stylize(this.activeRequests.length, 'number') +
|
|
177
|
+
' ]\n' +
|
|
178
|
+
indent +
|
|
179
|
+
' peers: ' +
|
|
180
|
+
peers +
|
|
181
|
+
'\n' +
|
|
182
|
+
indent +
|
|
183
|
+
')'
|
|
184
|
+
)
|
|
140
185
|
}
|
|
141
186
|
|
|
142
187
|
static MAX_SUGGESTED_BLOCK_SIZE = MAX_SUGGESTED_BLOCK_SIZE
|
|
143
188
|
|
|
144
189
|
static DefaultEncryption = DefaultEncryption
|
|
145
190
|
|
|
146
|
-
static key
|
|
147
|
-
if (b4a.isBuffer(manifest))
|
|
191
|
+
static key(manifest, { compat, version, namespace } = {}) {
|
|
192
|
+
if (b4a.isBuffer(manifest))
|
|
193
|
+
manifest = { version, signers: [{ publicKey: manifest, namespace }] }
|
|
148
194
|
return compat ? manifest.signers[0].publicKey : manifestHash(createManifest(manifest))
|
|
149
195
|
}
|
|
150
196
|
|
|
151
|
-
static discoveryKey
|
|
197
|
+
static discoveryKey(key) {
|
|
152
198
|
return crypto.discoveryKey(key)
|
|
153
199
|
}
|
|
154
200
|
|
|
155
|
-
static blockEncryptionKey
|
|
201
|
+
static blockEncryptionKey(key, encryptionKey) {
|
|
156
202
|
return DefaultEncryption.blockEncryptionKey(key, encryptionKey)
|
|
157
203
|
}
|
|
158
204
|
|
|
159
|
-
static getProtocolMuxer
|
|
205
|
+
static getProtocolMuxer(stream) {
|
|
160
206
|
return stream.noiseStream.userData
|
|
161
207
|
}
|
|
162
208
|
|
|
163
|
-
static createCore
|
|
209
|
+
static createCore(storage, opts) {
|
|
164
210
|
return new Core(Hypercore.defaultStorage(storage), { autoClose: false, ...opts })
|
|
165
211
|
}
|
|
166
212
|
|
|
167
|
-
static createProtocolStream
|
|
213
|
+
static createProtocolStream(isInitiator, opts = {}) {
|
|
168
214
|
let outerStream = Protomux.isProtomux(isInitiator)
|
|
169
215
|
? isInitiator.stream
|
|
170
216
|
: isStream(isInitiator)
|
|
@@ -197,22 +243,26 @@ class Hypercore extends EventEmitter {
|
|
|
197
243
|
return outerStream
|
|
198
244
|
}
|
|
199
245
|
|
|
200
|
-
static defaultStorage
|
|
246
|
+
static defaultStorage(storage, opts = {}) {
|
|
201
247
|
if (CoreStorage.isCoreStorage(storage)) return storage
|
|
202
248
|
|
|
203
249
|
const directory = storage
|
|
204
250
|
return new CoreStorage(directory, opts)
|
|
205
251
|
}
|
|
206
252
|
|
|
207
|
-
static clearRequests
|
|
253
|
+
static clearRequests(session, err) {
|
|
208
254
|
return Replicator.clearRequests(session, err)
|
|
209
255
|
}
|
|
210
256
|
|
|
211
|
-
snapshot
|
|
257
|
+
snapshot(opts) {
|
|
212
258
|
return this.session({ ...opts, snapshot: true })
|
|
213
259
|
}
|
|
214
260
|
|
|
215
|
-
|
|
261
|
+
compact() {
|
|
262
|
+
return this.core.compact()
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
session(opts = {}) {
|
|
216
266
|
if (this.closing) {
|
|
217
267
|
// This makes the closing logic a lot easier. If this turns out to be a problem
|
|
218
268
|
// in practice, open an issue and we'll try to make a solution for it.
|
|
@@ -243,13 +293,13 @@ class Hypercore extends EventEmitter {
|
|
|
243
293
|
return s
|
|
244
294
|
}
|
|
245
295
|
|
|
246
|
-
async setEncryptionKey
|
|
296
|
+
async setEncryptionKey(key, opts) {
|
|
247
297
|
if (!this.opened) await this.opening
|
|
248
298
|
const encryption = this._getEncryptionProvider({ key, block: !!(opts && opts.block) })
|
|
249
299
|
return this.setEncryption(encryption)
|
|
250
300
|
}
|
|
251
301
|
|
|
252
|
-
async setEncryption
|
|
302
|
+
async setEncryption(encryption) {
|
|
253
303
|
if (!this.opened) await this.opening
|
|
254
304
|
|
|
255
305
|
if (encryption === null) {
|
|
@@ -264,11 +314,11 @@ class Hypercore extends EventEmitter {
|
|
|
264
314
|
this.encryption = encryption
|
|
265
315
|
}
|
|
266
316
|
|
|
267
|
-
setKeyPair
|
|
317
|
+
setKeyPair(keyPair) {
|
|
268
318
|
this.keyPair = keyPair
|
|
269
319
|
}
|
|
270
320
|
|
|
271
|
-
setActive
|
|
321
|
+
setActive(bool) {
|
|
272
322
|
const active = !!bool
|
|
273
323
|
if (active === this._active || this.closing) return
|
|
274
324
|
this._active = active
|
|
@@ -276,7 +326,7 @@ class Hypercore extends EventEmitter {
|
|
|
276
326
|
this.core.replicator.updateActivity(this._active ? 1 : -1)
|
|
277
327
|
}
|
|
278
328
|
|
|
279
|
-
async _open
|
|
329
|
+
async _open(storage, key, opts) {
|
|
280
330
|
const preload = opts.preload || (opts.parent && opts.parent.preload)
|
|
281
331
|
|
|
282
332
|
if (preload) {
|
|
@@ -324,7 +374,7 @@ class Hypercore extends EventEmitter {
|
|
|
324
374
|
if (this.core.closing) this.close().catch(safetyCatch)
|
|
325
375
|
}
|
|
326
376
|
|
|
327
|
-
_removeSession
|
|
377
|
+
_removeSession() {
|
|
328
378
|
if (this._sessionIndex === -1) return
|
|
329
379
|
const head = this.sessions.pop()
|
|
330
380
|
if (head !== this) this.sessions[(head._sessionIndex = this._sessionIndex)] = head
|
|
@@ -332,7 +382,7 @@ class Hypercore extends EventEmitter {
|
|
|
332
382
|
if (this.ongc !== null) this.ongc(this)
|
|
333
383
|
}
|
|
334
384
|
|
|
335
|
-
async _openSession
|
|
385
|
+
async _openSession(opts) {
|
|
336
386
|
if (this.core.opened === false) await this.core.ready()
|
|
337
387
|
|
|
338
388
|
if (this.keyPair === null) this.keyPair = opts.keyPair || this.core.header.keyPair
|
|
@@ -388,10 +438,23 @@ class Hypercore extends EventEmitter {
|
|
|
388
438
|
}
|
|
389
439
|
|
|
390
440
|
if (this.state && checkout !== -1) {
|
|
391
|
-
if (!opts.name && !opts.atom)
|
|
392
|
-
|
|
441
|
+
if (!opts.name && !opts.atom)
|
|
442
|
+
throw ASSERTION('Checkouts must be named or atomized', this.discoveryKey)
|
|
443
|
+
if (checkout > this.state.length)
|
|
444
|
+
throw ASSERTION(
|
|
445
|
+
'Invalid checkout ' + checkout + ' for ' + opts.name + ', length is ' + this.state.length,
|
|
446
|
+
this.discoveryKey
|
|
447
|
+
)
|
|
393
448
|
if (this.state.prologue && checkout < this.state.prologue.length) {
|
|
394
|
-
throw ASSERTION(
|
|
449
|
+
throw ASSERTION(
|
|
450
|
+
'Invalid checkout ' +
|
|
451
|
+
checkout +
|
|
452
|
+
' for ' +
|
|
453
|
+
opts.name +
|
|
454
|
+
', prologue length is ' +
|
|
455
|
+
this.state.prologue.length,
|
|
456
|
+
this.discoveryKey
|
|
457
|
+
)
|
|
395
458
|
}
|
|
396
459
|
if (checkout < this.state.length) await this.state.truncate(checkout, this.fork)
|
|
397
460
|
}
|
|
@@ -425,11 +488,11 @@ class Hypercore extends EventEmitter {
|
|
|
425
488
|
this.opened = true
|
|
426
489
|
}
|
|
427
490
|
|
|
428
|
-
get replicator
|
|
491
|
+
get replicator() {
|
|
429
492
|
return this.core === null ? null : this.core.replicator
|
|
430
493
|
}
|
|
431
494
|
|
|
432
|
-
_getSnapshot
|
|
495
|
+
_getSnapshot() {
|
|
433
496
|
return {
|
|
434
497
|
length: this.state.length,
|
|
435
498
|
byteLength: this.state.byteLength,
|
|
@@ -437,33 +500,33 @@ class Hypercore extends EventEmitter {
|
|
|
437
500
|
}
|
|
438
501
|
}
|
|
439
502
|
|
|
440
|
-
_updateSnapshot
|
|
503
|
+
_updateSnapshot() {
|
|
441
504
|
const prev = this._snapshot
|
|
442
|
-
const next = this._snapshot = this._getSnapshot()
|
|
505
|
+
const next = (this._snapshot = this._getSnapshot())
|
|
443
506
|
|
|
444
507
|
if (!prev) return true
|
|
445
508
|
return prev.length !== next.length || prev.fork !== next.fork
|
|
446
509
|
}
|
|
447
510
|
|
|
448
|
-
_isWritable
|
|
511
|
+
_isWritable() {
|
|
449
512
|
if (this._readonly) return false
|
|
450
513
|
if (this.state && !this.state.isDefault()) return true
|
|
451
514
|
return !!(this.keyPair && this.keyPair.secretKey)
|
|
452
515
|
}
|
|
453
516
|
|
|
454
|
-
close
|
|
517
|
+
close({ error } = {}) {
|
|
455
518
|
if (this.closing) return this.closing
|
|
456
519
|
|
|
457
520
|
this.closing = this._close(error || null)
|
|
458
521
|
return this.closing
|
|
459
522
|
}
|
|
460
523
|
|
|
461
|
-
clearRequests
|
|
524
|
+
clearRequests(activeRequests, error) {
|
|
462
525
|
if (!activeRequests.length) return
|
|
463
526
|
if (this.core) this.core.replicator.clearRequests(activeRequests, error)
|
|
464
527
|
}
|
|
465
528
|
|
|
466
|
-
async _close
|
|
529
|
+
async _close(error) {
|
|
467
530
|
if (this.opened === false) {
|
|
468
531
|
try {
|
|
469
532
|
await this.opening
|
|
@@ -511,14 +574,14 @@ class Hypercore extends EventEmitter {
|
|
|
511
574
|
this.emit('close')
|
|
512
575
|
}
|
|
513
576
|
|
|
514
|
-
async commit
|
|
577
|
+
async commit(session, opts) {
|
|
515
578
|
await this.ready()
|
|
516
579
|
await session.ready()
|
|
517
580
|
|
|
518
581
|
return this.state.commit(session.state, { keyPair: this.keyPair, ...opts })
|
|
519
582
|
}
|
|
520
583
|
|
|
521
|
-
replicate
|
|
584
|
+
replicate(isInitiator, opts = {}) {
|
|
522
585
|
// Only limitation here is that ondiscoverykey doesn't work atm when passing a muxer directly,
|
|
523
586
|
// because it doesn't really make a lot of sense.
|
|
524
587
|
if (Protomux.isProtomux(isInitiator)) return this._attachToMuxer(isInitiator)
|
|
@@ -535,11 +598,16 @@ class Hypercore extends EventEmitter {
|
|
|
535
598
|
return protocolStream
|
|
536
599
|
}
|
|
537
600
|
|
|
538
|
-
_isAttached
|
|
539
|
-
return
|
|
601
|
+
_isAttached(stream) {
|
|
602
|
+
return (
|
|
603
|
+
stream.userData &&
|
|
604
|
+
this.core &&
|
|
605
|
+
this.core.replicator &&
|
|
606
|
+
this.core.replicator.attached(stream.userData)
|
|
607
|
+
)
|
|
540
608
|
}
|
|
541
609
|
|
|
542
|
-
_attachToMuxer
|
|
610
|
+
_attachToMuxer(mux) {
|
|
543
611
|
if (this.opened) {
|
|
544
612
|
this.core.replicator.attachTo(mux)
|
|
545
613
|
} else {
|
|
@@ -549,55 +617,55 @@ class Hypercore extends EventEmitter {
|
|
|
549
617
|
return mux
|
|
550
618
|
}
|
|
551
619
|
|
|
552
|
-
get id
|
|
620
|
+
get id() {
|
|
553
621
|
return this.core === null ? null : this.core.id
|
|
554
622
|
}
|
|
555
623
|
|
|
556
|
-
get key
|
|
624
|
+
get key() {
|
|
557
625
|
return this.core === null ? null : this.core.key
|
|
558
626
|
}
|
|
559
627
|
|
|
560
|
-
get discoveryKey
|
|
628
|
+
get discoveryKey() {
|
|
561
629
|
return this.core === null ? null : this.core.discoveryKey
|
|
562
630
|
}
|
|
563
631
|
|
|
564
|
-
get manifest
|
|
632
|
+
get manifest() {
|
|
565
633
|
return this.core === null ? null : this.core.manifest
|
|
566
634
|
}
|
|
567
635
|
|
|
568
|
-
get length
|
|
636
|
+
get length() {
|
|
569
637
|
if (this._snapshot) return this._snapshot.length
|
|
570
638
|
return this.opened === false ? 0 : this.state.length
|
|
571
639
|
}
|
|
572
640
|
|
|
573
|
-
get signedLength
|
|
641
|
+
get signedLength() {
|
|
574
642
|
return this.opened === false ? 0 : this.state.signedLength()
|
|
575
643
|
}
|
|
576
644
|
|
|
577
645
|
/**
|
|
578
646
|
* Deprecated. Use `const { byteLength } = await core.info()`.
|
|
579
647
|
*/
|
|
580
|
-
get byteLength
|
|
648
|
+
get byteLength() {
|
|
581
649
|
if (this.opened === false) return 0
|
|
582
650
|
if (this._snapshot) return this._snapshot.byteLength
|
|
583
|
-
return this.state.byteLength -
|
|
651
|
+
return this.state.byteLength - this.state.length * this.padding
|
|
584
652
|
}
|
|
585
653
|
|
|
586
|
-
get contiguousLength
|
|
654
|
+
get contiguousLength() {
|
|
587
655
|
if (this.opened === false) return 0
|
|
588
656
|
return Math.min(this.core.state.length, this.core.header.hints.contiguousLength)
|
|
589
657
|
}
|
|
590
658
|
|
|
591
|
-
get contiguousByteLength
|
|
659
|
+
get contiguousByteLength() {
|
|
592
660
|
return 0
|
|
593
661
|
}
|
|
594
662
|
|
|
595
|
-
get fork
|
|
663
|
+
get fork() {
|
|
596
664
|
if (this.opened === false) return 0
|
|
597
665
|
return this.state.fork
|
|
598
666
|
}
|
|
599
667
|
|
|
600
|
-
get padding
|
|
668
|
+
get padding() {
|
|
601
669
|
if (this.encryption && this.key && this.manifest) {
|
|
602
670
|
return this.encryption.padding(this.core, this.length)
|
|
603
671
|
}
|
|
@@ -605,24 +673,24 @@ class Hypercore extends EventEmitter {
|
|
|
605
673
|
return 0
|
|
606
674
|
}
|
|
607
675
|
|
|
608
|
-
get peers
|
|
676
|
+
get peers() {
|
|
609
677
|
return this.opened === false ? [] : this.core.replicator.peers
|
|
610
678
|
}
|
|
611
679
|
|
|
612
|
-
get globalCache
|
|
680
|
+
get globalCache() {
|
|
613
681
|
return this.opened === false ? null : this.core.globalCache
|
|
614
682
|
}
|
|
615
683
|
|
|
616
|
-
ready
|
|
684
|
+
ready() {
|
|
617
685
|
return this.opening
|
|
618
686
|
}
|
|
619
687
|
|
|
620
|
-
async setUserData
|
|
688
|
+
async setUserData(key, value) {
|
|
621
689
|
if (this.opened === false) await this.opening
|
|
622
690
|
await this.state.setUserData(key, value)
|
|
623
691
|
}
|
|
624
692
|
|
|
625
|
-
async getUserData
|
|
693
|
+
async getUserData(key) {
|
|
626
694
|
if (this.opened === false) await this.opening
|
|
627
695
|
const batch = this.state.storage.read()
|
|
628
696
|
const p = batch.getUserData(key)
|
|
@@ -630,7 +698,7 @@ class Hypercore extends EventEmitter {
|
|
|
630
698
|
return p
|
|
631
699
|
}
|
|
632
700
|
|
|
633
|
-
transferSession
|
|
701
|
+
transferSession(core) {
|
|
634
702
|
// todo: validate we can move
|
|
635
703
|
|
|
636
704
|
if (this.weak === false) {
|
|
@@ -652,7 +720,7 @@ class Hypercore extends EventEmitter {
|
|
|
652
720
|
this.emit('migrate', this.key)
|
|
653
721
|
}
|
|
654
722
|
|
|
655
|
-
findingPeers
|
|
723
|
+
findingPeers() {
|
|
656
724
|
this._findingPeers++
|
|
657
725
|
if (this.core !== null && !this.closing) this.core.replicator.findingPeers++
|
|
658
726
|
|
|
@@ -668,13 +736,13 @@ class Hypercore extends EventEmitter {
|
|
|
668
736
|
}
|
|
669
737
|
}
|
|
670
738
|
|
|
671
|
-
async info
|
|
739
|
+
async info(opts) {
|
|
672
740
|
if (this.opened === false) await this.opening
|
|
673
741
|
|
|
674
742
|
return Info.from(this, opts)
|
|
675
743
|
}
|
|
676
744
|
|
|
677
|
-
async update
|
|
745
|
+
async update(opts) {
|
|
678
746
|
if (this.opened === false) await this.opening
|
|
679
747
|
if (this.closing !== null) return false
|
|
680
748
|
if (this.snapshotted) return false
|
|
@@ -705,7 +773,7 @@ class Hypercore extends EventEmitter {
|
|
|
705
773
|
return true
|
|
706
774
|
}
|
|
707
775
|
|
|
708
|
-
async seek
|
|
776
|
+
async seek(bytes, opts) {
|
|
709
777
|
if (this.opened === false) await this.opening
|
|
710
778
|
if (!isValidIndex(bytes)) throw ASSERTION('seek is invalid', this.discoveryKey)
|
|
711
779
|
|
|
@@ -726,7 +794,8 @@ class Hypercore extends EventEmitter {
|
|
|
726
794
|
const offset = await s.update()
|
|
727
795
|
if (offset) return offset
|
|
728
796
|
|
|
729
|
-
if (this.closing !== null)
|
|
797
|
+
if (this.closing !== null)
|
|
798
|
+
throw SESSION_CLOSED('cannot seek on a closed session', this.discoveryKey)
|
|
730
799
|
|
|
731
800
|
if (!this._shouldWait(opts, this.wait)) return null
|
|
732
801
|
|
|
@@ -743,9 +812,10 @@ class Hypercore extends EventEmitter {
|
|
|
743
812
|
}
|
|
744
813
|
}
|
|
745
814
|
|
|
746
|
-
async has
|
|
815
|
+
async has(start, end = start + 1) {
|
|
747
816
|
if (this.opened === false) await this.opening
|
|
748
|
-
if (!isValidIndex(start) || !isValidIndex(end))
|
|
817
|
+
if (!isValidIndex(start) || !isValidIndex(end))
|
|
818
|
+
throw ASSERTION('has range is invalid', this.discoveryKey)
|
|
749
819
|
|
|
750
820
|
if (this.state.isDefault()) {
|
|
751
821
|
if (end === start + 1) return this.core.bitfield.get(start)
|
|
@@ -770,16 +840,18 @@ class Hypercore extends EventEmitter {
|
|
|
770
840
|
count++
|
|
771
841
|
}
|
|
772
842
|
|
|
773
|
-
return count ===
|
|
843
|
+
return count === end - start
|
|
774
844
|
}
|
|
775
845
|
|
|
776
|
-
async get
|
|
846
|
+
async get(index, opts) {
|
|
777
847
|
if (this.opened === false) await this.opening
|
|
778
848
|
if (!isValidIndex(index)) throw ASSERTION('block index is invalid', this.discoveryKey)
|
|
779
849
|
|
|
780
|
-
if (this.closing !== null)
|
|
850
|
+
if (this.closing !== null)
|
|
851
|
+
throw SESSION_CLOSED('cannot get on a closed session', this.discoveryKey)
|
|
781
852
|
|
|
782
|
-
const encoding =
|
|
853
|
+
const encoding =
|
|
854
|
+
(opts && opts.valueEncoding && c.from(opts.valueEncoding)) || this.valueEncoding
|
|
783
855
|
|
|
784
856
|
if (this.onseq !== null) this.onseq(index, this)
|
|
785
857
|
|
|
@@ -800,18 +872,20 @@ class Hypercore extends EventEmitter {
|
|
|
800
872
|
return this._decode(encoding, block, index)
|
|
801
873
|
}
|
|
802
874
|
|
|
803
|
-
async clear
|
|
875
|
+
async clear(start, end = start + 1, opts) {
|
|
804
876
|
if (this.opened === false) await this.opening
|
|
805
|
-
if (this.closing !== null)
|
|
877
|
+
if (this.closing !== null)
|
|
878
|
+
throw SESSION_CLOSED('cannot clear on a closed session', this.discoveryKey)
|
|
806
879
|
|
|
807
880
|
if (typeof end === 'object') {
|
|
808
881
|
opts = end
|
|
809
882
|
end = start + 1
|
|
810
883
|
}
|
|
811
884
|
|
|
812
|
-
if (!isValidIndex(start) || !isValidIndex(end))
|
|
885
|
+
if (!isValidIndex(start) || !isValidIndex(end))
|
|
886
|
+
throw ASSERTION('clear range is invalid', this.discoveryKey)
|
|
813
887
|
|
|
814
|
-
const cleared =
|
|
888
|
+
const cleared = opts && opts.diff ? { blocks: 0 } : null
|
|
815
889
|
|
|
816
890
|
if (start >= end) return cleared
|
|
817
891
|
if (start >= this.length) return cleared
|
|
@@ -821,17 +895,18 @@ class Hypercore extends EventEmitter {
|
|
|
821
895
|
return cleared
|
|
822
896
|
}
|
|
823
897
|
|
|
824
|
-
async purge
|
|
898
|
+
async purge() {
|
|
825
899
|
await this._closeAllSessions(null)
|
|
826
900
|
await this.core.purge()
|
|
827
901
|
}
|
|
828
902
|
|
|
829
|
-
async _get
|
|
903
|
+
async _get(index, opts) {
|
|
830
904
|
const block = await readBlock(this.state.storage.read(), index)
|
|
831
905
|
|
|
832
906
|
if (block !== null) return block
|
|
833
907
|
|
|
834
|
-
if (this.closing !== null)
|
|
908
|
+
if (this.closing !== null)
|
|
909
|
+
throw SESSION_CLOSED('cannot get on a closed session', this.discoveryKey)
|
|
835
910
|
|
|
836
911
|
// snapshot should check if core has block
|
|
837
912
|
if (this._snapshot !== null) {
|
|
@@ -876,7 +951,7 @@ class Hypercore extends EventEmitter {
|
|
|
876
951
|
return maybeUnslab(replicatedBlock)
|
|
877
952
|
}
|
|
878
953
|
|
|
879
|
-
_shouldWait
|
|
954
|
+
_shouldWait(opts, defaultValue) {
|
|
880
955
|
if (opts) {
|
|
881
956
|
if (opts.wait === false) return false
|
|
882
957
|
if (opts.wait === true) return true
|
|
@@ -884,33 +959,33 @@ class Hypercore extends EventEmitter {
|
|
|
884
959
|
return defaultValue
|
|
885
960
|
}
|
|
886
961
|
|
|
887
|
-
createReadStream
|
|
962
|
+
createReadStream(opts) {
|
|
888
963
|
return new ReadStream(this, opts)
|
|
889
964
|
}
|
|
890
965
|
|
|
891
|
-
createWriteStream
|
|
966
|
+
createWriteStream() {
|
|
892
967
|
return new WriteStream(this)
|
|
893
968
|
}
|
|
894
969
|
|
|
895
|
-
createByteStream
|
|
970
|
+
createByteStream(opts) {
|
|
896
971
|
return new ByteStream(this, opts)
|
|
897
972
|
}
|
|
898
973
|
|
|
899
|
-
download
|
|
974
|
+
download(range) {
|
|
900
975
|
return new Download(this, range)
|
|
901
976
|
}
|
|
902
977
|
|
|
903
978
|
// TODO: get rid of this / deprecate it?
|
|
904
|
-
undownload
|
|
979
|
+
undownload(range) {
|
|
905
980
|
range.destroy(null)
|
|
906
981
|
}
|
|
907
982
|
|
|
908
983
|
// TODO: get rid of this / deprecate it?
|
|
909
|
-
cancel
|
|
984
|
+
cancel(request) {
|
|
910
985
|
// Do nothing for now
|
|
911
986
|
}
|
|
912
987
|
|
|
913
|
-
async truncate
|
|
988
|
+
async truncate(newLength = 0, opts = {}) {
|
|
914
989
|
if (this.opened === false) await this.opening
|
|
915
990
|
|
|
916
991
|
const {
|
|
@@ -921,7 +996,8 @@ class Hypercore extends EventEmitter {
|
|
|
921
996
|
|
|
922
997
|
const isDefault = this.state === this.core.state
|
|
923
998
|
const writable = !this._readonly && !!(signature || (keyPair && keyPair.secretKey))
|
|
924
|
-
if (isDefault && writable === false && (newLength > 0 || fork !== this.state.fork))
|
|
999
|
+
if (isDefault && writable === false && (newLength > 0 || fork !== this.state.fork))
|
|
1000
|
+
throw SESSION_NOT_WRITABLE('cannot append to a non-writable core', this.discoveryKey)
|
|
925
1001
|
|
|
926
1002
|
await this.state.truncate(newLength, fork, { keyPair, signature })
|
|
927
1003
|
|
|
@@ -929,16 +1005,18 @@ class Hypercore extends EventEmitter {
|
|
|
929
1005
|
if (this.state === this.core.state) this.core.replicator.updateAll()
|
|
930
1006
|
}
|
|
931
1007
|
|
|
932
|
-
async append
|
|
1008
|
+
async append(blocks, opts = {}) {
|
|
933
1009
|
if (this.opened === false) await this.opening
|
|
934
1010
|
|
|
935
1011
|
const isDefault = this.state === this.core.state
|
|
936
1012
|
const defaultKeyPair = this.state.name === null ? this.keyPair : null
|
|
937
1013
|
|
|
938
1014
|
const { keyPair = defaultKeyPair, signature = null, maxLength } = opts
|
|
939
|
-
const writable =
|
|
1015
|
+
const writable =
|
|
1016
|
+
!isDefault || !!signature || !!(keyPair && keyPair.secretKey) || opts.writable === true
|
|
940
1017
|
|
|
941
|
-
if (this._readonly || writable === false)
|
|
1018
|
+
if (this._readonly || writable === false)
|
|
1019
|
+
throw SESSION_NOT_WRITABLE('cannot append to a readonly core', this.discoveryKey)
|
|
942
1020
|
|
|
943
1021
|
blocks = Array.isArray(blocks) ? blocks : [blocks]
|
|
944
1022
|
|
|
@@ -953,14 +1031,17 @@ class Hypercore extends EventEmitter {
|
|
|
953
1031
|
}
|
|
954
1032
|
for (const b of buffers) {
|
|
955
1033
|
if (b.byteLength > MAX_SUGGESTED_BLOCK_SIZE) {
|
|
956
|
-
throw BAD_ARGUMENT(
|
|
1034
|
+
throw BAD_ARGUMENT(
|
|
1035
|
+
'Appended block exceeds the maximum suggested block size',
|
|
1036
|
+
this.discoveryKey
|
|
1037
|
+
)
|
|
957
1038
|
}
|
|
958
1039
|
}
|
|
959
1040
|
|
|
960
1041
|
return this.state.append(buffers, { keyPair, signature, preappend, maxLength })
|
|
961
1042
|
}
|
|
962
1043
|
|
|
963
|
-
async signable
|
|
1044
|
+
async signable(length = -1, fork = -1) {
|
|
964
1045
|
if (this.opened === false) await this.opening
|
|
965
1046
|
if (length === -1) length = this.length
|
|
966
1047
|
if (fork === -1) fork = this.fork
|
|
@@ -968,7 +1049,7 @@ class Hypercore extends EventEmitter {
|
|
|
968
1049
|
return caps.treeSignable(this.key, await this.treeHash(length), length, fork)
|
|
969
1050
|
}
|
|
970
1051
|
|
|
971
|
-
async treeHash
|
|
1052
|
+
async treeHash(length = -1) {
|
|
972
1053
|
if (this.opened === false) await this.opening
|
|
973
1054
|
if (length === -1) length = this.length
|
|
974
1055
|
|
|
@@ -976,7 +1057,7 @@ class Hypercore extends EventEmitter {
|
|
|
976
1057
|
return crypto.tree(roots)
|
|
977
1058
|
}
|
|
978
1059
|
|
|
979
|
-
async proof
|
|
1060
|
+
async proof(opts) {
|
|
980
1061
|
if (this.opened === false) await this.opening
|
|
981
1062
|
const rx = this.state.storage.read()
|
|
982
1063
|
const promise = MerkleTree.proof(this.state, rx, opts)
|
|
@@ -984,14 +1065,14 @@ class Hypercore extends EventEmitter {
|
|
|
984
1065
|
return promise
|
|
985
1066
|
}
|
|
986
1067
|
|
|
987
|
-
async verifyFullyRemote
|
|
1068
|
+
async verifyFullyRemote(proof) {
|
|
988
1069
|
if (this.opened === false) await this.opening
|
|
989
1070
|
const batch = await MerkleTree.verifyFullyRemote(this.state, proof)
|
|
990
1071
|
await this.core._verifyBatchUpgrade(batch, proof.manifest)
|
|
991
1072
|
return batch
|
|
992
1073
|
}
|
|
993
1074
|
|
|
994
|
-
registerExtension
|
|
1075
|
+
registerExtension(name, handlers = {}) {
|
|
995
1076
|
if (this.extensions.has(name)) {
|
|
996
1077
|
const ext = this.extensions.get(name)
|
|
997
1078
|
ext.handlers = handlers
|
|
@@ -1005,23 +1086,23 @@ class Hypercore extends EventEmitter {
|
|
|
1005
1086
|
handlers,
|
|
1006
1087
|
encoding: c.from(handlers.encoding || c.buffer),
|
|
1007
1088
|
session: this,
|
|
1008
|
-
send
|
|
1089
|
+
send(message, peer) {
|
|
1009
1090
|
const buffer = c.encode(this.encoding, message)
|
|
1010
1091
|
peer.extension(name, buffer)
|
|
1011
1092
|
},
|
|
1012
|
-
broadcast
|
|
1093
|
+
broadcast(message) {
|
|
1013
1094
|
const buffer = c.encode(this.encoding, message)
|
|
1014
1095
|
for (const peer of this.session.peers) {
|
|
1015
1096
|
peer.extension(name, buffer)
|
|
1016
1097
|
}
|
|
1017
1098
|
},
|
|
1018
|
-
destroy
|
|
1099
|
+
destroy() {
|
|
1019
1100
|
for (const peer of this.session.peers) {
|
|
1020
1101
|
if (peer.extensions.get(name) === ext) peer.extensions.delete(name)
|
|
1021
1102
|
}
|
|
1022
1103
|
this.session.extensions.delete(name)
|
|
1023
1104
|
},
|
|
1024
|
-
_onmessage
|
|
1105
|
+
_onmessage(state, peer) {
|
|
1025
1106
|
const m = this.encoding.decode(state)
|
|
1026
1107
|
if (this.handlers.onmessage) this.handlers.onmessage(m, peer)
|
|
1027
1108
|
}
|
|
@@ -1039,7 +1120,7 @@ class Hypercore extends EventEmitter {
|
|
|
1039
1120
|
return ext
|
|
1040
1121
|
}
|
|
1041
1122
|
|
|
1042
|
-
_encode
|
|
1123
|
+
_encode(enc, val) {
|
|
1043
1124
|
const state = { start: this.padding, end: this.padding, buffer: null }
|
|
1044
1125
|
|
|
1045
1126
|
if (b4a.isBuffer(val)) {
|
|
@@ -1061,7 +1142,7 @@ class Hypercore extends EventEmitter {
|
|
|
1061
1142
|
return state.buffer
|
|
1062
1143
|
}
|
|
1063
1144
|
|
|
1064
|
-
_decode
|
|
1145
|
+
_decode(enc, block, index) {
|
|
1065
1146
|
if (this.encryption) block = block.subarray(this.encryption.padding(this.core, index))
|
|
1066
1147
|
try {
|
|
1067
1148
|
if (enc) return c.decode(enc, block)
|
|
@@ -1071,7 +1152,7 @@ class Hypercore extends EventEmitter {
|
|
|
1071
1152
|
return block
|
|
1072
1153
|
}
|
|
1073
1154
|
|
|
1074
|
-
_getEncryptionProvider
|
|
1155
|
+
_getEncryptionProvider(e) {
|
|
1075
1156
|
if (isEncryptionProvider(e)) return e
|
|
1076
1157
|
if (!e || !e.key) return null
|
|
1077
1158
|
return new DefaultEncryption(e.key, this.key, { block: e.block, compat: this.core.compat })
|
|
@@ -1080,15 +1161,15 @@ class Hypercore extends EventEmitter {
|
|
|
1080
1161
|
|
|
1081
1162
|
module.exports = Hypercore
|
|
1082
1163
|
|
|
1083
|
-
function isStream
|
|
1164
|
+
function isStream(s) {
|
|
1084
1165
|
return typeof s === 'object' && s && typeof s.pipe === 'function'
|
|
1085
1166
|
}
|
|
1086
1167
|
|
|
1087
|
-
function toHex
|
|
1168
|
+
function toHex(buf) {
|
|
1088
1169
|
return buf && b4a.toString(buf, 'hex')
|
|
1089
1170
|
}
|
|
1090
1171
|
|
|
1091
|
-
async function preappend
|
|
1172
|
+
async function preappend(blocks) {
|
|
1092
1173
|
const offset = this.state.length
|
|
1093
1174
|
const fork = this.state.encryptionFork
|
|
1094
1175
|
|
|
@@ -1097,26 +1178,30 @@ async function preappend (blocks) {
|
|
|
1097
1178
|
}
|
|
1098
1179
|
}
|
|
1099
1180
|
|
|
1100
|
-
function isValidIndex
|
|
1181
|
+
function isValidIndex(index) {
|
|
1101
1182
|
return index === 0 || index > 0
|
|
1102
1183
|
}
|
|
1103
1184
|
|
|
1104
|
-
function maybeUnslab
|
|
1185
|
+
function maybeUnslab(block) {
|
|
1105
1186
|
// Unslab only when it takes up less then half the slab
|
|
1106
1187
|
return block !== null && 2 * block.byteLength < block.buffer.byteLength ? unslab(block) : block
|
|
1107
1188
|
}
|
|
1108
1189
|
|
|
1109
|
-
function checkSnapshot
|
|
1110
|
-
if (index >= snapshot.state.snapshotCompatLength)
|
|
1190
|
+
function checkSnapshot(snapshot, index) {
|
|
1191
|
+
if (index >= snapshot.state.snapshotCompatLength)
|
|
1192
|
+
throw SNAPSHOT_NOT_AVAILABLE(
|
|
1193
|
+
`snapshot at index ${index} not available (max compat length ${snapshot.state.snapshotCompatLength})`,
|
|
1194
|
+
snapshot.discoveryKey
|
|
1195
|
+
)
|
|
1111
1196
|
}
|
|
1112
1197
|
|
|
1113
|
-
function readBlock
|
|
1198
|
+
function readBlock(rx, index) {
|
|
1114
1199
|
const promise = rx.getBlock(index)
|
|
1115
1200
|
rx.tryFlush()
|
|
1116
1201
|
return promise
|
|
1117
1202
|
}
|
|
1118
1203
|
|
|
1119
|
-
function initOnce
|
|
1204
|
+
function initOnce(session, storage, key, opts) {
|
|
1120
1205
|
if (storage === null) storage = opts.storage || null
|
|
1121
1206
|
if (key === null) key = opts.key || null
|
|
1122
1207
|
|
|
@@ -1139,7 +1224,7 @@ function initOnce (session, storage, key, opts) {
|
|
|
1139
1224
|
})
|
|
1140
1225
|
}
|
|
1141
1226
|
|
|
1142
|
-
function maybeAddMonitor
|
|
1227
|
+
function maybeAddMonitor(name) {
|
|
1143
1228
|
if (name === 'append' || name === 'truncate') return
|
|
1144
1229
|
if (this._monitorIndex >= 0 || this.closing) return
|
|
1145
1230
|
|
|
@@ -1150,21 +1235,21 @@ function maybeAddMonitor (name) {
|
|
|
1150
1235
|
}
|
|
1151
1236
|
}
|
|
1152
1237
|
|
|
1153
|
-
function isSessionMoved
|
|
1238
|
+
function isSessionMoved(err) {
|
|
1154
1239
|
return err.code === 'SESSION_MOVED'
|
|
1155
1240
|
}
|
|
1156
1241
|
|
|
1157
|
-
function getEncryptionOption
|
|
1242
|
+
function getEncryptionOption(opts) {
|
|
1158
1243
|
// old style, supported for now but will go away
|
|
1159
1244
|
if (opts.encryptionKey) return { key: opts.encryptionKey, block: !!opts.isBlockKey }
|
|
1160
1245
|
if (!opts.encryption) return null
|
|
1161
1246
|
return b4a.isBuffer(opts.encryption) ? { key: opts.encryption } : opts.encryption
|
|
1162
1247
|
}
|
|
1163
1248
|
|
|
1164
|
-
function isEncryptionProvider
|
|
1249
|
+
function isEncryptionProvider(e) {
|
|
1165
1250
|
return e && isFunction(e.padding) && isFunction(e.encrypt) && isFunction(e.decrypt)
|
|
1166
1251
|
}
|
|
1167
1252
|
|
|
1168
|
-
function isFunction
|
|
1253
|
+
function isFunction(fn) {
|
|
1169
1254
|
return !!fn && typeof fn === 'function'
|
|
1170
1255
|
}
|