hypercore 10.3.2 → 10.4.1
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 +13 -12
- package/lib/bitfield.js +257 -69
- package/lib/compat.js +11 -0
- package/lib/core.js +1 -1
- package/lib/info.js +11 -12
- package/lib/oplog.js +1 -1
- package/lib/remote-bitfield.js +246 -16
- package/lib/replicator.js +44 -36
- package/package.json +3 -3
package/index.js
CHANGED
|
@@ -429,29 +429,30 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
429
429
|
const protocolStream = Hypercore.createProtocolStream(isInitiator, opts)
|
|
430
430
|
const noiseStream = protocolStream.noiseStream
|
|
431
431
|
const protocol = noiseStream.userData
|
|
432
|
+
const useSession = !!opts.session
|
|
432
433
|
|
|
433
|
-
this._attachToMuxer(protocol,
|
|
434
|
+
this._attachToMuxer(protocol, useSession)
|
|
434
435
|
|
|
435
436
|
return protocolStream
|
|
436
437
|
}
|
|
437
438
|
|
|
438
|
-
_attachToMuxer (mux,
|
|
439
|
-
// If the user wants to, we can make this replication run in a session
|
|
440
|
-
// that way the core wont close "under them" during replication
|
|
441
|
-
if (opts.session) {
|
|
442
|
-
const s = this.session()
|
|
443
|
-
mux.stream.on('close', () => s.close().catch(noop))
|
|
444
|
-
}
|
|
445
|
-
|
|
439
|
+
_attachToMuxer (mux, useSession) {
|
|
446
440
|
if (this.opened) {
|
|
447
|
-
this.
|
|
441
|
+
this._attachToMuxerOpened(mux, useSession)
|
|
448
442
|
} else {
|
|
449
|
-
this.opening.then(
|
|
443
|
+
this.opening.then(this._attachToMuxerOpened.bind(this, mux, useSession), mux.destroy.bind(mux))
|
|
450
444
|
}
|
|
451
445
|
|
|
452
446
|
return mux
|
|
453
447
|
}
|
|
454
448
|
|
|
449
|
+
_attachToMuxerOpened (mux, useSession) {
|
|
450
|
+
// If the user wants to, we can make this replication run in a session
|
|
451
|
+
// that way the core wont close "under them" during replication
|
|
452
|
+
const session = useSession ? this.session() : null
|
|
453
|
+
this.replicator.attachTo(mux, session)
|
|
454
|
+
}
|
|
455
|
+
|
|
455
456
|
get discoveryKey () {
|
|
456
457
|
return this.replicator === null ? null : this.replicator.discoveryKey
|
|
457
458
|
}
|
|
@@ -616,7 +617,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
616
617
|
async info () {
|
|
617
618
|
if (this.opened === false) await this.opening
|
|
618
619
|
|
|
619
|
-
return Info.from(this
|
|
620
|
+
return Info.from(this)
|
|
620
621
|
}
|
|
621
622
|
|
|
622
623
|
async update (opts) {
|
package/lib/bitfield.js
CHANGED
|
@@ -1,99 +1,244 @@
|
|
|
1
1
|
const BigSparseArray = require('big-sparse-array')
|
|
2
2
|
const b4a = require('b4a')
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const quickbit = require('./compat').quickbit
|
|
4
|
+
|
|
5
|
+
const BITS_PER_PAGE = 32768
|
|
6
|
+
const BYTES_PER_PAGE = BITS_PER_PAGE / 8
|
|
7
|
+
const WORDS_PER_PAGE = BYTES_PER_PAGE / 4
|
|
8
|
+
const BITS_PER_SEGMENT = 2097152
|
|
9
|
+
const BYTES_PER_SEGMENT = BITS_PER_SEGMENT / 8
|
|
10
|
+
const WORDS_PER_SEGMENT = BYTES_PER_SEGMENT / 4
|
|
11
|
+
const INITIAL_WORDS_PER_SEGMENT = 1024
|
|
12
|
+
const PAGES_PER_SEGMENT = BITS_PER_SEGMENT / BITS_PER_PAGE
|
|
13
|
+
const SEGMENT_GROWTH_FACTOR = 4
|
|
14
|
+
|
|
15
|
+
class BitfieldPage {
|
|
16
|
+
constructor (index, segment) {
|
|
7
17
|
this.dirty = false
|
|
8
18
|
this.index = index
|
|
9
|
-
this.bitfield =
|
|
19
|
+
this.bitfield = null
|
|
20
|
+
this.segment = segment
|
|
21
|
+
|
|
22
|
+
segment.add(this)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get tree () {
|
|
26
|
+
return this.segment.tree
|
|
10
27
|
}
|
|
11
28
|
|
|
12
29
|
get (index) {
|
|
13
|
-
return
|
|
30
|
+
return quickbit.get(this.bitfield, index)
|
|
14
31
|
}
|
|
15
32
|
|
|
16
33
|
set (index, val) {
|
|
17
|
-
|
|
34
|
+
if (quickbit.set(this.bitfield, index, val)) {
|
|
35
|
+
this.tree.update(this.offset * 8 + index)
|
|
36
|
+
}
|
|
18
37
|
}
|
|
19
38
|
|
|
20
39
|
setRange (start, length, val) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
40
|
+
quickbit.fill(this.bitfield, val, start, start + length)
|
|
41
|
+
|
|
42
|
+
let i = Math.floor(start / 32)
|
|
43
|
+
const n = i + Math.ceil(length / 32)
|
|
44
|
+
|
|
45
|
+
while (i < n) this.tree.update(this.offset * 8 + i++ * 32)
|
|
25
46
|
}
|
|
26
47
|
|
|
27
|
-
|
|
28
|
-
return
|
|
48
|
+
findFirst (val, position) {
|
|
49
|
+
return quickbit.findFirst(this.bitfield, val, position)
|
|
29
50
|
}
|
|
30
51
|
|
|
31
|
-
|
|
32
|
-
return
|
|
52
|
+
findLast (val, position) {
|
|
53
|
+
return quickbit.findLast(this.bitfield, val, position)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class BitfieldSegment {
|
|
58
|
+
constructor (index, bitfield) {
|
|
59
|
+
this.index = index
|
|
60
|
+
this.offset = index * BYTES_PER_SEGMENT
|
|
61
|
+
this.tree = quickbit.Index.from(bitfield)
|
|
62
|
+
this.pages = new Array(PAGES_PER_SEGMENT)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get bitfield () {
|
|
66
|
+
return this.tree.field
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
add (page) {
|
|
70
|
+
const i = page.index - this.index * PAGES_PER_SEGMENT
|
|
71
|
+
this.pages[i] = page
|
|
72
|
+
|
|
73
|
+
const start = i * WORDS_PER_PAGE
|
|
74
|
+
const end = start + WORDS_PER_PAGE
|
|
75
|
+
|
|
76
|
+
if (end >= this.bitfield.length) this.reallocate(end)
|
|
77
|
+
|
|
78
|
+
page.bitfield = this.bitfield.subarray(start, end)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
reallocate (length) {
|
|
82
|
+
let target = this.bitfield.length
|
|
83
|
+
while (target < length) target *= SEGMENT_GROWTH_FACTOR
|
|
84
|
+
|
|
85
|
+
const bitfield = new Uint32Array(target)
|
|
86
|
+
bitfield.set(this.bitfield)
|
|
87
|
+
|
|
88
|
+
this.tree = quickbit.Index.from(bitfield)
|
|
89
|
+
|
|
90
|
+
for (let i = 0; i < this.pages.length; i++) {
|
|
91
|
+
const page = this.pages[i]
|
|
92
|
+
if (!page) continue
|
|
93
|
+
|
|
94
|
+
const start = i * WORDS_PER_PAGE
|
|
95
|
+
const end = start + WORDS_PER_PAGE
|
|
96
|
+
|
|
97
|
+
page.bitfield = bitfield.subarray(start, end)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
findFirst (val, position) {
|
|
102
|
+
position = this.tree.skipFirst(!val, position)
|
|
103
|
+
|
|
104
|
+
const j = position & (BITS_PER_PAGE - 1)
|
|
105
|
+
const i = (position - j) / BITS_PER_PAGE
|
|
106
|
+
|
|
107
|
+
if (i >= PAGES_PER_SEGMENT) return -1
|
|
108
|
+
|
|
109
|
+
const p = this.pages[i]
|
|
110
|
+
|
|
111
|
+
if (p) {
|
|
112
|
+
const index = p.findFirst(val, j)
|
|
113
|
+
|
|
114
|
+
if (index !== -1) {
|
|
115
|
+
return i * BITS_PER_PAGE + index
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return -1
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
findLast (val, position) {
|
|
123
|
+
position = this.tree.skipLast(!val, position)
|
|
124
|
+
|
|
125
|
+
const j = position & (BITS_PER_PAGE - 1)
|
|
126
|
+
const i = (position - j) / BITS_PER_PAGE
|
|
127
|
+
|
|
128
|
+
if (i >= PAGES_PER_SEGMENT) return -1
|
|
129
|
+
|
|
130
|
+
const p = this.pages[i]
|
|
131
|
+
|
|
132
|
+
if (p) {
|
|
133
|
+
const index = p.findLast(val, j)
|
|
134
|
+
|
|
135
|
+
if (index !== -1) {
|
|
136
|
+
return i * BITS_PER_PAGE + index
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return -1
|
|
33
141
|
}
|
|
34
142
|
}
|
|
35
143
|
|
|
36
144
|
module.exports = class Bitfield {
|
|
37
|
-
constructor (storage,
|
|
38
|
-
this.pageSize = 32768
|
|
39
|
-
this.pages = new BigSparseArray()
|
|
145
|
+
constructor (storage, buffer) {
|
|
40
146
|
this.unflushed = []
|
|
41
147
|
this.storage = storage
|
|
42
|
-
this.resumed = !!(
|
|
148
|
+
this.resumed = !!(buffer && buffer.byteLength >= 4)
|
|
149
|
+
|
|
150
|
+
this._pages = new BigSparseArray()
|
|
151
|
+
this._segments = new BigSparseArray()
|
|
152
|
+
|
|
153
|
+
const view = this.resumed
|
|
154
|
+
? new Uint32Array(
|
|
155
|
+
buffer.buffer,
|
|
156
|
+
buffer.byteOffset,
|
|
157
|
+
Math.floor(buffer.byteLength / 4)
|
|
158
|
+
)
|
|
159
|
+
: new Uint32Array(INITIAL_WORDS_PER_SEGMENT)
|
|
160
|
+
|
|
161
|
+
for (let i = 0; i < view.length; i += WORDS_PER_SEGMENT) {
|
|
162
|
+
let bitfield = view.subarray(i, i + (WORDS_PER_SEGMENT))
|
|
163
|
+
let length = WORDS_PER_SEGMENT
|
|
164
|
+
|
|
165
|
+
if (i === 0) {
|
|
166
|
+
length = INITIAL_WORDS_PER_SEGMENT
|
|
167
|
+
while (length < bitfield.length) length *= SEGMENT_GROWTH_FACTOR
|
|
168
|
+
}
|
|
43
169
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
170
|
+
if (bitfield.length !== length) {
|
|
171
|
+
const copy = new Uint32Array(length)
|
|
172
|
+
copy.set(bitfield, 0)
|
|
173
|
+
bitfield = copy
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const segment = new BitfieldSegment(i / (WORDS_PER_SEGMENT), bitfield)
|
|
177
|
+
this._segments.set(segment.index, segment)
|
|
47
178
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
179
|
+
for (let j = 0; j < bitfield.length; j += WORDS_PER_PAGE) {
|
|
180
|
+
const page = new BitfieldPage((i + j) / WORDS_PER_PAGE, segment)
|
|
181
|
+
this._pages.set(page.index, page)
|
|
182
|
+
}
|
|
52
183
|
}
|
|
53
184
|
}
|
|
54
185
|
|
|
55
186
|
get (index) {
|
|
56
|
-
const j = index & (
|
|
57
|
-
const i = (index - j) /
|
|
187
|
+
const j = index & (BITS_PER_PAGE - 1)
|
|
188
|
+
const i = (index - j) / BITS_PER_PAGE
|
|
58
189
|
|
|
59
|
-
const p = this.
|
|
190
|
+
const p = this._pages.get(i)
|
|
60
191
|
|
|
61
192
|
return p ? p.get(j) : false
|
|
62
193
|
}
|
|
63
194
|
|
|
64
195
|
set (index, val) {
|
|
65
|
-
const j = index & (
|
|
66
|
-
const i = (index - j) /
|
|
196
|
+
const j = index & (BITS_PER_PAGE - 1)
|
|
197
|
+
const i = (index - j) / BITS_PER_PAGE
|
|
67
198
|
|
|
68
|
-
let p = this.
|
|
199
|
+
let p = this._pages.get(i)
|
|
69
200
|
|
|
70
201
|
if (!p && val) {
|
|
71
|
-
|
|
202
|
+
const k = Math.floor(i / PAGES_PER_SEGMENT)
|
|
203
|
+
const s = this._segments.get(k) || this._segments.set(k, new BitfieldSegment(k, new Uint32Array(k === 0 ? INITIAL_WORDS_PER_SEGMENT : WORDS_PER_SEGMENT)))
|
|
204
|
+
|
|
205
|
+
p = this._pages.set(i, new BitfieldPage(i, s))
|
|
72
206
|
}
|
|
73
207
|
|
|
74
|
-
if (p
|
|
75
|
-
p.
|
|
76
|
-
|
|
208
|
+
if (p) {
|
|
209
|
+
p.set(j, val)
|
|
210
|
+
|
|
211
|
+
if (!p.dirty) {
|
|
212
|
+
p.dirty = true
|
|
213
|
+
this.unflushed.push(p)
|
|
214
|
+
}
|
|
77
215
|
}
|
|
78
216
|
}
|
|
79
217
|
|
|
80
218
|
setRange (start, length, val) {
|
|
81
|
-
let j = start & (
|
|
82
|
-
let i = (start - j) /
|
|
219
|
+
let j = start & (BITS_PER_PAGE - 1)
|
|
220
|
+
let i = (start - j) / BITS_PER_PAGE
|
|
83
221
|
|
|
84
222
|
while (length > 0) {
|
|
85
|
-
let p = this.
|
|
223
|
+
let p = this._pages.get(i)
|
|
86
224
|
|
|
87
225
|
if (!p && val) {
|
|
88
|
-
|
|
226
|
+
const k = Math.floor(i / PAGES_PER_SEGMENT)
|
|
227
|
+
const s = this._segments.get(k) || this._segments.set(k, new BitfieldSegment(k, new Uint32Array(k === 0 ? INITIAL_WORDS_PER_SEGMENT : WORDS_PER_SEGMENT)))
|
|
228
|
+
|
|
229
|
+
p = this._pages.set(i, new BitfieldPage(i, s))
|
|
89
230
|
}
|
|
90
231
|
|
|
91
|
-
const end = Math.min(j + length,
|
|
232
|
+
const end = Math.min(j + length, BITS_PER_PAGE)
|
|
92
233
|
const range = end - j
|
|
93
234
|
|
|
94
|
-
if (p
|
|
95
|
-
p.
|
|
96
|
-
|
|
235
|
+
if (p) {
|
|
236
|
+
p.setRange(j, range, val)
|
|
237
|
+
|
|
238
|
+
if (!p.dirty) {
|
|
239
|
+
p.dirty = true
|
|
240
|
+
this.unflushed.push(p)
|
|
241
|
+
}
|
|
97
242
|
}
|
|
98
243
|
|
|
99
244
|
j = 0
|
|
@@ -102,18 +247,18 @@ module.exports = class Bitfield {
|
|
|
102
247
|
}
|
|
103
248
|
}
|
|
104
249
|
|
|
105
|
-
|
|
106
|
-
let j = position & (
|
|
107
|
-
let i = (position - j) /
|
|
250
|
+
findFirst (val, position) {
|
|
251
|
+
let j = position & (BITS_PER_SEGMENT - 1)
|
|
252
|
+
let i = (position - j) / BITS_PER_SEGMENT
|
|
108
253
|
|
|
109
|
-
while (i < this.
|
|
110
|
-
const
|
|
254
|
+
while (i < this._segments.maxLength) {
|
|
255
|
+
const s = this._segments.get(i)
|
|
111
256
|
|
|
112
|
-
if (
|
|
113
|
-
const index =
|
|
257
|
+
if (s) {
|
|
258
|
+
const index = s.findFirst(val, j)
|
|
114
259
|
|
|
115
260
|
if (index !== -1) {
|
|
116
|
-
return i *
|
|
261
|
+
return i * BITS_PER_SEGMENT + index
|
|
117
262
|
}
|
|
118
263
|
}
|
|
119
264
|
|
|
@@ -124,33 +269,72 @@ module.exports = class Bitfield {
|
|
|
124
269
|
return -1
|
|
125
270
|
}
|
|
126
271
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
272
|
+
firstSet (position) {
|
|
273
|
+
return this.findFirst(true, position)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
firstUnset (position) {
|
|
277
|
+
return this.findFirst(false, position)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
findLast (val, position) {
|
|
281
|
+
let j = position & (BITS_PER_SEGMENT - 1)
|
|
282
|
+
let i = (position - j) / BITS_PER_SEGMENT
|
|
130
283
|
|
|
131
284
|
while (i >= 0) {
|
|
132
|
-
const
|
|
285
|
+
const s = this._segments.get(i)
|
|
133
286
|
|
|
134
|
-
if (
|
|
135
|
-
const index =
|
|
287
|
+
if (s) {
|
|
288
|
+
const index = s.findLast(val, j)
|
|
136
289
|
|
|
137
290
|
if (index !== -1) {
|
|
138
|
-
return i *
|
|
291
|
+
return i * BITS_PER_SEGMENT + index
|
|
139
292
|
}
|
|
140
293
|
}
|
|
141
294
|
|
|
142
|
-
j =
|
|
295
|
+
j = BITS_PER_SEGMENT - 1
|
|
143
296
|
i--
|
|
144
297
|
}
|
|
145
298
|
|
|
146
299
|
return -1
|
|
147
300
|
}
|
|
148
301
|
|
|
302
|
+
lastSet (position) {
|
|
303
|
+
return this.findLast(true, position)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
lastUnset (position) {
|
|
307
|
+
return this.findLast(false, position)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
* want (start, length) {
|
|
311
|
+
const j = start & (BITS_PER_SEGMENT - 1)
|
|
312
|
+
let i = (start - j) / BITS_PER_SEGMENT
|
|
313
|
+
|
|
314
|
+
while (length > 0) {
|
|
315
|
+
const s = this._segments.get(i)
|
|
316
|
+
|
|
317
|
+
if (s) {
|
|
318
|
+
// We always send at least 4 KiB worth of bitfield in a want, rounding
|
|
319
|
+
// to the nearest 4 KiB.
|
|
320
|
+
const end = ceilTo(clamp(length / 8, 4096, BYTES_PER_SEGMENT), 4096)
|
|
321
|
+
|
|
322
|
+
yield {
|
|
323
|
+
start: i * BITS_PER_SEGMENT,
|
|
324
|
+
bitfield: s.bitfield.subarray(0, end / 4)
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
i++
|
|
329
|
+
length -= BITS_PER_SEGMENT
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
149
333
|
clear () {
|
|
150
334
|
return new Promise((resolve, reject) => {
|
|
151
335
|
this.storage.truncate(0, (err) => {
|
|
152
336
|
if (err) return reject(err)
|
|
153
|
-
this.
|
|
337
|
+
this._pages = new BigSparseArray()
|
|
154
338
|
this.unflushed = []
|
|
155
339
|
resolve()
|
|
156
340
|
})
|
|
@@ -182,7 +366,7 @@ module.exports = class Bitfield {
|
|
|
182
366
|
)
|
|
183
367
|
|
|
184
368
|
page.dirty = false
|
|
185
|
-
this.storage.write(page.index *
|
|
369
|
+
this.storage.write(page.index * BYTES_PER_PAGE, buf, done)
|
|
186
370
|
}
|
|
187
371
|
|
|
188
372
|
function done (err) {
|
|
@@ -195,12 +379,13 @@ module.exports = class Bitfield {
|
|
|
195
379
|
})
|
|
196
380
|
}
|
|
197
381
|
|
|
198
|
-
static open (storage) {
|
|
382
|
+
static open (storage, tree = null) {
|
|
199
383
|
return new Promise((resolve, reject) => {
|
|
200
384
|
storage.stat((err, st) => {
|
|
201
385
|
if (err) return resolve(new Bitfield(storage, null))
|
|
202
|
-
|
|
386
|
+
let size = st.size - (st.size & 3)
|
|
203
387
|
if (!size) return resolve(new Bitfield(storage, null))
|
|
388
|
+
if (tree) size = Math.min(size, ceilTo(tree.length / 8, 4096))
|
|
204
389
|
storage.read(0, size, (err, data) => {
|
|
205
390
|
if (err) return reject(err)
|
|
206
391
|
resolve(new Bitfield(storage, data))
|
|
@@ -210,9 +395,12 @@ module.exports = class Bitfield {
|
|
|
210
395
|
}
|
|
211
396
|
}
|
|
212
397
|
|
|
213
|
-
function
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
398
|
+
function clamp (n, min, max) {
|
|
399
|
+
return Math.min(Math.max(n, min), max)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function ceilTo (n, multiple = 1) {
|
|
403
|
+
const remainder = n % multiple
|
|
404
|
+
if (remainder === 0) return n
|
|
405
|
+
return n + multiple - remainder
|
|
218
406
|
}
|
package/lib/compat.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Export the appropriate version of `quickbit-universal` as the plain import
|
|
2
|
+
// may resolve to an older version in some environments
|
|
3
|
+
let quickbit = require('quickbit-universal')
|
|
4
|
+
if (
|
|
5
|
+
typeof quickbit.findFirst !== 'function' ||
|
|
6
|
+
typeof quickbit.findLast !== 'function'
|
|
7
|
+
) {
|
|
8
|
+
// This should always load the fallback from the locally installed version
|
|
9
|
+
quickbit = require('quickbit-universal/fallback')
|
|
10
|
+
}
|
|
11
|
+
exports.quickbit = quickbit
|
package/lib/core.js
CHANGED
|
@@ -108,7 +108,7 @@ module.exports = class Core {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
const tree = await MerkleTree.open(treeFile, { crypto, ...header.tree })
|
|
111
|
-
const bitfield = await Bitfield.open(bitfieldFile)
|
|
111
|
+
const bitfield = await Bitfield.open(bitfieldFile, tree)
|
|
112
112
|
const blocks = new BlockStore(dataFile, tree)
|
|
113
113
|
|
|
114
114
|
if (overwrite) {
|
package/lib/info.js
CHANGED
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
module.exports = class Info {
|
|
2
2
|
constructor (opts = {}) {
|
|
3
|
+
this.key = opts.key
|
|
4
|
+
this.discoveryKey = opts.discoveryKey
|
|
3
5
|
this.length = opts.length || 0
|
|
4
6
|
this.contiguousLength = opts.contiguousLength || 0
|
|
5
7
|
this.byteLength = opts.byteLength || 0
|
|
8
|
+
this.fork = opts.fork || 0
|
|
6
9
|
this.padding = opts.padding || 0
|
|
7
10
|
}
|
|
8
11
|
|
|
9
|
-
static async from (
|
|
12
|
+
static async from (session) {
|
|
10
13
|
return new Info({
|
|
11
|
-
key:
|
|
12
|
-
discoveryKey:
|
|
13
|
-
length:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
? snapshot.byteLength
|
|
19
|
-
: (core.tree.byteLength - (core.tree.length * padding)),
|
|
20
|
-
fork: core.tree.fork,
|
|
21
|
-
padding
|
|
14
|
+
key: session.key,
|
|
15
|
+
discoveryKey: session.discoveryKey,
|
|
16
|
+
length: session.length,
|
|
17
|
+
contiguousLength: session.contiguousLength,
|
|
18
|
+
byteLength: session.byteLength,
|
|
19
|
+
fork: session.fork,
|
|
20
|
+
padding: session.padding
|
|
22
21
|
})
|
|
23
22
|
}
|
|
24
23
|
}
|
package/lib/oplog.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const cenc = require('compact-encoding')
|
|
2
2
|
const b4a = require('b4a')
|
|
3
|
-
const crc32 = require('
|
|
3
|
+
const { crc32 } = require('crc-universal')
|
|
4
4
|
|
|
5
5
|
module.exports = class Oplog {
|
|
6
6
|
constructor (storage, { pageSize = 4096, headerEncoding = cenc.raw, entryEncoding = cenc.raw } = {}) {
|
package/lib/remote-bitfield.js
CHANGED
|
@@ -1,45 +1,275 @@
|
|
|
1
1
|
const BigSparseArray = require('big-sparse-array')
|
|
2
|
-
const
|
|
2
|
+
const quickbit = require('./compat').quickbit
|
|
3
|
+
|
|
4
|
+
const BITS_PER_PAGE = 32768
|
|
5
|
+
const BYTES_PER_PAGE = BITS_PER_PAGE / 8
|
|
6
|
+
const WORDS_PER_PAGE = BYTES_PER_PAGE / 4
|
|
7
|
+
const BITS_PER_SEGMENT = 2097152
|
|
8
|
+
const BYTES_PER_SEGMENT = BITS_PER_SEGMENT / 8
|
|
9
|
+
const PAGES_PER_SEGMENT = BITS_PER_SEGMENT / BITS_PER_PAGE
|
|
10
|
+
|
|
11
|
+
class RemoteBitfieldPage {
|
|
12
|
+
constructor (index, bitfield, segment) {
|
|
13
|
+
this.index = index
|
|
14
|
+
this.offset = index * BYTES_PER_PAGE - segment.offset
|
|
15
|
+
this.bitfield = bitfield
|
|
16
|
+
this.segment = segment
|
|
17
|
+
|
|
18
|
+
segment.add(this)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get tree () {
|
|
22
|
+
return this.segment.tree
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get (index) {
|
|
26
|
+
return quickbit.get(this.bitfield, index)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
set (index, val) {
|
|
30
|
+
if (quickbit.set(this.bitfield, index, val)) {
|
|
31
|
+
this.tree.update(this.offset * 8 + index)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setRange (start, length, val) {
|
|
36
|
+
quickbit.fill(this.bitfield, val, start, start + length)
|
|
37
|
+
|
|
38
|
+
let i = Math.floor(start / 32)
|
|
39
|
+
const n = i + Math.ceil(length / 32)
|
|
40
|
+
|
|
41
|
+
while (i < n) this.tree.update(this.offset * 8 + i++ * 32)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
findFirst (val, position) {
|
|
45
|
+
return quickbit.findFirst(this.bitfield, val, position)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
findLast (val, position) {
|
|
49
|
+
return quickbit.findLast(this.bitfield, val, position)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
insert (start, bitfield) {
|
|
53
|
+
this.bitfield.set(bitfield, start / 32)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class RemoteBitfieldSegment {
|
|
58
|
+
constructor (index) {
|
|
59
|
+
this.index = index
|
|
60
|
+
this.offset = index * BYTES_PER_SEGMENT
|
|
61
|
+
this.tree = quickbit.Index.from([])
|
|
62
|
+
this.pages = new Array(PAGES_PER_SEGMENT)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get chunks () {
|
|
66
|
+
return this.tree.chunks
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
add (page) {
|
|
70
|
+
this.pages[page.index - this.index * PAGES_PER_SEGMENT] = page
|
|
71
|
+
|
|
72
|
+
const chunk = { field: page.bitfield, offset: page.offset }
|
|
73
|
+
|
|
74
|
+
this.chunks.push(chunk)
|
|
75
|
+
|
|
76
|
+
for (let i = this.chunks.length - 2; i >= 0; i--) {
|
|
77
|
+
const prev = this.chunks[i]
|
|
78
|
+
if (prev.offset <= chunk.offset) break
|
|
79
|
+
this.chunks[i] = chunk
|
|
80
|
+
this.chunks[i + 1] = prev
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
findFirst (val, position) {
|
|
85
|
+
position = this.tree.skipFirst(!val, position)
|
|
86
|
+
|
|
87
|
+
const j = position & (BITS_PER_PAGE - 1)
|
|
88
|
+
const i = (position - j) / BITS_PER_PAGE
|
|
89
|
+
|
|
90
|
+
if (i >= PAGES_PER_SEGMENT) return -1
|
|
91
|
+
|
|
92
|
+
const p = this.pages[i]
|
|
93
|
+
|
|
94
|
+
if (p) {
|
|
95
|
+
const index = p.findFirst(val, j)
|
|
96
|
+
|
|
97
|
+
if (index !== -1) {
|
|
98
|
+
return i * BITS_PER_PAGE + index
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return -1
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
findLast (val, position) {
|
|
106
|
+
position = this.tree.skipLast(!val, position)
|
|
107
|
+
|
|
108
|
+
const j = position & (BITS_PER_PAGE - 1)
|
|
109
|
+
const i = (position - j) / BITS_PER_PAGE
|
|
110
|
+
|
|
111
|
+
if (i >= PAGES_PER_SEGMENT) return -1
|
|
112
|
+
|
|
113
|
+
const p = this.pages[i]
|
|
114
|
+
|
|
115
|
+
if (p) {
|
|
116
|
+
const index = p.findLast(val, j)
|
|
117
|
+
|
|
118
|
+
if (index !== -1) {
|
|
119
|
+
return i * BITS_PER_PAGE + index
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return -1
|
|
124
|
+
}
|
|
125
|
+
}
|
|
3
126
|
|
|
4
127
|
module.exports = class RemoteBitfield {
|
|
5
128
|
constructor () {
|
|
6
|
-
this.
|
|
7
|
-
this.
|
|
129
|
+
this._pages = new BigSparseArray()
|
|
130
|
+
this._segments = new BigSparseArray()
|
|
8
131
|
}
|
|
9
132
|
|
|
10
133
|
get (index) {
|
|
11
|
-
const j = index & (
|
|
12
|
-
const i = (index - j) /
|
|
134
|
+
const j = index & (BITS_PER_PAGE - 1)
|
|
135
|
+
const i = (index - j) / BITS_PER_PAGE
|
|
13
136
|
|
|
14
|
-
const p = this.
|
|
137
|
+
const p = this._pages.get(i)
|
|
15
138
|
|
|
16
|
-
return p ?
|
|
139
|
+
return p ? p.get(j) : false
|
|
17
140
|
}
|
|
18
141
|
|
|
19
142
|
set (index, val) {
|
|
20
|
-
const j = index & (
|
|
21
|
-
const i = (index - j) /
|
|
143
|
+
const j = index & (BITS_PER_PAGE - 1)
|
|
144
|
+
const i = (index - j) / BITS_PER_PAGE
|
|
22
145
|
|
|
23
|
-
|
|
146
|
+
let p = this._pages.get(i)
|
|
24
147
|
|
|
25
|
-
|
|
148
|
+
if (!p && val) {
|
|
149
|
+
const k = Math.floor(i / PAGES_PER_SEGMENT)
|
|
150
|
+
const s = this._segments.get(k) || this._segments.set(k, new RemoteBitfieldSegment(k))
|
|
151
|
+
|
|
152
|
+
p = this._pages.set(i, new RemoteBitfieldPage(i, new Uint32Array(WORDS_PER_PAGE), s))
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (p) p.set(j, val)
|
|
26
156
|
}
|
|
27
157
|
|
|
28
158
|
setRange (start, length, val) {
|
|
29
|
-
let j = start & (
|
|
30
|
-
let i = (start - j) /
|
|
159
|
+
let j = start & (BITS_PER_PAGE - 1)
|
|
160
|
+
let i = (start - j) / BITS_PER_PAGE
|
|
31
161
|
|
|
32
162
|
while (length > 0) {
|
|
33
|
-
|
|
163
|
+
let p = this._pages.get(i)
|
|
164
|
+
|
|
165
|
+
if (!p && val) {
|
|
166
|
+
const k = Math.floor(i / PAGES_PER_SEGMENT)
|
|
167
|
+
const s = this._segments.get(k) || this._segments.set(k, new RemoteBitfieldSegment(k))
|
|
168
|
+
|
|
169
|
+
p = this._pages.set(i, new RemoteBitfieldPage(i, new Uint32Array(WORDS_PER_PAGE), s))
|
|
170
|
+
}
|
|
34
171
|
|
|
35
|
-
const end = Math.min(j + length,
|
|
172
|
+
const end = Math.min(j + length, BITS_PER_PAGE)
|
|
36
173
|
const range = end - j
|
|
37
174
|
|
|
38
|
-
|
|
175
|
+
if (p) p.setRange(j, range, val)
|
|
39
176
|
|
|
40
177
|
j = 0
|
|
41
178
|
i++
|
|
42
179
|
length -= range
|
|
43
180
|
}
|
|
44
181
|
}
|
|
182
|
+
|
|
183
|
+
findFirst (val, position) {
|
|
184
|
+
let j = position & (BITS_PER_SEGMENT - 1)
|
|
185
|
+
let i = (position - j) / BITS_PER_SEGMENT
|
|
186
|
+
|
|
187
|
+
while (i < this._segments.maxLength) {
|
|
188
|
+
const s = this._segments.get(i)
|
|
189
|
+
|
|
190
|
+
if (s) {
|
|
191
|
+
const index = s.findFirst(val, j)
|
|
192
|
+
|
|
193
|
+
if (index !== -1) {
|
|
194
|
+
return i * BITS_PER_SEGMENT + index
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
j = 0
|
|
199
|
+
i++
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return -1
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
firstSet (position) {
|
|
206
|
+
return this.findFirst(true, position)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
firstUnset (position) {
|
|
210
|
+
return this.findFirst(false, position)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
findLast (val, position) {
|
|
214
|
+
let j = position & (BITS_PER_SEGMENT - 1)
|
|
215
|
+
let i = (position - j) / BITS_PER_SEGMENT
|
|
216
|
+
|
|
217
|
+
while (i >= 0) {
|
|
218
|
+
const s = this._segments.get(i)
|
|
219
|
+
|
|
220
|
+
if (s) {
|
|
221
|
+
const index = s.findLast(val, j)
|
|
222
|
+
|
|
223
|
+
if (index !== -1) {
|
|
224
|
+
return i * BITS_PER_SEGMENT + index
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
j = BITS_PER_SEGMENT - 1
|
|
229
|
+
i--
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return -1
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
lastSet (position) {
|
|
236
|
+
return this.findLast(true, position)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
lastUnset (position) {
|
|
240
|
+
return this.findLast(false, position)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
insert (start, bitfield) {
|
|
244
|
+
if (start % 32 !== 0) return false
|
|
245
|
+
|
|
246
|
+
let length = bitfield.byteLength * 8
|
|
247
|
+
|
|
248
|
+
let j = start & (BITS_PER_PAGE - 1)
|
|
249
|
+
let i = (start - j) / BITS_PER_PAGE
|
|
250
|
+
|
|
251
|
+
while (length > 0) {
|
|
252
|
+
let p = this._pages.get(i)
|
|
253
|
+
|
|
254
|
+
if (!p) {
|
|
255
|
+
const k = Math.floor(i / PAGES_PER_SEGMENT)
|
|
256
|
+
const s = this._segments.get(k) || this._segments.set(k, new RemoteBitfieldSegment(k))
|
|
257
|
+
|
|
258
|
+
p = this._pages.set(i, new RemoteBitfieldPage(i, new Uint32Array(WORDS_PER_PAGE), s))
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const end = Math.min(j + length, BITS_PER_PAGE)
|
|
262
|
+
const range = end - j
|
|
263
|
+
|
|
264
|
+
p.insert(j, bitfield.subarray(0, range / 32))
|
|
265
|
+
|
|
266
|
+
bitfield = bitfield.subarray(range / 32)
|
|
267
|
+
|
|
268
|
+
j = 0
|
|
269
|
+
i++
|
|
270
|
+
length -= range
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return true
|
|
274
|
+
}
|
|
45
275
|
}
|
package/lib/replicator.js
CHANGED
|
@@ -243,13 +243,15 @@ class BlockTracker {
|
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
class Peer {
|
|
246
|
-
constructor (replicator, protomux, channel) {
|
|
246
|
+
constructor (replicator, protomux, channel, session) {
|
|
247
247
|
this.core = replicator.core
|
|
248
248
|
this.replicator = replicator
|
|
249
249
|
this.stream = protomux.stream
|
|
250
250
|
this.protomux = protomux
|
|
251
251
|
this.remotePublicKey = this.stream.remotePublicKey
|
|
252
252
|
|
|
253
|
+
this.session = session
|
|
254
|
+
|
|
253
255
|
this.channel = channel
|
|
254
256
|
this.channel.userData = this
|
|
255
257
|
|
|
@@ -376,6 +378,8 @@ class Peer {
|
|
|
376
378
|
}
|
|
377
379
|
|
|
378
380
|
onclose (isRemote) {
|
|
381
|
+
if (this.session) this.session.close().catch(noop)
|
|
382
|
+
|
|
379
383
|
if (this.remoteOpened === false) {
|
|
380
384
|
this.replicator._ifAvailable--
|
|
381
385
|
this.replicator.updateAll()
|
|
@@ -570,17 +574,9 @@ class Peer {
|
|
|
570
574
|
}
|
|
571
575
|
|
|
572
576
|
onbitfield ({ start, bitfield }) {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
if (bitfield.length < 1024) {
|
|
576
|
-
const buf = b4a.from(bitfield.buffer, bitfield.byteOffset, bitfield.byteLength)
|
|
577
|
-
const bigger = b4a.concat([buf, b4a.alloc(4096 - buf.length)])
|
|
578
|
-
bitfield = new Uint32Array(bigger.buffer, bigger.byteOffset, 1024)
|
|
577
|
+
if (this.remoteBitfield.insert(start, bitfield)) {
|
|
578
|
+
this._update()
|
|
579
579
|
}
|
|
580
|
-
|
|
581
|
-
this.remoteBitfield.pages.set(start / this.core.bitfield.pageSize, bitfield)
|
|
582
|
-
|
|
583
|
-
this._update()
|
|
584
580
|
}
|
|
585
581
|
|
|
586
582
|
onrange ({ drop, start, length }) {
|
|
@@ -1219,8 +1215,7 @@ module.exports = class Replicator {
|
|
|
1219
1215
|
for (let i = 0; i < this._ranges.length; i++) {
|
|
1220
1216
|
const r = this._ranges[i]
|
|
1221
1217
|
|
|
1222
|
-
|
|
1223
|
-
while (r.start < r.end && this.core.bitfield.get(mapIndex(r.blocks, r.end - 1)) === true) r.end--
|
|
1218
|
+
clampRange(this.core, r)
|
|
1224
1219
|
|
|
1225
1220
|
if (r.end !== -1 && r.start >= r.end) {
|
|
1226
1221
|
this._resolveRangeRequest(r, i--)
|
|
@@ -1332,18 +1327,8 @@ module.exports = class Replicator {
|
|
|
1332
1327
|
|
|
1333
1328
|
peer.protomux.cork()
|
|
1334
1329
|
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
for (; i < n; i++) {
|
|
1339
|
-
const p = this.core.bitfield.pages.get(i)
|
|
1340
|
-
|
|
1341
|
-
if (p) {
|
|
1342
|
-
peer.wireBitfield.send({
|
|
1343
|
-
start: i * this.core.bitfield.pageSize,
|
|
1344
|
-
bitfield: p.bitfield
|
|
1345
|
-
})
|
|
1346
|
-
}
|
|
1330
|
+
for (const msg of this.core.bitfield.want(start, length)) {
|
|
1331
|
+
peer.wireBitfield.send(msg)
|
|
1347
1332
|
}
|
|
1348
1333
|
|
|
1349
1334
|
peer.protomux.uncork()
|
|
@@ -1525,21 +1510,21 @@ module.exports = class Replicator {
|
|
|
1525
1510
|
this._maybeResolveIfAvailableRanges()
|
|
1526
1511
|
}
|
|
1527
1512
|
|
|
1528
|
-
attachTo (protomux) {
|
|
1529
|
-
const makePeer = this._makePeer.bind(this, protomux)
|
|
1513
|
+
attachTo (protomux, session) {
|
|
1514
|
+
const makePeer = this._makePeer.bind(this, protomux, session)
|
|
1530
1515
|
|
|
1531
1516
|
protomux.pair({ protocol: 'hypercore/alpha', id: this.discoveryKey }, makePeer)
|
|
1532
|
-
|
|
1533
1517
|
this._ifAvailable++
|
|
1534
1518
|
protomux.stream.opened.then((opened) => {
|
|
1535
1519
|
this._ifAvailable--
|
|
1536
1520
|
if (opened) makePeer()
|
|
1521
|
+
else if (session) session.close().catch(noop)
|
|
1537
1522
|
this._checkUpgradeIfAvailable()
|
|
1538
1523
|
})
|
|
1539
1524
|
}
|
|
1540
1525
|
|
|
1541
|
-
_makePeer (protomux) {
|
|
1542
|
-
if (protomux.opened({ protocol: 'hypercore/alpha', id: this.discoveryKey })) return
|
|
1526
|
+
_makePeer (protomux, session) {
|
|
1527
|
+
if (protomux.opened({ protocol: 'hypercore/alpha', id: this.discoveryKey })) return onnochannel()
|
|
1543
1528
|
|
|
1544
1529
|
const channel = protomux.createChannel({
|
|
1545
1530
|
userData: null,
|
|
@@ -1563,9 +1548,9 @@ module.exports = class Replicator {
|
|
|
1563
1548
|
onclose: onwireclose
|
|
1564
1549
|
})
|
|
1565
1550
|
|
|
1566
|
-
if (channel === null) return
|
|
1551
|
+
if (channel === null) return onnochannel()
|
|
1567
1552
|
|
|
1568
|
-
const peer = new Peer(this, protomux, channel)
|
|
1553
|
+
const peer = new Peer(this, protomux, channel, session)
|
|
1569
1554
|
const stream = protomux.stream
|
|
1570
1555
|
|
|
1571
1556
|
peer.channel.open({
|
|
@@ -1573,6 +1558,11 @@ module.exports = class Replicator {
|
|
|
1573
1558
|
})
|
|
1574
1559
|
|
|
1575
1560
|
return true
|
|
1561
|
+
|
|
1562
|
+
function onnochannel () {
|
|
1563
|
+
if (session) session.close().catch(noop)
|
|
1564
|
+
return false
|
|
1565
|
+
}
|
|
1576
1566
|
}
|
|
1577
1567
|
}
|
|
1578
1568
|
|
|
@@ -1592,16 +1582,34 @@ function removeInflight (inf, req) {
|
|
|
1592
1582
|
return true
|
|
1593
1583
|
}
|
|
1594
1584
|
|
|
1595
|
-
function mapIndex (blocks, index) {
|
|
1596
|
-
return blocks === null ? index : blocks[index]
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1599
1585
|
function noop () {}
|
|
1600
1586
|
|
|
1601
1587
|
function toLength (start, end) {
|
|
1602
1588
|
return end === -1 ? -1 : (end < start ? 0 : end - start)
|
|
1603
1589
|
}
|
|
1604
1590
|
|
|
1591
|
+
function clampRange (core, r) {
|
|
1592
|
+
if (r.blocks === null) {
|
|
1593
|
+
const start = core.bitfield.firstUnset(r.start)
|
|
1594
|
+
|
|
1595
|
+
if (r.end === -1) {
|
|
1596
|
+
r.start = start === -1 ? core.tree.length : start
|
|
1597
|
+
} else {
|
|
1598
|
+
const end = core.bitfield.lastUnset(r.end - 1) + 1
|
|
1599
|
+
|
|
1600
|
+
if (start === -1) {
|
|
1601
|
+
r.start = r.end
|
|
1602
|
+
} else {
|
|
1603
|
+
r.start = start
|
|
1604
|
+
r.end = end
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
} else {
|
|
1608
|
+
while (r.start < r.end && core.bitfield.get(r.blocks[r.start])) r.start++
|
|
1609
|
+
while (r.start < r.end && core.bitfield.get(r.blocks[r.end - 1])) r.end--
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1605
1613
|
function onwireopen (m, c) {
|
|
1606
1614
|
return c.userData.onopen(m)
|
|
1607
1615
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hypercore",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.4.1",
|
|
4
4
|
"description": "Hypercore is a secure, distributed append-only log",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -36,14 +36,14 @@
|
|
|
36
36
|
"@hyperswarm/secret-stream": "^6.0.0",
|
|
37
37
|
"b4a": "^1.1.0",
|
|
38
38
|
"big-sparse-array": "^1.0.2",
|
|
39
|
-
"bits-to-bytes": "^1.3.0",
|
|
40
39
|
"compact-encoding": "^2.11.0",
|
|
41
|
-
"
|
|
40
|
+
"crc-universal": "^1.0.2",
|
|
42
41
|
"events": "^3.3.0",
|
|
43
42
|
"flat-tree": "^1.9.0",
|
|
44
43
|
"hypercore-crypto": "^3.2.1",
|
|
45
44
|
"is-options": "^1.0.1",
|
|
46
45
|
"protomux": "^3.4.0",
|
|
46
|
+
"quickbit-universal": "^2.0.3",
|
|
47
47
|
"random-access-file": "^4.0.0",
|
|
48
48
|
"random-array-iterator": "^1.0.0",
|
|
49
49
|
"safety-catch": "^1.0.1",
|