hypercore 11.16.2 → 11.18.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 +153 -155
- 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/inspect.js +50 -0
- 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/lib/audit.js
CHANGED
|
@@ -3,9 +3,20 @@ const flat = require('flat-tree')
|
|
|
3
3
|
const b4a = require('b4a')
|
|
4
4
|
const { MerkleTree } = require('./merkle-tree')
|
|
5
5
|
|
|
6
|
-
module.exports = async function auditCore
|
|
6
|
+
module.exports = async function auditCore(
|
|
7
|
+
core,
|
|
8
|
+
{ tree = true, blocks = true, bitfield = true, dryRun = false } = {}
|
|
9
|
+
) {
|
|
7
10
|
const length = core.state.length
|
|
8
|
-
const stats = {
|
|
11
|
+
const stats = {
|
|
12
|
+
treeNodes: 0,
|
|
13
|
+
blocks: 0,
|
|
14
|
+
bits: 0,
|
|
15
|
+
droppedTreeNodes: 0,
|
|
16
|
+
droppedBlocks: 0,
|
|
17
|
+
droppedBits: 0,
|
|
18
|
+
corrupt: false
|
|
19
|
+
}
|
|
9
20
|
|
|
10
21
|
// audit the tree
|
|
11
22
|
if (tree) {
|
|
@@ -126,20 +137,20 @@ module.exports = async function auditCore (core, { tree = true, blocks = true, b
|
|
|
126
137
|
return stats
|
|
127
138
|
}
|
|
128
139
|
|
|
129
|
-
function isBadBlock
|
|
140
|
+
function isBadBlock(node, block) {
|
|
130
141
|
if (!node) return true
|
|
131
142
|
const hash = crypto.data(block)
|
|
132
143
|
return !b4a.equals(hash, node.hash) || node.size !== block.byteLength
|
|
133
144
|
}
|
|
134
145
|
|
|
135
|
-
function isBadTree
|
|
146
|
+
function isBadTree(parent, left, right) {
|
|
136
147
|
if (!left && !right) return false
|
|
137
148
|
if (!left || !right) return true
|
|
138
149
|
const hash = crypto.parent(left, right)
|
|
139
|
-
return !b4a.equals(hash, parent.hash) || parent.size !==
|
|
150
|
+
return !b4a.equals(hash, parent.hash) || parent.size !== left.size + right.size
|
|
140
151
|
}
|
|
141
152
|
|
|
142
|
-
function
|
|
153
|
+
function* allBits(bitfield) {
|
|
143
154
|
let i = 0
|
|
144
155
|
if (bitfield.get(0)) yield 0
|
|
145
156
|
while (true) {
|
package/lib/bit-interlude.js
CHANGED
|
@@ -2,11 +2,11 @@ const b4a = require('b4a')
|
|
|
2
2
|
const quickbit = require('./compat').quickbit
|
|
3
3
|
|
|
4
4
|
module.exports = class BitInterlude {
|
|
5
|
-
constructor
|
|
5
|
+
constructor() {
|
|
6
6
|
this.ranges = []
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
contiguousLength
|
|
9
|
+
contiguousLength(from) {
|
|
10
10
|
for (const r of this.ranges) {
|
|
11
11
|
if (r.start > from) break
|
|
12
12
|
if (!r.value && r.start <= from) return r.start
|
|
@@ -17,7 +17,7 @@ module.exports = class BitInterlude {
|
|
|
17
17
|
return from
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
get
|
|
20
|
+
get(index) {
|
|
21
21
|
let start = 0
|
|
22
22
|
let end = this.ranges.length
|
|
23
23
|
|
|
@@ -42,7 +42,7 @@ module.exports = class BitInterlude {
|
|
|
42
42
|
return false
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
setRange
|
|
45
|
+
setRange(start, end, value) {
|
|
46
46
|
if (start === end) return
|
|
47
47
|
|
|
48
48
|
let r = null
|
|
@@ -75,8 +75,18 @@ module.exports = class BitInterlude {
|
|
|
75
75
|
// we overran but our start is contained in this interval, move start back
|
|
76
76
|
if (start >= r.start && start <= r.end) {
|
|
77
77
|
if (r.value !== value) {
|
|
78
|
+
r.end = start // Crop current comparison
|
|
79
|
+
|
|
80
|
+
// If there's a next range
|
|
81
|
+
if (this.ranges.length - 1 > i) {
|
|
82
|
+
const next = this.ranges[i + 1]
|
|
83
|
+
// If the same, go next
|
|
84
|
+
if (next.value === value) continue
|
|
85
|
+
// Else we overlap so update next range
|
|
86
|
+
if (next.start < end) next.start = end
|
|
87
|
+
}
|
|
88
|
+
|
|
78
89
|
this.ranges.splice(++i, 0, { start, end, value })
|
|
79
|
-
r.end = start
|
|
80
90
|
return
|
|
81
91
|
}
|
|
82
92
|
|
|
@@ -109,7 +119,7 @@ module.exports = class BitInterlude {
|
|
|
109
119
|
this.ranges.push({ start, end, value })
|
|
110
120
|
}
|
|
111
121
|
|
|
112
|
-
flush
|
|
122
|
+
flush(tx, bitfield) {
|
|
113
123
|
if (!this.ranges.length) return []
|
|
114
124
|
|
|
115
125
|
let index = this.ranges[0].start
|
|
@@ -159,7 +169,7 @@ module.exports = class BitInterlude {
|
|
|
159
169
|
}
|
|
160
170
|
}
|
|
161
171
|
|
|
162
|
-
function mergeRanges
|
|
172
|
+
function mergeRanges(a, b) {
|
|
163
173
|
const ranges = []
|
|
164
174
|
if (a.start < b.start) ranges.push({ start: a.start, end: b.start, value: a.value })
|
|
165
175
|
ranges.push({ start: b.start, end: b.end, value: b.value })
|
package/lib/bitfield.js
CHANGED
|
@@ -13,7 +13,7 @@ const PAGES_PER_SEGMENT = BITS_PER_SEGMENT / BITS_PER_PAGE
|
|
|
13
13
|
const SEGMENT_GROWTH_FACTOR = 4
|
|
14
14
|
|
|
15
15
|
class BitfieldPage {
|
|
16
|
-
constructor
|
|
16
|
+
constructor(index, segment) {
|
|
17
17
|
this.index = index
|
|
18
18
|
this.offset = index * BYTES_PER_PAGE - segment.offset
|
|
19
19
|
this.bitfield = null
|
|
@@ -22,21 +22,21 @@ class BitfieldPage {
|
|
|
22
22
|
segment.add(this)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
get tree
|
|
25
|
+
get tree() {
|
|
26
26
|
return this.segment.tree
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
get
|
|
29
|
+
get(index, dirty) {
|
|
30
30
|
return quickbit.get(this.bitfield, index)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
set
|
|
33
|
+
set(index, val) {
|
|
34
34
|
if (quickbit.set(this.bitfield, index, val)) {
|
|
35
35
|
this.tree.update(this.offset * 8 + index)
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
setRange
|
|
39
|
+
setRange(start, end, val) {
|
|
40
40
|
quickbit.fill(this.bitfield, val, start, end)
|
|
41
41
|
|
|
42
42
|
let i = Math.floor(start / 128)
|
|
@@ -45,15 +45,15 @@ class BitfieldPage {
|
|
|
45
45
|
while (i <= n) this.tree.update(this.offset * 8 + i++ * 128)
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
findFirst
|
|
48
|
+
findFirst(val, position) {
|
|
49
49
|
return quickbit.findFirst(this.bitfield, val, position)
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
findLast
|
|
52
|
+
findLast(val, position) {
|
|
53
53
|
return quickbit.findLast(this.bitfield, val, position)
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
count
|
|
56
|
+
count(start, length, val) {
|
|
57
57
|
const end = start + length
|
|
58
58
|
|
|
59
59
|
let i = start
|
|
@@ -76,18 +76,18 @@ class BitfieldPage {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
class BitfieldSegment {
|
|
79
|
-
constructor
|
|
79
|
+
constructor(index, bitfield) {
|
|
80
80
|
this.index = index
|
|
81
81
|
this.offset = index * BYTES_PER_SEGMENT
|
|
82
82
|
this.tree = quickbit.Index.from(bitfield, BYTES_PER_SEGMENT)
|
|
83
83
|
this.pages = new Array(PAGES_PER_SEGMENT)
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
get bitfield
|
|
86
|
+
get bitfield() {
|
|
87
87
|
return this.tree.field
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
add
|
|
90
|
+
add(page) {
|
|
91
91
|
const i = page.index - this.index * PAGES_PER_SEGMENT
|
|
92
92
|
this.pages[i] = page
|
|
93
93
|
|
|
@@ -99,7 +99,7 @@ class BitfieldSegment {
|
|
|
99
99
|
page.bitfield = this.bitfield.subarray(start, end)
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
reallocate
|
|
102
|
+
reallocate(length) {
|
|
103
103
|
let target = this.bitfield.length
|
|
104
104
|
while (target < length) target *= SEGMENT_GROWTH_FACTOR
|
|
105
105
|
|
|
@@ -119,7 +119,7 @@ class BitfieldSegment {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
findFirst
|
|
122
|
+
findFirst(val, position) {
|
|
123
123
|
position = this.tree.skipFirst(!val, position)
|
|
124
124
|
|
|
125
125
|
let j = position & (BITS_PER_PAGE - 1)
|
|
@@ -144,7 +144,7 @@ class BitfieldSegment {
|
|
|
144
144
|
return -1
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
findLast
|
|
147
|
+
findLast(val, position) {
|
|
148
148
|
position = this.tree.skipLast(!val, position)
|
|
149
149
|
|
|
150
150
|
let j = position & (BITS_PER_PAGE - 1)
|
|
@@ -174,22 +174,18 @@ module.exports = class Bitfield {
|
|
|
174
174
|
static BITS_PER_PAGE = BITS_PER_PAGE
|
|
175
175
|
static BYTES_PER_PAGE = BYTES_PER_PAGE
|
|
176
176
|
|
|
177
|
-
constructor
|
|
177
|
+
constructor(buffer) {
|
|
178
178
|
this.resumed = !!(buffer && buffer.byteLength >= 0)
|
|
179
179
|
|
|
180
180
|
this._pages = new BigSparseArray()
|
|
181
181
|
this._segments = new BigSparseArray()
|
|
182
182
|
|
|
183
183
|
const view = this.resumed
|
|
184
|
-
? new Uint32Array(
|
|
185
|
-
buffer.buffer,
|
|
186
|
-
buffer.byteOffset,
|
|
187
|
-
Math.floor(buffer.byteLength / 4)
|
|
188
|
-
)
|
|
184
|
+
? new Uint32Array(buffer.buffer, buffer.byteOffset, Math.floor(buffer.byteLength / 4))
|
|
189
185
|
: new Uint32Array(INITIAL_WORDS_PER_SEGMENT)
|
|
190
186
|
|
|
191
187
|
for (let i = 0; i < view.length; i += WORDS_PER_SEGMENT) {
|
|
192
|
-
let bitfield = view.subarray(i, i +
|
|
188
|
+
let bitfield = view.subarray(i, i + WORDS_PER_SEGMENT)
|
|
193
189
|
let length = WORDS_PER_SEGMENT
|
|
194
190
|
|
|
195
191
|
if (i === 0) {
|
|
@@ -203,7 +199,7 @@ module.exports = class Bitfield {
|
|
|
203
199
|
bitfield = copy
|
|
204
200
|
}
|
|
205
201
|
|
|
206
|
-
const segment = new BitfieldSegment(i /
|
|
202
|
+
const segment = new BitfieldSegment(i / WORDS_PER_SEGMENT, bitfield)
|
|
207
203
|
this._segments.set(segment.index, segment)
|
|
208
204
|
|
|
209
205
|
for (let j = 0; j < bitfield.length; j += WORDS_PER_PAGE) {
|
|
@@ -213,11 +209,11 @@ module.exports = class Bitfield {
|
|
|
213
209
|
}
|
|
214
210
|
}
|
|
215
211
|
|
|
216
|
-
static from
|
|
212
|
+
static from(bitfield) {
|
|
217
213
|
return new Bitfield(bitfield.toBuffer(bitfield._pages.maxLength * BITS_PER_PAGE))
|
|
218
214
|
}
|
|
219
215
|
|
|
220
|
-
toBuffer
|
|
216
|
+
toBuffer(length) {
|
|
221
217
|
const pages = Math.ceil(length / BITS_PER_PAGE)
|
|
222
218
|
const buffer = b4a.allocUnsafe(pages * BYTES_PER_PAGE)
|
|
223
219
|
|
|
@@ -241,14 +237,14 @@ module.exports = class Bitfield {
|
|
|
241
237
|
return buffer
|
|
242
238
|
}
|
|
243
239
|
|
|
244
|
-
getBitfield
|
|
240
|
+
getBitfield(index) {
|
|
245
241
|
const i = this.getPageIndex(index)
|
|
246
242
|
|
|
247
243
|
const p = this._pages.get(i)
|
|
248
244
|
return p || null
|
|
249
245
|
}
|
|
250
246
|
|
|
251
|
-
merge
|
|
247
|
+
merge(bitfield, length) {
|
|
252
248
|
let i = 0
|
|
253
249
|
|
|
254
250
|
while (i < length) {
|
|
@@ -265,7 +261,7 @@ module.exports = class Bitfield {
|
|
|
265
261
|
}
|
|
266
262
|
}
|
|
267
263
|
|
|
268
|
-
get
|
|
264
|
+
get(index) {
|
|
269
265
|
const j = index & (BITS_PER_PAGE - 1)
|
|
270
266
|
const i = (index - j) / BITS_PER_PAGE
|
|
271
267
|
|
|
@@ -274,16 +270,16 @@ module.exports = class Bitfield {
|
|
|
274
270
|
return p ? p.get(j) : false
|
|
275
271
|
}
|
|
276
272
|
|
|
277
|
-
getPageByteLength
|
|
273
|
+
getPageByteLength() {
|
|
278
274
|
return BYTES_PER_PAGE
|
|
279
275
|
}
|
|
280
276
|
|
|
281
|
-
getPageIndex
|
|
277
|
+
getPageIndex(index) {
|
|
282
278
|
const j = index & (BITS_PER_PAGE - 1)
|
|
283
279
|
return (index - j) / BITS_PER_PAGE
|
|
284
280
|
}
|
|
285
281
|
|
|
286
|
-
getPage
|
|
282
|
+
getPage(index, create) {
|
|
287
283
|
const i = this.getPageIndex(index)
|
|
288
284
|
|
|
289
285
|
let p = this._pages.get(i)
|
|
@@ -293,14 +289,22 @@ module.exports = class Bitfield {
|
|
|
293
289
|
if (!create) return null
|
|
294
290
|
|
|
295
291
|
const k = Math.floor(i / PAGES_PER_SEGMENT)
|
|
296
|
-
const s =
|
|
292
|
+
const s =
|
|
293
|
+
this._segments.get(k) ||
|
|
294
|
+
this._segments.set(
|
|
295
|
+
k,
|
|
296
|
+
new BitfieldSegment(
|
|
297
|
+
k,
|
|
298
|
+
new Uint32Array(k === 0 ? INITIAL_WORDS_PER_SEGMENT : WORDS_PER_SEGMENT)
|
|
299
|
+
)
|
|
300
|
+
)
|
|
297
301
|
|
|
298
302
|
p = this._pages.set(i, new BitfieldPage(i, s))
|
|
299
303
|
|
|
300
304
|
return p
|
|
301
305
|
}
|
|
302
306
|
|
|
303
|
-
set
|
|
307
|
+
set(index, val) {
|
|
304
308
|
const j = index & (BITS_PER_PAGE - 1)
|
|
305
309
|
const i = (index - j) / BITS_PER_PAGE
|
|
306
310
|
|
|
@@ -308,7 +312,15 @@ module.exports = class Bitfield {
|
|
|
308
312
|
|
|
309
313
|
if (!p && val) {
|
|
310
314
|
const k = Math.floor(i / PAGES_PER_SEGMENT)
|
|
311
|
-
const s =
|
|
315
|
+
const s =
|
|
316
|
+
this._segments.get(k) ||
|
|
317
|
+
this._segments.set(
|
|
318
|
+
k,
|
|
319
|
+
new BitfieldSegment(
|
|
320
|
+
k,
|
|
321
|
+
new Uint32Array(k === 0 ? INITIAL_WORDS_PER_SEGMENT : WORDS_PER_SEGMENT)
|
|
322
|
+
)
|
|
323
|
+
)
|
|
312
324
|
|
|
313
325
|
p = this._pages.set(i, new BitfieldPage(i, s))
|
|
314
326
|
}
|
|
@@ -316,7 +328,7 @@ module.exports = class Bitfield {
|
|
|
316
328
|
if (p) p.set(j, val)
|
|
317
329
|
}
|
|
318
330
|
|
|
319
|
-
setRange
|
|
331
|
+
setRange(start, end, val) {
|
|
320
332
|
let j = start & (BITS_PER_PAGE - 1)
|
|
321
333
|
let i = (start - j) / BITS_PER_PAGE
|
|
322
334
|
|
|
@@ -325,7 +337,15 @@ module.exports = class Bitfield {
|
|
|
325
337
|
|
|
326
338
|
if (!p && val) {
|
|
327
339
|
const k = Math.floor(i / PAGES_PER_SEGMENT)
|
|
328
|
-
const s =
|
|
340
|
+
const s =
|
|
341
|
+
this._segments.get(k) ||
|
|
342
|
+
this._segments.set(
|
|
343
|
+
k,
|
|
344
|
+
new BitfieldSegment(
|
|
345
|
+
k,
|
|
346
|
+
new Uint32Array(k === 0 ? INITIAL_WORDS_PER_SEGMENT : WORDS_PER_SEGMENT)
|
|
347
|
+
)
|
|
348
|
+
)
|
|
329
349
|
|
|
330
350
|
p = this._pages.set(i, new BitfieldPage(i, s))
|
|
331
351
|
}
|
|
@@ -342,7 +362,7 @@ module.exports = class Bitfield {
|
|
|
342
362
|
}
|
|
343
363
|
}
|
|
344
364
|
|
|
345
|
-
findFirst
|
|
365
|
+
findFirst(val, position) {
|
|
346
366
|
let j = position & (BITS_PER_SEGMENT - 1)
|
|
347
367
|
let i = (position - j) / BITS_PER_SEGMENT
|
|
348
368
|
|
|
@@ -363,15 +383,15 @@ module.exports = class Bitfield {
|
|
|
363
383
|
return val ? -1 : this._segments.maxLength * BITS_PER_SEGMENT
|
|
364
384
|
}
|
|
365
385
|
|
|
366
|
-
firstSet
|
|
386
|
+
firstSet(position) {
|
|
367
387
|
return this.findFirst(true, position)
|
|
368
388
|
}
|
|
369
389
|
|
|
370
|
-
firstUnset
|
|
390
|
+
firstUnset(position) {
|
|
371
391
|
return this.findFirst(false, position)
|
|
372
392
|
}
|
|
373
393
|
|
|
374
|
-
findLast
|
|
394
|
+
findLast(val, position) {
|
|
375
395
|
let j = position & (BITS_PER_SEGMENT - 1)
|
|
376
396
|
let i = (position - j) / BITS_PER_SEGMENT
|
|
377
397
|
|
|
@@ -392,15 +412,15 @@ module.exports = class Bitfield {
|
|
|
392
412
|
return -1
|
|
393
413
|
}
|
|
394
414
|
|
|
395
|
-
lastSet
|
|
415
|
+
lastSet(position) {
|
|
396
416
|
return this.findLast(true, position)
|
|
397
417
|
}
|
|
398
418
|
|
|
399
|
-
lastUnset
|
|
419
|
+
lastUnset(position) {
|
|
400
420
|
return this.findLast(false, position)
|
|
401
421
|
}
|
|
402
422
|
|
|
403
|
-
hasSet
|
|
423
|
+
hasSet(start, length) {
|
|
404
424
|
const end = start + length
|
|
405
425
|
|
|
406
426
|
let j = start & (BITS_PER_SEGMENT - 1)
|
|
@@ -413,7 +433,7 @@ module.exports = class Bitfield {
|
|
|
413
433
|
|
|
414
434
|
if (s) index = s.findFirst(true, j)
|
|
415
435
|
|
|
416
|
-
if (index !== -1) return
|
|
436
|
+
if (index !== -1) return i * BITS_PER_SEGMENT + index < end
|
|
417
437
|
|
|
418
438
|
j = 0
|
|
419
439
|
i++
|
|
@@ -424,7 +444,7 @@ module.exports = class Bitfield {
|
|
|
424
444
|
return false
|
|
425
445
|
}
|
|
426
446
|
|
|
427
|
-
count
|
|
447
|
+
count(start, length, val) {
|
|
428
448
|
let j = start & (BITS_PER_PAGE - 1)
|
|
429
449
|
let i = (start - j) / BITS_PER_PAGE
|
|
430
450
|
let c = 0
|
|
@@ -446,15 +466,15 @@ module.exports = class Bitfield {
|
|
|
446
466
|
return c
|
|
447
467
|
}
|
|
448
468
|
|
|
449
|
-
countSet
|
|
469
|
+
countSet(start, length) {
|
|
450
470
|
return this.count(start, length, true)
|
|
451
471
|
}
|
|
452
472
|
|
|
453
|
-
countUnset
|
|
473
|
+
countUnset(start, length) {
|
|
454
474
|
return this.count(start, length, false)
|
|
455
475
|
}
|
|
456
476
|
|
|
457
|
-
*
|
|
477
|
+
*want(start, length) {
|
|
458
478
|
const j = start & (BITS_PER_SEGMENT - 1)
|
|
459
479
|
let i = (start - j) / BITS_PER_SEGMENT
|
|
460
480
|
|
|
@@ -477,17 +497,17 @@ module.exports = class Bitfield {
|
|
|
477
497
|
}
|
|
478
498
|
}
|
|
479
499
|
|
|
480
|
-
clear
|
|
500
|
+
clear(tx) {
|
|
481
501
|
return tx.deleteBitfieldPageRange(0, -1)
|
|
482
502
|
}
|
|
483
503
|
|
|
484
|
-
onupdate
|
|
504
|
+
onupdate(ranges) {
|
|
485
505
|
for (const { start, end, value } of ranges) {
|
|
486
506
|
this.setRange(start, end, value)
|
|
487
507
|
}
|
|
488
508
|
}
|
|
489
509
|
|
|
490
|
-
static async open
|
|
510
|
+
static async open(storage, length) {
|
|
491
511
|
if (length === 0) return new Bitfield(storage, null)
|
|
492
512
|
|
|
493
513
|
const pages = Math.ceil(length / BITS_PER_PAGE)
|
|
@@ -502,11 +522,11 @@ module.exports = class Bitfield {
|
|
|
502
522
|
}
|
|
503
523
|
}
|
|
504
524
|
|
|
505
|
-
function clamp
|
|
525
|
+
function clamp(n, min, max) {
|
|
506
526
|
return Math.min(Math.max(n, min), max)
|
|
507
527
|
}
|
|
508
528
|
|
|
509
|
-
function ceilTo
|
|
529
|
+
function ceilTo(n, multiple = 1) {
|
|
510
530
|
const remainder = n % multiple
|
|
511
531
|
if (remainder === 0) return n
|
|
512
532
|
return n + multiple - remainder
|
package/lib/caps.js
CHANGED
|
@@ -21,7 +21,11 @@ exports.DEFAULT_ENCRYPTION = DEFAULT_ENCRYPTION
|
|
|
21
21
|
|
|
22
22
|
exports.replicate = function (isInitiator, key, handshakeHash) {
|
|
23
23
|
const out = b4a.allocUnsafe(32)
|
|
24
|
-
sodium.crypto_generichash_batch(
|
|
24
|
+
sodium.crypto_generichash_batch(
|
|
25
|
+
out,
|
|
26
|
+
[isInitiator ? REPLICATE_INITIATOR : REPLICATE_RESPONDER, key],
|
|
27
|
+
handshakeHash
|
|
28
|
+
)
|
|
25
29
|
return out
|
|
26
30
|
}
|
|
27
31
|
|
package/lib/copy-prologue.js
CHANGED
|
@@ -11,7 +11,7 @@ const MIN_BATCH_USED = 512 * 1024
|
|
|
11
11
|
|
|
12
12
|
module.exports = copyPrologue
|
|
13
13
|
|
|
14
|
-
async function copyPrologue
|
|
14
|
+
async function copyPrologue(src, dst) {
|
|
15
15
|
const prologue = dst.header.manifest.prologue
|
|
16
16
|
|
|
17
17
|
if (src.length < prologue.length || prologue.length === 0) return
|
|
@@ -29,7 +29,11 @@ async function copyPrologue (src, dst) {
|
|
|
29
29
|
let lastPage = -1
|
|
30
30
|
let lastBlock = -1
|
|
31
31
|
|
|
32
|
-
for await (const data of src.storage.createBlockStream({
|
|
32
|
+
for await (const data of src.storage.createBlockStream({
|
|
33
|
+
gte: 0,
|
|
34
|
+
lt: prologue.length,
|
|
35
|
+
reverse: true
|
|
36
|
+
})) {
|
|
33
37
|
if (walkTree(stack, data.index * 2, batch) === false) {
|
|
34
38
|
throw new Error('Missing block or tree node for ' + data.index)
|
|
35
39
|
}
|
|
@@ -44,7 +48,7 @@ async function copyPrologue (src, dst) {
|
|
|
44
48
|
batch.used += Math.max(data.value.byteLength, 128) // 128 is just a sanity number to avoid mega batches
|
|
45
49
|
|
|
46
50
|
// always safe to partially flush so we do that ondemand to reduce memory usage...
|
|
47
|
-
if ((batch.used >= MIN_BATCH_USED && page !== lastPage) ||
|
|
51
|
+
if ((batch.used >= MIN_BATCH_USED && page !== lastPage) || batch.used >= MAX_BATCH_USED) {
|
|
48
52
|
await flushBatch(prologue, src, dst, batch)
|
|
49
53
|
}
|
|
50
54
|
|
|
@@ -57,7 +61,7 @@ async function copyPrologue (src, dst) {
|
|
|
57
61
|
await flushBatch(prologue, src, dst, batch)
|
|
58
62
|
}
|
|
59
63
|
|
|
60
|
-
async function flushBatch
|
|
64
|
+
async function flushBatch(prologue, src, dst, batch) {
|
|
61
65
|
const nodePromises = []
|
|
62
66
|
|
|
63
67
|
const srcReader = src.storage.read()
|
|
@@ -183,7 +187,7 @@ async function flushBatch (prologue, src, dst, batch) {
|
|
|
183
187
|
batch.used = 0
|
|
184
188
|
}
|
|
185
189
|
|
|
186
|
-
function signalReplicator
|
|
190
|
+
function signalReplicator(core, upgraded, start, length) {
|
|
187
191
|
if (upgraded) {
|
|
188
192
|
core.replicator.cork()
|
|
189
193
|
core.replicator.onhave(start, length, false)
|
|
@@ -194,7 +198,7 @@ function signalReplicator (core, upgraded, start, length) {
|
|
|
194
198
|
}
|
|
195
199
|
}
|
|
196
200
|
|
|
197
|
-
function prologueToTree
|
|
201
|
+
function prologueToTree(prologue) {
|
|
198
202
|
return {
|
|
199
203
|
fork: 0,
|
|
200
204
|
length: prologue.length,
|
|
@@ -203,15 +207,15 @@ function prologueToTree (prologue) {
|
|
|
203
207
|
}
|
|
204
208
|
}
|
|
205
209
|
|
|
206
|
-
function getBitfieldPage
|
|
210
|
+
function getBitfieldPage(index) {
|
|
207
211
|
return Math.floor(index / Bitfield.BITS_PER_PAGE)
|
|
208
212
|
}
|
|
209
213
|
|
|
210
|
-
function getBitfieldOffset
|
|
214
|
+
function getBitfieldOffset(index) {
|
|
211
215
|
return index & (Bitfield.BITS_PER_PAGE - 1)
|
|
212
216
|
}
|
|
213
217
|
|
|
214
|
-
function walkTree
|
|
218
|
+
function walkTree(stack, target, batch) {
|
|
215
219
|
while (stack.length > 0) {
|
|
216
220
|
const node = stack.pop()
|
|
217
221
|
|
|
@@ -239,4 +243,4 @@ function walkTree (stack, target, batch) {
|
|
|
239
243
|
return false
|
|
240
244
|
}
|
|
241
245
|
|
|
242
|
-
function noop
|
|
246
|
+
function noop() {}
|