hypercore 9.12.0 → 10.0.0-alpha.11

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.
Files changed (86) hide show
  1. package/.github/workflows/test-node.yml +3 -4
  2. package/README.md +131 -404
  3. package/__snapshots__/test/storage.js.snapshot.cjs +15 -0
  4. package/examples/announce.js +19 -0
  5. package/examples/basic.js +10 -0
  6. package/examples/http.js +123 -0
  7. package/examples/lookup.js +20 -0
  8. package/index.js +365 -1600
  9. package/lib/bitfield.js +113 -285
  10. package/lib/block-encryption.js +68 -0
  11. package/lib/block-store.js +58 -0
  12. package/lib/core.js +468 -0
  13. package/lib/extensions.js +76 -0
  14. package/lib/merkle-tree.js +1110 -0
  15. package/lib/messages.js +571 -0
  16. package/lib/mutex.js +39 -0
  17. package/lib/oplog.js +224 -0
  18. package/lib/protocol.js +525 -0
  19. package/lib/random-iterator.js +46 -0
  20. package/lib/remote-bitfield.js +24 -0
  21. package/lib/replicator.js +857 -0
  22. package/lib/streams.js +39 -0
  23. package/package.json +44 -45
  24. package/test/basic.js +59 -471
  25. package/test/bitfield.js +48 -133
  26. package/test/core.js +290 -0
  27. package/test/encodings.js +18 -0
  28. package/test/encryption.js +123 -0
  29. package/test/extension.js +71 -0
  30. package/test/helpers/index.js +23 -0
  31. package/test/merkle-tree.js +518 -0
  32. package/test/mutex.js +137 -0
  33. package/test/oplog.js +399 -0
  34. package/test/preload.js +72 -0
  35. package/test/replicate.js +227 -824
  36. package/test/sessions.js +173 -0
  37. package/test/storage.js +31 -0
  38. package/test/streams.js +39 -146
  39. package/test/user-data.js +47 -0
  40. package/bench/all.sh +0 -65
  41. package/bench/copy-64kb-blocks.js +0 -51
  42. package/bench/helpers/read-throttled.js +0 -27
  43. package/bench/helpers/read.js +0 -47
  44. package/bench/helpers/write.js +0 -29
  45. package/bench/read-16kb-blocks-proof-throttled.js +0 -1
  46. package/bench/read-16kb-blocks-proof.js +0 -1
  47. package/bench/read-16kb-blocks-throttled.js +0 -1
  48. package/bench/read-16kb-blocks.js +0 -1
  49. package/bench/read-512b-blocks.js +0 -1
  50. package/bench/read-64kb-blocks-linear-batch.js +0 -18
  51. package/bench/read-64kb-blocks-linear.js +0 -18
  52. package/bench/read-64kb-blocks-proof.js +0 -1
  53. package/bench/read-64kb-blocks.js +0 -1
  54. package/bench/replicate-16kb-blocks.js +0 -19
  55. package/bench/replicate-64kb-blocks.js +0 -19
  56. package/bench/write-16kb-blocks.js +0 -1
  57. package/bench/write-512b-blocks.js +0 -1
  58. package/bench/write-64kb-blocks-static.js +0 -1
  59. package/bench/write-64kb-blocks.js +0 -1
  60. package/example.js +0 -23
  61. package/lib/cache.js +0 -26
  62. package/lib/crypto.js +0 -5
  63. package/lib/replicate.js +0 -829
  64. package/lib/safe-buffer-equals.js +0 -6
  65. package/lib/storage.js +0 -421
  66. package/lib/tree-index.js +0 -183
  67. package/test/ack.js +0 -306
  68. package/test/audit.js +0 -36
  69. package/test/cache.js +0 -93
  70. package/test/compat.js +0 -209
  71. package/test/copy.js +0 -377
  72. package/test/default-storage.js +0 -51
  73. package/test/extensions.js +0 -137
  74. package/test/get.js +0 -64
  75. package/test/head.js +0 -65
  76. package/test/helpers/create-tracking-ram.js +0 -27
  77. package/test/helpers/create.js +0 -6
  78. package/test/helpers/replicate.js +0 -4
  79. package/test/seek.js +0 -234
  80. package/test/selections.js +0 -95
  81. package/test/set-uploading-downloading.js +0 -91
  82. package/test/stats.js +0 -77
  83. package/test/timeouts.js +0 -22
  84. package/test/tree-index.js +0 -841
  85. package/test/update.js +0 -156
  86. package/test/value-encoding.js +0 -52
