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
package/README.md CHANGED
@@ -1,68 +1,40 @@
1
- # hypercore
1
+ # Hypercore 10
2
2
 
3
- Hypercore is a secure, distributed append-only log.
3
+ NOTE: This is the _ALPHA_ version of the upcoming [Hypercore](https://github.com/hypercore-protocol/hypercore) 10 protocol upgrade.
4
4
 
5
- Built for sharing large datasets and streams of real time data as part of the [Hypercore Protocol](https://hypercore-protocol.org).
5
+ Features all the power of Hypercore combined with
6
6
 
7
- ``` sh
8
- npm install hypercore
9
- ```
10
-
11
- [![Build Status](https://github.com/hypercore-protocol/hypercore/workflows/Build%20Status/badge.svg)](https://github.com/hypercore-protocol/hypercore/actions?query=workflow%3A%22Build+Status%22)
12
-
13
- To learn more about how hypercore works on a technical level read the [Dat paper](https://github.com/datprotocol/whitepaper/blob/master/dat-paper.pdf).
14
-
15
- ## Features
16
-
17
- * **Sparse replication.** Only download the data you are interested in.
18
- * **Realtime.** Get the latest updates to the log fast and securely.
19
- * **Performant.** Uses a simple flat file structure to maximize I/O performance.
20
- * **Secure.** Uses signed merkle trees to verify log integrity in real time.
21
- * **Browser support.** Simply pick a storage provider (like [random-access-memory](https://github.com/random-access-storage/random-access-memory)) that works in the browser
7
+ * Multiwriter support
8
+ * Fork recovery
9
+ * Promises
10
+ * Simplications and performance/scaling improvements
11
+ * Internal oplog design
22
12
 
23
- Note that the latest release is Hypercore 8, which is not compatible with Hypercore 7 on the wire format, but storage compatible.
13
+ ## Install
24
14
 
25
- ## Usage
15
+ Install from NPM using the next tag
26
16
 
27
- ``` js
28
- var hypercore = require('hypercore')
29
- var feed = hypercore('./my-first-dataset', {valueEncoding: 'utf-8'})
30
-
31
- feed.append('hello')
32
- feed.append('world', function (err) {
33
- if (err) throw err
34
- feed.get(0, console.log) // prints hello
35
- feed.get(1, console.log) // prints world
36
- })
17
+ ```sh
18
+ npm install hypercore@next
37
19
  ```
38
20
 
39
- To get find other modules that help with building data structures, P2P networks etc on top of Hypercore see the [companion modules](#Companion-modules) list at the bottom of this page.
40
-
41
- ## Terminology
42
-
43
- - **feed**. This is what hypercores are: a data feed. Feeds are permanent data structures that can be shared on the dat network.
44
- - **stream**. Streams are a tool in the code for reading or writing data. Streams are temporary and almost always returned by functions.
45
- - **pipe**. Streams tend to either be readable (giving data) or writable (receiving data). If you connect a readable to a writable, that's called piping.
46
- - **replication stream**. A stream returned by the `replicate()` function which can be piped to a peer. It is used to sync the peers' hypercore feeds.
47
- - **swarming**. Swarming describes adding yourself to the network, finding peers, and sharing data with them. Piping a replication feed describes sharing the data with one peer.
48
-
49
21
  ## API
50
22
 
51
- #### `var feed = hypercore(storage, [key], [options])`
23
+ #### `const core = new Hypercore(storage, [key], [options])`
52
24
 
53
- Create a new hypercore feed.
25
+ Make a new Hypercore instance.
54
26
 
55
- `storage` should be set to a directory where you want to store the data and feed metadata.
27
+ `storage` should be set to a directory where you want to store the data and core metadata.
56
28
 
57
29
  ``` js
58
- var feed = hypercore('./directory') // store data in ./directory
30
+ const core = new Hypercore('./directory') // store data in ./directory
59
31
  ```
60
32
 
61
- Alternatively you can pass a function instead that is called with every filename hypercore needs to function and return your own [abstract-random-access](https://github.com/random-access-storage/abstract-random-access) instance that is used to store the data.
33
+ Alternatively you can pass a function instead that is called with every filename Hypercore needs to function and return your own [abstract-random-access](https://github.com/random-access-storage/abstract-random-access) instance that is used to store the data.
62
34
 
63
35
  ``` js
64
- var ram = require('random-access-memory')
65
- var feed = hypercore(function (filename) {
36
+ const ram = require('random-access-memory')
37
+ const core = new Hypercore((filename) => {
66
38
  // filename will be one of: data, bitfield, tree, signatures, key, secret_key
67
39
  // the data file will contain all your data concatenated.
68
40
 
@@ -71,58 +43,42 @@ var feed = hypercore(function (filename) {
71
43
  })
72
44
  ```
73
45
 
74
- Per default hypercore uses [random-access-file](https://github.com/random-access-storage/random-access-file). This is also useful if you want to store specific files in other directories. For example you might want to store the secret key elsewhere.
46
+ Per default Hypercore uses [random-access-file](https://github.com/random-access-storage/random-access-file). This is also useful if you want to store specific files in other directories.
75
47
 
76
- `key` can be set to a hypercore feed public key. If you do not set this the public key will be loaded from storage. If no key exists a new key pair will be generated.
48
+ Hypercore will produce the following files:
49
+
50
+ * `oplog` - The internal truncating journal/oplog that tracks mutations, the public key and other metadata.
51
+ * `tree` - The Merkle Tree file.
52
+ * `bitfield` - The bitfield of which data blocks this core has.
53
+ * `data` - The raw data of each block.
54
+
55
+ Note that `tree`, `data`, and `bitfield` are normally heavily sparse files.
56
+
57
+ `key` can be set to a Hypercore public key. If you do not set this the public key will be loaded from storage. If no key exists a new key pair will be generated.
77
58
 
78
59
  `options` include:
79
60
 
80
61
  ``` js
81
62
  {
82
- createIfMissing: true, // create a new hypercore key pair if none was present in storage
83
- overwrite: false, // overwrite any old hypercore that might already exist
63
+ createIfMissing: true, // create a new Hypercore key pair if none was present in storage
64
+ overwrite: false, // overwrite any old Hypercore that might already exist
84
65
  valueEncoding: 'json' | 'utf-8' | 'binary', // defaults to binary
85
- sparse: false, // do not mark the entire feed to be downloaded
86
- eagerUpdate: true, // always fetch the latest update that is advertised. default false in sparse mode.
87
- secretKey: buffer, // optionally pass the corresponding secret key yourself
88
- storeSecretKey: true, // if false, will not save the secret key
89
- storageCacheSize: 65536, // the # of entries to keep in the storage system's LRU cache (false or 0 to disable)
90
- onwrite: (index, data, peer, cb) // optional hook called before data is written after being verified
91
- // (remember to call cb() at the end of your handler)
92
- stats: true // collect network-related statistics,
93
- // Optionally use custom cryptography for signatures
94
- crypto: {
95
- sign (data, secretKey, cb(err, signature)),
96
- verify (signature, data, key, cb(err, valid))
97
- }
98
- noiseKeyPair: { publicKey, secretKey } // set a static key pair to use for Noise authentication when replicating
66
+ keyPair: kp, // optionally pass the public key and secret key as a key pair
67
+ encryptionKey: k // optionally pass an encryption key to enable block encryption
99
68
  }
100
69
  ```
101
70
 
102
- You can also set valueEncoding to any [abstract-encoding](https://github.com/mafintosh/abstract-encoding) instance.
103
-
104
- __Note:__ The `[key]` and `secretKey` are _Node.js_ buffer instances, not browser-based ArrayBuffer instances. When creating hypercores in browser, if you pass an ArrayBuffer instance, you will get an error similar to `key must be at least 16, was given undefined`. Instead, create a Node.js Buffer instance using [Feross‘s](https://github.com/feross) [buffer](https://github.com/feross/buffer) module (`npm install buffer`). e.g.,
105
-
106
- ```javascript
107
- const storage = someRandomAccessStorage
108
- const myPublicKey = someUint8Array
109
-
110
- const Buffer = require('buffer').Buffer
111
- const hypercorePublicKeyBuffer = Buffer.from(myPublicKey.buffer)
112
-
113
- const hypercore = hypercore(storage, hypercorePublicKeyBuffer)
114
- ```
115
-
116
- #### `feed.append(data, [callback])`
71
+ You can also set valueEncoding to any [abstract-encoding](https://github.com/mafintosh/abstract-encoding) or [compact-encoding](https://github.com/compact-encoding) instance.
117
72
 
118
- Append a block of data to the feed.
73
+ #### `const seq = await core.append(block)`
119
74
 
120
- Callback is called with `(err, seq)` when all data has been written at the returned `seq` number or error will be not `null`.
75
+ Append a block of data (or an array of blocks) to the core.
76
+ Returns the seq the first block was stored at.
121
77
 
122
- #### `const id = feed.get(index, [options], callback)`
78
+ #### `const block = await core.get(index, [options])`
123
79
 
124
80
  Get a block of data.
125
- If the data is not available locally this method will prioritize and wait for the data to be downloaded before calling the callback.
81
+ If the data is not available locally this method will prioritize and wait for the data to be downloaded.
126
82
 
127
83
  Options include
128
84
 
@@ -131,419 +87,190 @@ Options include
131
87
  wait: true, // wait for index to be downloaded
132
88
  onwait: () => {}, // hook that is called if the get is waiting for download
133
89
  timeout: 0, // wait at max some milliseconds (0 means no timeout)
134
- valueEncoding: 'json' | 'utf-8' | 'binary' // defaults to the feed's valueEncoding
90
+ valueEncoding: 'json' | 'utf-8' | 'binary' // defaults to the core's valueEncoding
135
91
  }
136
92
  ```
137
93
 
138
- Callback is called with `(err, data)`
94
+ #### `await core.truncate(newLength, [forkId])`
139
95
 
140
- #### `feed.getBatch(start, end, [options], callback)`
96
+ Truncate the core to a smaller length.
141
97
 
142
- Get a range of blocks efficiently. End index is non-inclusive. Options include
98
+ Per default this will update the fork id of the core to `+ 1`, but you can set the fork id you prefer with the option.
99
+ Note that the fork id should be monotonely incrementing.
100
+
101
+ #### `const stream = core.createReadStream([options])`
102
+
103
+ Make a read stream. Options include:
143
104
 
144
105
  ``` js
145
106
  {
146
- wait: sameAsAbove,
147
- timeout: sameAsAbove,
148
- valueEncoding: sameAsAbove
107
+ start: 0,
108
+ end: core.length,
109
+ live: false,
110
+ snapshot: true // auto set end to core.length on open or update it on every read
149
111
  }
150
112
  ```
151
113
 
152
- #### `feed.cancel(getId)`
153
-
154
- Cancel a pending get.
114
+ #### `const range = core.download([range])`
155
115
 
156
- #### `feed.head([options], callback)`
116
+ Download a range of data.
157
117
 
158
- Get the block of data at the tip of the feed. This will be the most recently
159
- appended block.
118
+ You can await when the range has been fully downloaded by doing:
160
119
 
161
- Accepts the same `options` as `feed.get()`.
162
-
163
- #### `const id = feed.download([range], [callback])`
120
+ ```js
121
+ await range.downloaded()
122
+ ```
164
123
 
165
- Download a range of data. Callback is called when all data has been downloaded.
166
124
  A range can have the following properties:
167
125
 
168
126
  ``` js
169
127
  {
170
128
  start: startIndex,
171
129
  end: nonInclusiveEndIndex,
130
+ blocks: [index1, index2, ...],
172
131
  linear: false // download range linearly and not randomly
173
132
  }
174
133
  ```
175
134
 
176
- If you do not mark a range the entire feed will be marked for download.
177
-
178
- If you have not enabled sparse mode (`sparse: true` in the feed constructor) then the entire
179
- feed will be marked for download when the feed is created.
180
-
181
- If you have an array of blocks you want to get downloaded you also also pass that
135
+ To download the full core continously (often referred to as non sparse mode) do
182
136
 
183
137
  ``` js
184
- {
185
- blocks: [0, 1, 4, 10] // will download those 4 blocks as fast as possible
186
- }
138
+ // Note that this will never be consider downloaded as the range
139
+ // will keep waiting for new blocks to be appended.
140
+ core.download({ start: 0, end: -1 })
187
141
  ```
188
142
 
189
- #### `feed.undownload(downloadId)`
190
-
191
- Cancel a previous download request.
192
-
193
- #### `feed.signature([index], callback)`
143
+ To downloaded a discrete range of blocks pass a list of indices.
194
144
 
195
- Get a signature proving the correctness of the block at index, or the whole stream.
196
-
197
- Callback is called with `(err, signature)`.
198
- The signature has the following properties:
199
- ``` js
200
- {
201
- index: lastSignedBlock,
202
- signature: Buffer
203
- }
145
+ ```js
146
+ core.download({ blocks: [4, 9, 7] });
204
147
  ```
205
148
 
206
- #### `feed.verify(index, signature, callback)`
207
-
208
- Verify a signature is correct for the data up to index, which must be the last signed
209
- block associated with the signature.
149
+ To cancel downloading a range simply destroy the range instance.
210
150
 
211
- Callback is called with `(err, success)` where success is true only if the signature is
212
- correct.
213
-
214
- #### `feed.rootHashes(index, callback)`
215
-
216
- Retrieve the root *hashes* for given `index`.
217
-
218
- Callback is called with `(err, roots)`; `roots` is an *Array* of *Node* objects:
219
- ```
220
- Node {
221
- index: location in the merkle tree of this root,
222
- size: total bytes in children of this root,
223
- hash: hash of the children of this root (32-byte buffer)
224
- }
151
+ ``` js
152
+ // will stop downloading now
153
+ range.destroy()
225
154
  ```
226
155
 
227
-
228
- #### `var number = feed.downloaded([start], [end])`
229
-
230
- Returns total number of downloaded blocks within range.
231
- If `end` is not specified it will default to the total number of blocks.
232
- If `start` is not specified it will default to 0.
233
-
234
- #### `var bool = feed.has(index)`
235
-
236
- Return true if a data block is available locally.
237
- False otherwise.
238
-
239
- #### `var bool = feed.has(start, end)`
240
- Return true if all data blocks within a range are available locally.
241
- False otherwise.
242
-
243
- #### `feed.clear(start, [end], [callback])`
244
-
245
- Clear a range of data from the local cache.
246
- Will clear the data from the bitfield and make a call to the underlying storage provider to delete the byte range the range occupies.
247
-
248
- `end` defaults to `start + 1`.
249
-
250
- #### `feed.seek(byteOffset, callback)`
156
+ #### `const [index, relativeOffset] = await core.seek(byteOffset)`
251
157
 
252
158
  Seek to a byte offset.
253
159
 
254
- Calls the callback with `(err, index, relativeOffset)`, where `index` is the data block the byteOffset is contained in and `relativeOffset` is
160
+ Returns `(index, relativeOffset)`, where `index` is the data block the byteOffset is contained in and `relativeOffset` is
255
161
  the relative byte offset in the data block.
256
162
 
257
- #### `feed.update([minLength], [callback])`
258
-
259
- Wait for the feed to contain at least `minLength` elements.
260
- If you do not provide `minLength` it will be set to current length + 1.
261
-
262
- Does not download any data from peers except for a proof of the new feed length.
263
-
264
- ``` js
265
- console.log('length is', feed.length)
266
- feed.update(function () {
267
- console.log('length has increased', feed.length)
268
- })
269
- ```
270
-
271
- Per default update will wait until a peer arrives and the update can be performed.
272
- If you only wanna check if any of the current peers you are connected to can
273
- update you (and return an error otherwise if you use the `ifAvailable` option)
274
-
275
- ``` js
276
- feed.update({ ifAvailable: true, minLength: 10 }, function (err) {
277
- // returns an error if non of your current peers can update you
278
- })
279
- ```
280
-
281
- #### `feed.setDownloading(bool)`
282
-
283
- Call this with `false` to make the feed stop downloading from other peers.
284
-
285
- #### `feed.setUploading(bool)`
286
-
287
- Call this with `false` to make the feed stop uploading to other peers.
288
-
289
- #### `var stream = feed.createReadStream([options])`
290
-
291
- Create a readable stream of data.
292
-
293
- Options include:
294
-
295
- ``` js
296
- {
297
- start: 0, // read from this index
298
- end: feed.length, // read until this index
299
- snapshot: true, // if set to false it will update `end` to `feed.length` on every read
300
- tail: false, // sets `start` to `feed.length`
301
- live: false, // set to true to keep reading forever
302
- timeout: 0, // timeout for each data event (0 means no timeout)
303
- wait: true, // wait for data to be downloaded
304
- batch: 1 // amount of messages to read in batch, increasing it (e.g. 100) can improve the performance reading
305
- }
306
- ```
307
-
308
- #### `var stream = feed.createWriteStream(opts)`
309
-
310
- Create a writable stream.
311
- Options include:
312
-
313
- ```
314
- {
315
- maxBlockSize: Infinity // set this to auto chunk individual blocks if they are larger than this number
316
- }
317
- ```
318
-
319
- #### `var stream = feed.replicate(isInitiator, [options])`
163
+ #### `const updated = await core.update()`
320
164
 
321
- Create a replication stream. You should pipe this to another hypercore instance.
322
-
323
- The `isInitiator` argument is a boolean indicating whether you are the iniatior of the connection (ie the client)
324
- or if you are the passive part (ie the server).
325
-
326
- If you are using a P2P swarm like [Hyperswarm](https://github.com/hyperswarm/hyperswarm) you can know this by checking if the swarm connection is a client socket or server socket. In Hyperswarm you can check that using [client property on the peer details object](https://github.com/hyperswarm/hyperswarm#swarmonconnection-socket-details--)
327
-
328
- If you want to multiplex the replication over an existing hypercore replication stream you can pass
329
- another stream instance instead of the `isInitiator` boolean.
165
+ Wait for the core to try and find a signed update to it's length.
166
+ Does not download any data from peers except for a proof of the new core length.
330
167
 
331
168
  ``` js
332
- // assuming we have two feeds, localFeed + remoteFeed, sharing the same key
333
- // on a server
334
- var net = require('net')
335
- var server = net.createServer(function (socket) {
336
- socket.pipe(remoteFeed.replicate(false)).pipe(socket)
337
- })
338
-
339
- // on a client
340
- var socket = net.connect(...)
341
- socket.pipe(localFeed.replicate(true)).pipe(socket)
169
+ const updated = await core.update()
170
+ console.log('core was updated?', updated, 'length is', core.length)
342
171
  ```
343
172
 
344
- Options include:
173
+ #### `await core.close()`
345
174
 
346
- ``` js
347
- {
348
- live: false, // keep replicating after all remote data has been downloaded?
349
- ack: false, // set to true to get explicit acknowledgement when a peer has written a block
350
- download: true, // download data from peers?
351
- upload: true, // upload data to peers?
352
- encrypted: true, // encrypt the data sent using the hypercore key pair
353
- noise: true, // set to false to disable the NOISE handshake completely, and also disable the capability verification. works only together with encrypted = false.
354
- keyPair: { publicKey, secretKey }, // use this keypair for Noise authentication
355
- onauthenticate (remotePublicKey, done) // hook that can be used to authenticate the remote peer.
356
- // calling done with an error will disallow the peer from connecting to you.
357
- onfeedauthenticate (feed, remotePublicKey, done) // hook similar to onauthenticate but called per feed to replicate over a stream of feeds.
358
- // calling done with an error will disallow the peer from syncing this particular feed, but the
359
- // stream will stay open.
360
- }
361
- ```
362
-
363
- When `ack` is `true`, you can listen on the replication `stream` for an `ack`
364
- event:
365
-
366
- ``` js
367
- var stream = feed.replicate({ ack: true })
368
- stream.on('ack', function (ack) {
369
- console.log(ack.start, ack.length)
370
- })
371
- ```
175
+ Fully close this core.
372
176
 
373
- #### `feed.close([callback])`
177
+ #### `core.on('close')`
374
178
 
375
- Fully close this feed.
179
+ Emitted when then core has been fully closed.
376
180
 
377
- Calls the callback with `(err)` when all storage has been closed.
181
+ #### `await core.ready()`
378
182
 
379
- #### `feed.destroyStorage([callback])`
183
+ Wait for the core to fully open.
380
184
 
381
- Destroys all stored data and fully closes this feed.
185
+ After this has called `core.length` and other properties have been set.
382
186
 
383
- Calls the callback with `(err)` when all storage has been deleted and closed.
187
+ In general you do NOT need to wait for `ready`, unless checking a synchronous property,
188
+ as all internals await this themself.
384
189
 
385
- #### `feed.audit([callback])`
190
+ #### `core.on('ready')`
386
191
 
387
- Audit all data in the feed. Will check that all current data stored
388
- matches the hashes in the merkle tree and clear the bitfield if not.
192
+ Emitted after the core has initially opened all it's internal state.
389
193
 
390
- When done a report is passed to the callback that looks like this:
194
+ #### `core.writable`
391
195
 
392
- ```js
393
- {
394
- valid: 10, // how many data blocks matches the hashes
395
- invalid: 0, // how many did not
396
- }
397
- ```
398
-
399
- If a block does not match the hash it is cleared from the data bitfield.
400
-
401
- #### `feed.writable`
402
-
403
- Can we append to this feed?
196
+ Can we append to this core?
404
197
 
405
198
  Populated after `ready` has been emitted. Will be `false` before the event.
406
199
 
407
- #### `feed.readable`
200
+ #### `core.readable`
408
201
 
409
- Can we read from this feed? After closing the feed this will be false.
202
+ Can we read from this core? After closing the core this will be false.
410
203
 
411
204
  Populated after `ready` has been emitted. Will be `false` before the event.
412
205
 
413
- #### `feed.key`
206
+ #### `core.key`
414
207
 
415
- Buffer containing the public key identifying this feed.
208
+ Buffer containing the public key identifying this core.
416
209
 
417
210
  Populated after `ready` has been emitted. Will be `null` before the event.
418
211
 
419
- #### `feed.discoveryKey`
212
+ #### `core.discoveryKey`
420
213
 
421
- Buffer containing a key derived from the feeds' public key.
422
- In contrast to `feed.key` this key does not allow you to verify the data but can be used to announce or look for peers that are sharing the same feed, without leaking the feed key.
214
+ Buffer containing a key derived from the core's public key.
215
+ In contrast to `core.key` this key does not allow you to verify the data but can be used to announce or look for peers that are sharing the same core, without leaking the core key.
423
216
 
424
217
  Populated after `ready` has been emitted. Will be `null` before the event.
425
218
 
426
- #### `feed.length`
219
+ #### `core.encryptionKey`
427
220
 
428
- How many blocks of data are available on this feed?
429
-
430
- Populated after `ready` has been emitted. Will be `0` before the event.
221
+ Buffer containing the optional block encryption key of this core. Will be `null` unless block encryption is enabled.
431
222
 
432
- #### `feed.byteLength`
223
+ #### `core.length`
433
224
 
434
- How much data is available on this feed in bytes?
225
+ How many blocks of data are available on this core?
435
226
 
436
227
  Populated after `ready` has been emitted. Will be `0` before the event.
437
228
 
438
- #### `feed.stats`
229
+ #### `core.byteLength`
439
230
 
440
- Return per-peer and total upload/download counts.
231
+ How much data is available on this core in bytes?
441
232
 
442
- The returned object is of the form:
443
- ```js
444
- {
445
- totals: {
446
- uploadedBytes: 100,
447
- uploadedBlocks: 1,
448
- downloadedBytes: 0,
449
- downloadedBlocks: 0
450
- },
451
- peers: [
452
- {
453
- uploadedBytes: 100,
454
- uploadedBlocks: 1,
455
- downloadedBytes: 0,
456
- downloadedBlocks: 0
457
- },
458
- ...
459
- ]
460
- }
461
- ```
233
+ Populated after `ready` has been emitted. Will be `0` before the event.
462
234
 
463
- Stats will be collected by default, but this can be disabled by setting `opts.stats` to false.
235
+ #### `core.fork`
464
236
 
465
- #### `feed.on('peer-add', peer)`
237
+ What is the current fork id of this core?
466
238
 
467
- Emitted when a peer is added.
239
+ Populated after `ready` has been emitted. Will be `0` before the event.
468
240
 
469
- #### `feed.on('peer-remove', peer)`
241
+ #### `core.padding`
470
242
 
471
- Emitted when a peer is removed.
243
+ How much padding is applied to each block of this core? Will be `0` unless block encryption is enabled.
472
244
 
473
- #### `feed.on('peer-open', peer)`
245
+ #### `const stream = core.replicate(isInitiatorOrReplicationStream)`
474
246
 
475
- Emitted when a peer channel has been fully opened.
247
+ Create a replication stream. You should pipe this to another Hypercore instance.
476
248
 
477
- #### `feed.peers`
249
+ The `isInitiator` argument is a boolean indicating whether you are the iniatior of the connection (ie the client)
250
+ or if you are the passive part (ie the server).
478
251
 
479
- A list of all peers you are connected with.
252
+ If you are using a P2P swarm like [Hyperswarm](https://github.com/hyperswarm/hyperswarm) you can know this by checking if the swarm connection is a client socket or server socket. In Hyperswarm you can check that using the [client property on the peer details object](https://github.com/hyperswarm/hyperswarm#swarmonconnection-socket-details--)
480
253
 
481
- #### `ext = feed.registerExtension(name, handlers)`
254
+ If you want to multiplex the replication over an existing Hypercore replication stream you can pass
255
+ another stream instance instead of the `isInitiator` boolean.
482
256
 
483
- Register a new replication extension. `name` should be the name of your extension and `handlers` should look like this:
257
+ ``` js
258
+ // assuming we have two cores, localCore + remoteCore, sharing the same key
259
+ // on a server
260
+ const net = require('net')
261
+ const server = net.createServer(function (socket) {
262
+ socket.pipe(remoteCore.replicate(false)).pipe(socket)
263
+ })
484
264
 
485
- ```js
486
- {
487
- encoding: 'json' | 'binary' | 'utf-8' | anyAbstractEncoding,
488
- onmessage (message, peer) {
489
- // called when a message is received from a peer
490
- // will be decoded using the encoding you provide
491
- },
492
- onerror (err) {
493
- // called in case of an decoding error
494
- }
495
- }
265
+ // on a client
266
+ const socket = net.connect(...)
267
+ socket.pipe(localCore.replicate(true)).pipe(socket)
496
268
  ```
497
269
 
498
- #### `ext.send(message, peer)`
499
-
500
- Send an extension message to a specific peer.
501
-
502
- #### `ext.broadcast(message)`
503
-
504
- Send a message to every peer you are connected to.
505
-
506
- #### `peer.publicKey`
507
-
508
- Get the public key buffer for this peer. Useful for identifying a peer in the swarm.
509
-
510
- #### `feed.on('ready')`
511
-
512
- Emitted when the feed is ready and all properties have been populated.
513
-
514
- #### `feed.on('error', err)`
515
-
516
- Emitted when the feed experiences a critical error.
517
-
518
- #### `feed.on('download', index, data)`
519
-
520
- Emitted when a data block has been downloaded.
521
-
522
- #### `feed.on('upload', index, data)`
523
-
524
- Emitted when a data block is going to be uploaded.
525
-
526
- #### `feed.on('append')`
527
-
528
- Emitted when the feed has been appended to (i.e. has a new length / byteLength).
529
-
530
- #### `feed.on('sync')`
531
-
532
- Emitted every time ALL data from `0` to `feed.length` has been downloaded.
533
-
534
- #### `feed.on('close')`
535
-
536
- Emitted when the feed has been fully closed
537
-
538
- ## Companion modules
539
-
540
- Hypercore works really well with a series of other modules. This in a non-exhaustive list of some of those:
270
+ #### `core.on('append')`
541
271
 
542
- * [Hyperswarm](https://github.com/hyperswarm/hyperswarm) - P2P swarming module that can you share Hypercores over a network.
543
- * [Hyperswarm replicator](https://github.com/hyperswarm/replicator) - Wanna share a single Hypercore without any hastle over a network?
544
- * [Hyperdrive](https://github.com/hypercore-protocol/hyperdrive) - Filesystem abstraction built on Hypercores
545
- * [Hypertrie](https://github.com/hypercore-protocol/hypertrie) - Scalable key/value store built on Hypercores
272
+ Emitted when the core has been appended to (i.e. has a new length / byteLength), either locally or remotely.
546
273
 
547
- ## License
274
+ #### `core.on('truncate')`
548
275
 
549
- MIT
276
+ Emitted when the core has been truncated, either locally or remotely.