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.
@@ -1,518 +0,0 @@
1
- const test = require('brittle')
2
- const Tree = require('../lib/merkle-tree')
3
- const ram = require('random-access-memory')
4
-
5
- test('nodes', async function (t) {
6
- const tree = await create()
7
-
8
- const b = tree.batch()
9
-
10
- for (let i = 0; i < 8; i++) {
11
- b.append(Buffer.from([i]))
12
- }
13
-
14
- b.commit()
15
-
16
- t.is(await tree.nodes(0), 0)
17
- t.end()
18
- })
19
-
20
- test('proof only block', async function (t) {
21
- const tree = await create(10)
22
-
23
- const proof = await tree.proof({
24
- block: { index: 4, nodes: 2, value: true }
25
- })
26
-
27
- t.is(proof.upgrade, null)
28
- t.is(proof.seek, null)
29
- t.is(proof.block.index, 4)
30
- t.is(proof.block.nodes.length, 2)
31
- t.alike(proof.block.nodes.map(n => n.index), [10, 13])
32
-
33
- t.end()
34
- })
35
-
36
- test('proof with upgrade', async function (t) {
37
- const tree = await create(10)
38
-
39
- const proof = await tree.proof({
40
- block: { index: 4, nodes: 0, value: true },
41
- upgrade: { start: 0, length: 10 }
42
- })
43
-
44
- t.is(proof.seek, null)
45
- t.is(proof.block.index, 4)
46
- t.is(proof.block.nodes.length, 3)
47
- t.alike(proof.block.nodes.map(n => n.index), [10, 13, 3])
48
- t.is(proof.upgrade.start, 0)
49
- t.is(proof.upgrade.length, 10)
50
- t.alike(proof.upgrade.nodes.map(n => n.index), [17])
51
- t.alike(proof.upgrade.additionalNodes.map(n => n.index), [])
52
-
53
- t.end()
54
- })
55
-
56
- test('proof with upgrade + additional', async function (t) {
57
- const tree = await create(10)
58
-
59
- const proof = await tree.proof({
60
- block: { index: 4, nodes: 0, value: true },
61
- upgrade: { start: 0, length: 8 }
62
- })
63
-
64
- t.is(proof.seek, null)
65
- t.is(proof.block.index, 4)
66
- t.is(proof.block.nodes.length, 3)
67
- t.alike(proof.block.nodes.map(n => n.index), [10, 13, 3])
68
- t.is(proof.upgrade.start, 0)
69
- t.is(proof.upgrade.length, 8)
70
- t.alike(proof.upgrade.nodes.map(n => n.index), [])
71
- t.alike(proof.upgrade.additionalNodes.map(n => n.index), [17])
72
-
73
- t.end()
74
- })
75
-
76
- test('proof with upgrade from existing state', async function (t) {
77
- const tree = await create(10)
78
-
79
- const proof = await tree.proof({
80
- block: { index: 1, nodes: 0, value: true },
81
- upgrade: { start: 1, length: 9 }
82
- })
83
-
84
- t.is(proof.seek, null)
85
- t.is(proof.block.index, 1)
86
- t.is(proof.block.nodes.length, 0)
87
- t.alike(proof.block.nodes.map(n => n.index), [])
88
- t.is(proof.upgrade.start, 1)
89
- t.is(proof.upgrade.length, 9)
90
- t.alike(proof.upgrade.nodes.map(n => n.index), [5, 11, 17])
91
- t.alike(proof.upgrade.additionalNodes.map(n => n.index), [])
92
-
93
- t.end()
94
- })
95
-
96
- test('proof with upgrade from existing state + additional', async function (t) {
97
- const tree = await create(10)
98
-
99
- const proof = await tree.proof({
100
- block: { index: 1, nodes: 0, value: true },
101
- upgrade: { start: 1, length: 5 }
102
- })
103
-
104
- t.is(proof.seek, null)
105
- t.is(proof.block.index, 1)
106
- t.is(proof.block.nodes.length, 0)
107
- t.alike(proof.block.nodes.map(n => n.index), [])
108
- t.is(proof.upgrade.start, 1)
109
- t.is(proof.upgrade.length, 5)
110
- t.alike(proof.upgrade.nodes.map(n => n.index), [5, 9])
111
- t.alike(proof.upgrade.additionalNodes.map(n => n.index), [13, 17])
112
-
113
- t.end()
114
- })
115
-
116
- test('proof block and seek, no upgrade', async function (t) {
117
- const tree = await create(10)
118
-
119
- const proof = await tree.proof({
120
- seek: { bytes: 8 },
121
- block: { index: 4, nodes: 2, value: true }
122
- })
123
-
124
- t.is(proof.upgrade, null)
125
- t.is(proof.seek, null) // seek included in the block
126
- t.is(proof.block.index, 4)
127
- t.is(proof.block.nodes.length, 2)
128
- t.alike(proof.block.nodes.map(n => n.index), [10, 13])
129
-
130
- t.end()
131
- })
132
-
133
- test('proof block and seek #2, no upgrade', async function (t) {
134
- const tree = await create(10)
135
-
136
- const proof = await tree.proof({
137
- seek: { bytes: 10 },
138
- block: { index: 4, nodes: 2, value: true }
139
- })
140
-
141
- t.is(proof.upgrade, null)
142
- t.is(proof.seek, null) // seek included in the block
143
- t.is(proof.block.index, 4)
144
- t.is(proof.block.nodes.length, 2)
145
- t.alike(proof.block.nodes.map(n => n.index), [10, 13])
146
-
147
- t.end()
148
- })
149
-
150
- test('proof block and seek #3, no upgrade', async function (t) {
151
- const tree = await create(10)
152
-
153
- const proof = await tree.proof({
154
- seek: { bytes: 13 },
155
- block: { index: 4, nodes: 2, value: true }
156
- })
157
-
158
- t.is(proof.upgrade, null)
159
- t.alike(proof.seek.nodes.map(n => n.index), [12, 14])
160
- t.is(proof.block.index, 4)
161
- t.is(proof.block.nodes.length, 1)
162
- t.alike(proof.block.nodes.map(n => n.index), [10])
163
-
164
- t.end()
165
- })
166
-
167
- test('proof block and seek that results in tree, no upgrade', async function (t) {
168
- const tree = await create(16)
169
-
170
- const proof = await tree.proof({
171
- seek: { bytes: 26 },
172
- block: { index: 0, nodes: 4, value: true }
173
- })
174
-
175
- t.is(proof.upgrade, null)
176
- t.alike(proof.block.nodes.map(n => n.index), [2, 5, 11])
177
- t.alike(proof.seek.nodes.map(n => n.index), [19, 27])
178
-
179
- t.end()
180
- })
181
-
182
- test('proof block and seek, with upgrade', async function (t) {
183
- const tree = await create(10)
184
-
185
- const proof = await tree.proof({
186
- seek: { bytes: 13 },
187
- block: { index: 4, nodes: 2, value: true },
188
- upgrade: { start: 8, length: 2 }
189
- })
190
-
191
- t.alike(proof.seek.nodes.map(n => n.index), [12, 14])
192
- t.is(proof.block.index, 4)
193
- t.is(proof.block.nodes.length, 1)
194
- t.alike(proof.block.nodes.map(n => n.index), [10])
195
- t.is(proof.upgrade.start, 8)
196
- t.is(proof.upgrade.length, 2)
197
- t.alike(proof.upgrade.nodes.map(n => n.index), [17])
198
- t.alike(proof.upgrade.additionalNodes.map(n => n.index), [])
199
-
200
- t.end()
201
- })
202
-
203
- test('proof seek with upgrade', async function (t) {
204
- const tree = await create(10)
205
-
206
- const proof = await tree.proof({
207
- seek: { bytes: 13 },
208
- upgrade: { start: 0, length: 10 }
209
- })
210
-
211
- t.alike(proof.seek.nodes.map(n => n.index), [12, 14, 9, 3])
212
- t.is(proof.block, null)
213
- t.is(proof.upgrade.start, 0)
214
- t.is(proof.upgrade.length, 10)
215
- t.alike(proof.upgrade.nodes.map(n => n.index), [17])
216
- t.alike(proof.upgrade.additionalNodes.map(n => n.index), [])
217
-
218
- t.end()
219
- })
220
-
221
- test('verify proof #1', async function (t) {
222
- const tree = await create(10)
223
- const clone = await create()
224
-
225
- const p = await tree.proof({
226
- block: { index: 3 },
227
- upgrade: { start: 0, length: 10 }
228
- })
229
-
230
- const b = await clone.verify(p)
231
- b.commit()
232
-
233
- t.is(clone.length, tree.length)
234
- t.is(clone.byteLength, tree.byteLength)
235
- t.is(await clone.byteOffset(6), await tree.byteOffset(6))
236
- t.is(await clone.get(6), await tree.get(6))
237
-
238
- t.end()
239
- })
240
-
241
- test('verify proof #2', async function (t) {
242
- const tree = await create(10)
243
- const clone = await create()
244
-
245
- const p = await tree.proof({
246
- seek: { bytes: 10 },
247
- upgrade: { start: 0, length: 10 }
248
- })
249
-
250
- const b = await clone.verify(p)
251
- b.commit()
252
-
253
- t.is(clone.length, tree.length)
254
- t.is(clone.byteLength, tree.byteLength)
255
- t.alike(await clone.byteRange(10), await tree.byteRange(10))
256
-
257
- t.end()
258
- })
259
-
260
- test('upgrade edgecase when no roots need upgrade', async function (t) {
261
- const tree = await create(4)
262
- const clone = await create()
263
-
264
- {
265
- const proof = await tree.proof({
266
- upgrade: { start: 0, length: 4 }
267
- })
268
-
269
- const b = await clone.verify(proof)
270
- b.commit()
271
- }
272
-
273
- const b = tree.batch()
274
- b.append(Buffer.from('#5'))
275
- b.commit()
276
-
277
- {
278
- const proof = await tree.proof({
279
- upgrade: { start: 4, length: 1 }
280
- })
281
-
282
- const b = await clone.verify(proof)
283
- b.commit()
284
- }
285
-
286
- t.is(tree.length, 5)
287
- t.end()
288
- })
289
-
290
- test('lowest common ancestor - small gap', async function (t) {
291
- const tree = await create(10)
292
- const clone = await create(8)
293
- const ancestors = await reorg(clone, tree)
294
-
295
- t.is(ancestors, 8)
296
- t.is(clone.length, tree.length)
297
- t.end()
298
- })
299
-
300
- test('lowest common ancestor - bigger gap', async function (t) {
301
- const tree = await create(20)
302
- const clone = await create(1)
303
- const ancestors = await reorg(clone, tree)
304
-
305
- t.is(ancestors, 1)
306
- t.is(clone.length, tree.length)
307
- t.end()
308
- })
309
-
310
- test('lowest common ancestor - remote is shorter than local', async function (t) {
311
- const tree = await create(5)
312
- const clone = await create(10)
313
- const ancestors = await reorg(clone, tree)
314
-
315
- t.is(ancestors, 5)
316
- t.is(clone.length, tree.length)
317
- t.end()
318
- })
319
-
320
- test('lowest common ancestor - simple fork', async function (t) {
321
- const tree = await create(5)
322
- const clone = await create(5)
323
-
324
- {
325
- const b = tree.batch()
326
- b.append(Buffer.from('fork #1'))
327
- b.commit()
328
- }
329
-
330
- {
331
- const b = clone.batch()
332
- b.append(Buffer.from('fork #2'))
333
- b.commit()
334
- }
335
-
336
- const ancestors = await reorg(clone, tree)
337
-
338
- t.is(ancestors, 5)
339
- t.is(clone.length, tree.length)
340
- t.end()
341
- })
342
-
343
- test('lowest common ancestor - long fork', async function (t) {
344
- const tree = await create(5)
345
- const clone = await create(5)
346
-
347
- {
348
- const b = tree.batch()
349
- b.append(Buffer.from('fork #1'))
350
- b.commit()
351
- }
352
-
353
- {
354
- const b = clone.batch()
355
- b.append(Buffer.from('fork #2'))
356
- b.commit()
357
- }
358
-
359
- {
360
- const b = tree.batch()
361
- for (let i = 0; i < 100; i++) b.append(Buffer.from('#' + i))
362
- b.commit()
363
- }
364
-
365
- {
366
- const b = clone.batch()
367
- for (let i = 0; i < 100; i++) b.append(Buffer.from('#' + i))
368
- b.commit()
369
- }
370
-
371
- const ancestors = await reorg(clone, tree)
372
-
373
- t.is(ancestors, 5)
374
- t.is(clone.length, tree.length)
375
-
376
- t.ok(await audit(tree))
377
- await tree.flush()
378
- t.ok(await audit(tree))
379
-
380
- t.end()
381
- })
382
-
383
- test('tree hash', async function (t) {
384
- const a = await create(5)
385
- const b = await create(5)
386
-
387
- t.alike(a.hash(), b.hash())
388
-
389
- {
390
- const b = a.batch()
391
- t.alike(b.hash(), a.hash())
392
- b.append(Buffer.from('hi'))
393
- const h = b.hash()
394
- t.unlike(h, a.hash())
395
- b.commit()
396
- t.alike(h, a.hash())
397
- }
398
-
399
- {
400
- const ba = b.batch()
401
- ba.append(Buffer.from('hi'))
402
- const h = ba.hash()
403
- t.unlike(h, b.hash())
404
- t.alike(h, a.hash())
405
- ba.commit()
406
- t.alike(h, b.hash())
407
- }
408
-
409
- t.end()
410
- })
411
-
412
- test('basic tree seeks', async function (t) {
413
- const a = await create(5)
414
-
415
- {
416
- const b = a.batch()
417
- b.append(Buffer.from('bigger'))
418
- b.append(Buffer.from('block'))
419
- b.append(Buffer.from('tiny'))
420
- b.append(Buffer.from('s'))
421
- b.append(Buffer.from('another'))
422
- b.commit()
423
- }
424
-
425
- t.is(a.length, 10)
426
- t.is(a.byteLength, 33)
427
-
428
- for (let i = 0; i < a.byteLength; i++) {
429
- const s = a.seek(i)
430
-
431
- const actual = await s.update()
432
- const expected = await linearSeek(a, i)
433
-
434
- if (actual[0] !== expected[0] || actual[1] !== expected[1]) {
435
- t.is(actual, expected, 'bad seek at ' + i)
436
- return
437
- }
438
- }
439
-
440
- t.pass('checked all byte seeks')
441
-
442
- async function linearSeek (tree, bytes) {
443
- for (let i = 0; i < tree.length * 2; i += 2) {
444
- const node = await tree.get(i)
445
- if (node.size > bytes) return [i / 2, bytes]
446
- bytes -= node.size
447
- }
448
- return [tree.length, bytes]
449
- }
450
- })
451
-
452
- test('clear full tree', async function (t) {
453
- const a = await create(5)
454
-
455
- t.is(a.length, 5)
456
-
457
- await a.clear()
458
-
459
- t.is(a.length, 0)
460
-
461
- try {
462
- await a.get(2)
463
- t.fail('node should not exist now')
464
- } catch {
465
- t.pass('node should fail')
466
- }
467
- })
468
-
469
- async function audit (tree) {
470
- const flat = require('flat-tree')
471
- const expectedRoots = flat.fullRoots(tree.length * 2)
472
-
473
- for (const root of tree.roots) {
474
- if (expectedRoots.shift() !== root.index) return false
475
- if (!(await check(root))) return false
476
- }
477
-
478
- if (expectedRoots.length) return false
479
-
480
- return true
481
-
482
- async function check (node) {
483
- if ((node.index & 1) === 0) return true
484
-
485
- const [l, r] = flat.children(node.index)
486
- const nl = await tree.get(l, false)
487
- const nr = await tree.get(r, false)
488
-
489
- if (!nl && !nr) return true
490
-
491
- return tree.crypto.parent(nl, nr).equals(node.hash) && await check(nl) && await check(nr)
492
- }
493
- }
494
-
495
- async function reorg (local, remote) {
496
- const upgrade = { start: 0, length: remote.length }
497
- const r = await local.reorg(await remote.proof({ upgrade }))
498
-
499
- while (!r.finished) {
500
- const index = r.want.end - 1
501
- const nodes = r.want.nodes
502
-
503
- await r.update(await remote.proof({ block: { index, nodes } }))
504
- }
505
-
506
- r.commit()
507
- return r.ancestors
508
- }
509
-
510
- async function create (length = 0) {
511
- const tree = await Tree.open(ram())
512
- const b = tree.batch()
513
- for (let i = 0; i < length; i++) {
514
- b.append(Buffer.from('#' + i))
515
- }
516
- b.commit()
517
- return tree
518
- }
package/test/mutex.js DELETED
@@ -1,137 +0,0 @@
1
- const test = require('brittle')
2
- const Mutex = require('../lib/mutex')
3
-
4
- test('mutex - lock after destroy', async function (t) {
5
- const mutex = new Mutex()
6
- mutex.destroy()
7
- try {
8
- await mutex.lock()
9
- t.fail('should not be able to lock after destroy')
10
- } catch {
11
- t.pass('lock threw after destroy')
12
- }
13
- })
14
-
15
- test('mutex - graceful destroy', async function (t) {
16
- t.plan(1)
17
-
18
- const mutex = new Mutex()
19
- const promises = []
20
- let resolveCount = 0
21
-
22
- for (let i = 0; i < 5; i++) {
23
- promises.push(mutex.lock().then(() => resolveCount++))
24
- }
25
-
26
- const destroyed = mutex.destroy()
27
-
28
- for (let i = 0; i < 5; i++) mutex.unlock()
29
-
30
- await destroyed
31
-
32
- t.is(resolveCount, 5)
33
- })
34
-
35
- test('mutex - quick destroy', async function (t) {
36
- t.plan(2)
37
-
38
- const mutex = new Mutex()
39
- const promises = []
40
- let rejectCount = 0
41
- let resolveCount = 0
42
-
43
- for (let i = 0; i < 5; i++) {
44
- promises.push(mutex.lock().then(() => resolveCount++, () => rejectCount++))
45
- }
46
-
47
- const destroyed = mutex.destroy(new Error('Test error'))
48
-
49
- for (let i = 0; i < 5; i++) mutex.unlock()
50
-
51
- await destroyed
52
-
53
- t.is(resolveCount, 1)
54
- t.is(rejectCount, 4)
55
- })
56
-
57
- test('mutex - graceful then quick destroy', async function (t) {
58
- t.plan(2)
59
-
60
- const mutex = new Mutex()
61
- const promises = []
62
- let rejectCount = 0
63
- let resolveCount = 0
64
-
65
- for (let i = 0; i < 5; i++) {
66
- promises.push(mutex.lock().then(() => resolveCount++, () => rejectCount++))
67
- }
68
-
69
- const destroyed = mutex.destroy()
70
- mutex.destroy(new Error('Test error'))
71
-
72
- for (let i = 0; i < 5; i++) mutex.unlock()
73
-
74
- await destroyed
75
-
76
- t.is(resolveCount, 1)
77
- t.is(rejectCount, 4)
78
- })
79
-
80
- test('mutex - quick destroy with re-entry', async function (t) {
81
- t.plan(2)
82
-
83
- const mutex = new Mutex()
84
- const promises = []
85
- let rejectCount = 0
86
- let resolveCount = 0
87
-
88
- for (let i = 0; i < 5; i++) {
89
- promises.push(lock())
90
- }
91
-
92
- const destroyed = mutex.destroy(new Error('Test error'))
93
-
94
- for (let i = 0; i < 5; i++) mutex.unlock()
95
-
96
- await destroyed
97
-
98
- t.is(resolveCount, 1)
99
- t.is(rejectCount, 4)
100
-
101
- async function lock () {
102
- try {
103
- await mutex.lock()
104
- resolveCount++
105
- } catch {
106
- try {
107
- await mutex.lock()
108
- t.fail('should never aquire it after failing')
109
- } catch {
110
- rejectCount++
111
- }
112
- }
113
- }
114
- })
115
-
116
- test('mutex - error propagates', async function (t) {
117
- const mutex = new Mutex()
118
-
119
- let resolveCount = 0
120
- const rejectErrors = []
121
- const err = new Error('Stop')
122
-
123
- for (let i = 0; i < 5; i++) {
124
- mutex.lock().then(() => resolveCount++, err => rejectErrors.push(err))
125
- }
126
-
127
- await mutex.destroy(err)
128
-
129
- try {
130
- await mutex.lock()
131
- } catch (e) {
132
- t.ok(e === err)
133
- }
134
-
135
- t.is(resolveCount, 1)
136
- t.alike(rejectErrors, [err, err, err, err])
137
- })