@@ -1,6 +0,0 @@
1
- // buffer-equals, but handle 'null' buffer parameters.
2
- module.exports = function safeBufferEquals (a, b) {
3
- if (!a) return !b
4
- if (!b) return !a
5
- return Buffer.compare(a, b) === 0
6
- }
package/lib/storage.js DELETED
@@ -1,421 +0,0 @@
1
- var uint64be = require('uint64be')
2
- var flat = require('flat-tree')
3
- var createCache = require('./cache')
4
-
5
- module.exports = Storage
6
-
7
- var noarr = []
8
-
9
- function Storage (create, opts) {
10
- if (!(this instanceof Storage)) return new Storage(create, opts)
11
-
12
- const cache = createCache(opts)
13
-
14
- this.treeCache = cache.tree || null
15
- this.dataCache = cache.data || null
16
- this.key = null
17
- this.secretKey = null
18
- this.tree = null
19
- this.data = null
20
- this.bitfield = null
21
- this.signatures = null
22
- this.create = create
23
- }
24
-
25
- Storage.prototype.putData = function (index, data, nodes, cb) {
26
- if (!cb) cb = noop
27
- var self = this
28
- if (!data.length) return cb(null)
29
- this.dataOffset(index, nodes, function (err, offset, size) {
30
- if (err) return cb(err)
31
- if (size !== data.length) return cb(new Error('Unexpected data size'))
32
- self.data.write(offset, data, cb)
33
- })
34
- }
35
-
36
- Storage.prototype.getData = function (index, cb) {
37
- var self = this
38
- var cached = this.dataCache && this.dataCache.get(index)
39
- if (cached) return process.nextTick(cb, null, cached)
40
- this.dataOffset(index, noarr, function (err, offset, size) {
41
- if (err) return cb(err)
42
- self.data.read(offset, size, (err, data) => {
43
- if (err) return cb(err)
44
- if (self.dataCache) self.dataCache.set(index, data)
45
- return cb(null, data)
46
- })
47
- })
48
- }
49
-
50
- Storage.prototype.nextSignature = function (index, cb) {
51
- var self = this
52
-
53
- this._getSignature(index, function (err, signature) {
54
- if (err) return cb(err)
55
- if (isBlank(signature)) return self.nextSignature(index + 1, cb)
56
- cb(null, { index: index, signature: signature })
57
- })
58
- }
59
-
60
- Storage.prototype.getSignature = function (index, cb) {
61
- this._getSignature(index, function (err, signature) {
62
- if (err) return cb(err)
63
- if (isBlank(signature)) return cb(new Error('No signature found'))
64
- cb(null, signature)
65
- })
66
- }
67
-
68
- // Caching not enabled for signatures because they are rarely reused.
69
- Storage.prototype._getSignature = function (index, cb) {
70
- this.signatures.read(32 + 64 * index, 64, cb)
71
- }
72
-
73
- Storage.prototype.putSignature = function (index, signature, cb) {
74
- this.signatures.write(32 + 64 * index, signature, cb)
75
- }
76
-
77
- Storage.prototype.deleteSignatures = function (start, end, cb) {
78
- this.signatures.del(32 + 64 * start, (end - start) * 64, cb)
79
- }
80
-
81
- Storage.prototype.dataOffset = function (index, cachedNodes, cb) {
82
- var roots = flat.fullRoots(2 * index)
83
- var self = this
84
- var offset = 0
85
- var pending = roots.length
86
- var error = null
87
- var blk = 2 * index
88
-
89
- if (!pending) {
90
- pending = 1
91
- onnode(null, null)
92
- return
93
- }
94
-
95
- for (var i = 0; i < roots.length; i++) {
96
- var node = findNode(cachedNodes, roots[i])
97
- if (node) onnode(null, node)
98
- else this.getNode(roots[i], onnode)
99
- }
100
-
101
- function onlast (err, node) {
102
- if (err) return cb(err)
103
- cb(null, offset, node.size)
104
- }
105
-
106
- function onnode (err, node) {
107
- if (err) error = err
108
- if (node) offset += node.size
109
- if (--pending) return
110
-
111
- if (error) return cb(error)
112
-
113
- var last = findNode(cachedNodes, blk)
114
- if (last) onlast(null, last)
115
- else self.getNode(blk, onlast)
116
- }
117
- }
118
-
119
- // Caching not enabled for batch reads because they'd be complicated to batch and they're rarely used.
120
- Storage.prototype.getDataBatch = function (start, n, cb) {
121
- var result = new Array(n)
122
- var sizes = new Array(n)
123
- var self = this
124
-
125
- this.dataOffset(start, noarr, function (err, offset, size) {
126
- if (err) return cb(err)
127
-
128
- start++
129
- n--
130
-
131
- if (n <= 0) return ontree(null, null)
132
- self.tree.read(32 + 80 * start, 80 * n - 40, ontree)
133
-
134
- function ontree (err, buf) {
135
- if (err) return cb(err)
136
-
137
- var total = sizes[0] = size
138
-
139
- if (buf) {
140
- for (var i = 1; i < sizes.length; i++) {
141
- sizes[i] = uint64be.decode(buf, 32 + (i - 1) * 80)
142
- total += sizes[i]
143
- }
144
- }
145
-
146
- self.data.read(offset, total, ondata)
147
- }
148
-
149
- function ondata (err, buf) {
150
- if (err) return cb(err)
151
- var total = 0
152
- for (var i = 0; i < result.length; i++) {
153
- result[i] = buf.slice(total, total += sizes[i])
154
- }
155
-
156
- cb(null, result)
157
- }
158
- })
159
- }
160
-
161
- Storage.prototype.getNode = function (index, cb) {
162
- if (this.treeCache) {
163
- var cached = this.treeCache.get(index)
164
- if (cached) return cb(null, cached)
165
- }
166
-
167
- var self = this
168
-
169
- this.tree.read(32 + 40 * index, 40, function (err, buf) {
170
- if (err) return cb(err)
171
-
172
- var hash = buf.slice(0, 32)
173
- var size = uint64be.decode(buf, 32)
174
-
175
- if (!size && isBlank(hash)) return cb(new Error('No node found'))
176
-
177
- var val = new Node(index, self.treeCache ? copyMaybe(hash, 40) : hash, size, null)
178
- if (self.treeCache) self.treeCache.set(index, val)
179
- cb(null, val)
180
- })
181
- }
182
-
183
- Storage.prototype.putNodeBatch = function (index, nodes, cb) {
184
- if (!cb) cb = noop
185
-
186
- var buf = Buffer.alloc(nodes.length * 40)
187
-
188
- for (var i = 0; i < nodes.length; i++) {
189
- var offset = i * 40
190
- var node = nodes[i]
191
- if (!node) continue
192
- node.hash.copy(buf, offset)
193
- uint64be.encode(node.size, buf, 32 + offset)
194
- }
195
-
196
- this.tree.write(32 + 40 * index, buf, cb)
197
- }
198
-
199
- Storage.prototype.putNode = function (index, node, cb) {
200
- if (!cb) cb = noop
201
-
202
- // TODO: re-enable put cache. currently this causes a memleak
203
- // because node.hash is a slice of the big data buffer on replicate
204
- // if (this.cache) this.cache.set(index, node)
205
-
206
- var buf = Buffer.allocUnsafe(40)
207
-
208
- node.hash.copy(buf, 0)
209
- uint64be.encode(node.size, buf, 32)
210
- this.tree.write(32 + 40 * index, buf, cb)
211
- }
212
-
213
- Storage.prototype.putBitfield = function (offset, data, cb) {
214
- this.bitfield.write(32 + offset, data, cb)
215
- }
216
-
217
- Storage.prototype.close = function (cb) {
218
- if (!cb) cb = noop
219
- var missing = 6
220
- var error = null
221
-
222
- close(this.bitfield, done)
223
- close(this.tree, done)
224
- close(this.data, done)
225
- close(this.key, done)
226
- close(this.secretKey, done)
227
- close(this.signatures, done)
228
-
229
- function done (err) {
230
- if (err) error = err
231
- if (--missing) return
232
- cb(error)
233
- }
234
- }
235
-
236
- Storage.prototype.destroy = function (cb) {
237
- if (!cb) cb = noop
238
- var missing = 6
239
- var error = null
240
-
241
- destroy(this.bitfield, done)
242
- destroy(this.tree, done)
243
- destroy(this.data, done)
244
- destroy(this.key, done)
245
- destroy(this.secretKey, done)
246
- destroy(this.signatures, done)
247
-
248
- function done (err) {
249
- if (err) error = err
250
- if (--missing) return
251
- cb(error)
252
- }
253
- }
254
-
255
- Storage.prototype.openKey = function (opts, cb) {
256
- if (typeof opts === 'function') return this.openKey({}, opts)
257
- if (!this.key) this.key = this.create('key', opts)
258
- this.key.read(0, 32, cb)
259
- }
260
-
261
- Storage.prototype.open = function (opts, cb) {
262
- if (typeof opts === 'function') return this.open({}, opts)
263
-
264
- var self = this
265
- var error = null
266
- var missing = 5
267
-
268
- if (!this.key) this.key = this.create('key', opts)
269
- if (!this.secretKey) this.secretKey = this.create('secret_key', opts)
270
- if (!this.tree) this.tree = this.create('tree', opts)
271
- if (!this.data) this.data = this.create('data', opts)
272
- if (!this.bitfield) this.bitfield = this.create('bitfield', opts)
273
- if (!this.signatures) this.signatures = this.create('signatures', opts)
274
-
275
- var result = {
276
- bitfield: [],
277
- bitfieldPageSize: 3584, // we upgraded the page size to fix a bug
278
- secretKey: null,
279
- key: null
280
- }
281
-
282
- this.bitfield.read(0, 32, function (err, h) {
283
- if (err && err.code === 'ELOCKED') return cb(err)
284
- if (h) result.bitfieldPageSize = h.readUInt16BE(5)
285
- self.bitfield.write(0, header(0, result.bitfieldPageSize, null), function (err) {
286
- if (err) return cb(err)
287
- readAll(self.bitfield, 32, result.bitfieldPageSize, function (err, pages) {
288
- if (pages) result.bitfield = pages
289
- done(err)
290
- })
291
- })
292
- })
293
-
294
- this.signatures.write(0, header(1, 64, 'Ed25519'), done)
295
- this.tree.write(0, header(2, 40, 'BLAKE2b'), done)
296
-
297
- // TODO: Improve the error handling here.
298
- // I.e. if secretKey length === 64 and it fails, error
299
-
300
- this.secretKey.read(0, 64, function (_, data) {
301
- if (data) result.secretKey = data
302
- done(null)
303
- })
304
-
305
- this.key.read(0, 32, function (_, data) {
306
- if (data) result.key = data
307
- done(null)
308
- })
309
-
310
- function done (err) {
311
- if (err) error = err
312
- if (--missing) return
313
- if (error) cb(error)
314
- else cb(null, result)
315
- }
316
- }
317
-
318
- Storage.Node = Node
319
-
320
- function noop () {}
321
-
322
- function copyMaybe (buf, maxSize) {
323
- if (buf.buffer.byteLength <= maxSize) return buf
324
- const cpy = Buffer.alloc(buf.byteLength)
325
- buf.copy(cpy)
326
- return cpy
327
- }
328
-
329
- function header (type, size, name) {
330
- var buf = Buffer.alloc(32)
331
-
332
- // magic number
333
- buf[0] = 5
334
- buf[1] = 2
335
- buf[2] = 87
336
- buf[3] = type
337
-
338
- // version
339
- buf[4] = 0
340
-
341
- // block size
342
- buf.writeUInt16BE(size, 5)
343
-
344
- if (name) {
345
- // algo name
346
- buf[7] = name.length
347
- buf.write(name, 8)
348
- }
349
-
350
- return buf
351
- }
352
-
353
- function Node (index, hash, size) {
354
- this.index = index
355
- this.hash = hash
356
- this.size = size
357
- }
358
-
359
- function findNode (nodes, index) {
360
- for (var i = 0; i < nodes.length; i++) {
361
- if (nodes[i].index === index) return nodes[i]
362
- }
363
- return null
364
- }
365
-
366
- function isBlank (buf) {
367
- for (var i = 0; i < buf.length; i++) {
368
- if (buf[i]) return false
369
- }
370
- return true
371
- }
372
-
373
- function close (st, cb) {
374
- if (st.close) st.close(cb)
375
- else cb()
376
- }
377
-
378
- function destroy (st, cb) {
379
- if (st.destroy) st.destroy(cb)
380
- else cb()
381
- }
382
-
383
- function statAndReadAll (st, offset, pageSize, cb) {
384
- st.stat(function (err, stat) {
385
- if (err) return cb(null, [])
386
-
387
- var result = []
388
-
389
- loop(null, null)
390
-
391
- function loop (err, batch) {
392
- if (err) return cb(err)
393
-
394
- if (batch) {
395
- offset += batch.length
396
- for (var i = 0; i < batch.length; i += pageSize) {
397
- result.push(batch.slice(i, i + pageSize))
398
- }
399
- }
400
-
401
- var next = Math.min(stat.size - offset, 32 * pageSize)
402
- if (!next) return cb(null, result)
403
-
404
- st.read(offset, next, loop)
405
- }
406
- })
407
- }
408
-
409
- function readAll (st, offset, pageSize, cb) {
410
- if (st.statable === true) return statAndReadAll(st, offset, pageSize, cb)
411
-
412
- var bufs = []
413
-
414
- st.read(offset, pageSize, loop)
415
-
416
- function loop (err, buf) {
417
- if (err) return cb(null, bufs)
418
- bufs.push(buf)
419
- st.read(offset + bufs.length * pageSize, pageSize, loop)
420
- }
421
- }
package/lib/tree-index.js DELETED
@@ -1,183 +0,0 @@
1
- var flat = require('flat-tree')
2
- var bitfield = require('sparse-bitfield')
3
-
4
- module.exports = TreeIndex
5
-
6
- function TreeIndex (bits) {
7
- if (!(this instanceof TreeIndex)) return new TreeIndex(bits)
8
- this.bitfield = bits || bitfield()
9
- }
10
-
11
- TreeIndex.prototype.proof = function (index, opts) {
12
- if (!opts) opts = {}
13
-
14
- var nodes = []
15
- var remoteTree = opts.tree || new TreeIndex()
16
- var digest = opts.digest || 0
17
-
18
- if (!this.get(index)) return null
19
- if (opts.hash) nodes.push(index) // always return hash - no matter what the digest says
20
- if (digest === 1) return { nodes: nodes, verifiedBy: 0 }
21
-
22
- var roots = null
23
- var sibling = index
24
- var next = index
25
- var hasRoot = digest & 1
26
- digest = rightShift(digest)
27
-
28
- while (digest) {
29
- if (digest === 1 && hasRoot) {
30
- if (this.get(next)) remoteTree.set(next)
31
-
32
- // having a root implies having prev roots as well
33
- // TODO: this can be optimized away be only sending "newer" roots,
34
- // when sending roots
35
- if (flat.sibling(next) < next) next = flat.sibling(next)
36
- roots = flat.fullRoots(flat.rightSpan(next) + 2)
37
- for (var i = 0; i < roots.length; i++) {
38
- if (this.get(roots[i])) remoteTree.set(roots[i])
39
- }
40
- break
41
- }
42
-
43
- sibling = flat.sibling(next)
44
- if (digest & 1) {
45
- if (this.get(sibling)) remoteTree.set(sibling)
46
- }
47
- next = flat.parent(next)
48
- digest = rightShift(digest)
49
- }
50
-
51
- next = index
52
-
53
- while (!remoteTree.get(next)) {
54
- sibling = flat.sibling(next)
55
- if (!this.get(sibling)) {
56
- // next is a local root
57
- var verifiedBy = this.verifiedBy(next)
58
- addFullRoots(verifiedBy, nodes, next, remoteTree)
59
- return { nodes: nodes, verifiedBy: verifiedBy }
60
- } else {
61
- if (!remoteTree.get(sibling)) nodes.push(sibling)
62
- }
63
-
64
- next = flat.parent(next)
65
- }
66
-
67
- return { nodes: nodes, verifiedBy: 0 }
68
- }
69
-
70
- TreeIndex.prototype.digest = function (index) {
71
- if (this.get(index)) return 1
72
-
73
- var digest = 0
74
- var next = flat.sibling(index)
75
- var max = Math.max(next + 2, this.bitfield.length) // TODO: make this less ... hacky
76
-
77
- var bit = 2
78
- var depth = flat.depth(index)
79
- var parent = flat.parent(next, depth++)
80
-
81
- while (flat.rightSpan(next) < max || flat.leftSpan(parent) > 0) {
82
- if (this.get(next)) {
83
- digest += bit // + cause in this case it's the same as | but works for large nums
84
- }
85
- if (this.get(parent)) {
86
- digest += 2 * bit
87
- if (!(digest & 1)) digest += 1
88
- if (digest + 1 === 4 * bit) return 1
89
- return digest
90
- }
91
- next = flat.sibling(parent)
92
- parent = flat.parent(next, depth++)
93
- bit *= 2
94
- }
95
-
96
- return digest
97
- }
98
-
99
- TreeIndex.prototype.blocks = function () {
100
- var top = 0
101
- var next = 0
102
- var max = this.bitfield.length
103
-
104
- while (flat.rightSpan(next) < max) {
105
- next = flat.parent(next)
106
- if (this.get(next)) top = next
107
- }
108
-
109
- return (this.get(top) ? this.verifiedBy(top) : 0) / 2
110
- }
111
-
112
- TreeIndex.prototype.roots = function () {
113
- return flat.fullRoots(2 * this.blocks())
114
- }
115
-
116
- TreeIndex.prototype.verifiedBy = function (index, nodes) {
117
- var hasIndex = this.get(index)
118
- if (!hasIndex) return 0
119
-
120
- // find root of current tree
121
-
122
- var depth = flat.depth(index)
123
- var top = index
124
- var parent = flat.parent(top, depth++)
125
- while (this.get(parent) && this.get(flat.sibling(top))) {
126
- top = parent
127
- parent = flat.parent(top, depth++)
128
- }
129
-
130
- // expand right down
131
-
132
- depth--
133
- while (depth) {
134
- top = flat.leftChild(flat.index(depth, flat.offset(top, depth) + 1), depth)
135
- depth--
136
-
137
- while (!this.get(top) && depth) top = flat.leftChild(top, depth--)
138
- if (nodes && this.get(top)) nodes.push(top)
139
- }
140
-
141
- return this.get(top) ? top + 2 : top
142
- }
143
-
144
- TreeIndex.prototype.get = function (index) {
145
- return this.bitfield.get(index)
146
- }
147
-
148
- TreeIndex.prototype.truncate = function (len) {
149
- const currentLen = 2 * this.blocks()
150
- const roots = flat.fullRoots(len)
151
-
152
- for (let i = len; i < currentLen; i++) {
153
- this.bitfield.set(i, false)
154
- }
155
-
156
- for (const root of roots) {
157
- let p = flat.parent(root)
158
- while (p < len) {
159
- this.bitfield.set(p, false)
160
- p = flat.parent(p)
161
- }
162
- }
163
- }
164
-
165
- TreeIndex.prototype.set = function (index) {
166
- if (!this.bitfield.set(index, true)) return false
167
- while (this.bitfield.get(flat.sibling(index))) {
168
- index = flat.parent(index)
169
- if (!this.bitfield.set(index, true)) break
170
- }
171
- return true
172
- }
173
-
174
- function rightShift (n) {
175
- return (n - (n & 1)) / 2
176
- }
177
-
178
- function addFullRoots (verifiedBy, nodes, root, remoteTree) {
179
- var roots = flat.fullRoots(verifiedBy)
180
- for (var i = 0; i < roots.length; i++) {
181
- if (roots[i] !== root && !remoteTree.get(roots[i])) nodes.push(roots[i])
182
- }
183
- }