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.
- package/.github/workflows/test-node.yml +3 -4
- package/README.md +131 -404
- package/__snapshots__/test/storage.js.snapshot.cjs +15 -0
- package/examples/announce.js +19 -0
- package/examples/basic.js +10 -0
- package/examples/http.js +123 -0
- package/examples/lookup.js +20 -0
- package/index.js +365 -1600
- package/lib/bitfield.js +113 -285
- package/lib/block-encryption.js +68 -0
- package/lib/block-store.js +58 -0
- package/lib/core.js +468 -0
- package/lib/extensions.js +76 -0
- package/lib/merkle-tree.js +1110 -0
- package/lib/messages.js +571 -0
- package/lib/mutex.js +39 -0
- package/lib/oplog.js +224 -0
- package/lib/protocol.js +525 -0
- package/lib/random-iterator.js +46 -0
- package/lib/remote-bitfield.js +24 -0
- package/lib/replicator.js +857 -0
- package/lib/streams.js +39 -0
- package/package.json +44 -45
- package/test/basic.js +59 -471
- package/test/bitfield.js +48 -133
- package/test/core.js +290 -0
- package/test/encodings.js +18 -0
- package/test/encryption.js +123 -0
- package/test/extension.js +71 -0
- package/test/helpers/index.js +23 -0
- package/test/merkle-tree.js +518 -0
- package/test/mutex.js +137 -0
- package/test/oplog.js +399 -0
- package/test/preload.js +72 -0
- package/test/replicate.js +227 -824
- package/test/sessions.js +173 -0
- package/test/storage.js +31 -0
- package/test/streams.js +39 -146
- package/test/user-data.js +47 -0
- package/bench/all.sh +0 -65
- package/bench/copy-64kb-blocks.js +0 -51
- package/bench/helpers/read-throttled.js +0 -27
- package/bench/helpers/read.js +0 -47
- package/bench/helpers/write.js +0 -29
- package/bench/read-16kb-blocks-proof-throttled.js +0 -1
- package/bench/read-16kb-blocks-proof.js +0 -1
- package/bench/read-16kb-blocks-throttled.js +0 -1
- package/bench/read-16kb-blocks.js +0 -1
- package/bench/read-512b-blocks.js +0 -1
- package/bench/read-64kb-blocks-linear-batch.js +0 -18
- package/bench/read-64kb-blocks-linear.js +0 -18
- package/bench/read-64kb-blocks-proof.js +0 -1
- package/bench/read-64kb-blocks.js +0 -1
- package/bench/replicate-16kb-blocks.js +0 -19
- package/bench/replicate-64kb-blocks.js +0 -19
- package/bench/write-16kb-blocks.js +0 -1
- package/bench/write-512b-blocks.js +0 -1
- package/bench/write-64kb-blocks-static.js +0 -1
- package/bench/write-64kb-blocks.js +0 -1
- package/example.js +0 -23
- package/lib/cache.js +0 -26
- package/lib/crypto.js +0 -5
- package/lib/replicate.js +0 -829
- package/lib/safe-buffer-equals.js +0 -6
- package/lib/storage.js +0 -421
- package/lib/tree-index.js +0 -183
- package/test/ack.js +0 -306
- package/test/audit.js +0 -36
- package/test/cache.js +0 -93
- package/test/compat.js +0 -209
- package/test/copy.js +0 -377
- package/test/default-storage.js +0 -51
- package/test/extensions.js +0 -137
- package/test/get.js +0 -64
- package/test/head.js +0 -65
- package/test/helpers/create-tracking-ram.js +0 -27
- package/test/helpers/create.js +0 -6
- package/test/helpers/replicate.js +0 -4
- package/test/seek.js +0 -234
- package/test/selections.js +0 -95
- package/test/set-uploading-downloading.js +0 -91
- package/test/stats.js +0 -77
- package/test/timeouts.js +0 -22
- package/test/tree-index.js +0 -841
- package/test/update.js +0 -156
- package/test/value-encoding.js +0 -52
package/README.md
CHANGED
|
@@ -1,68 +1,40 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Hypercore 10
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
NOTE: This is the _ALPHA_ version of the upcoming [Hypercore](https://github.com/hypercore-protocol/hypercore) 10 protocol upgrade.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Features all the power of Hypercore combined with
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
13
|
+
## Install
|
|
24
14
|
|
|
25
|
-
|
|
15
|
+
Install from NPM using the next tag
|
|
26
16
|
|
|
27
|
-
```
|
|
28
|
-
|
|
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
|
-
#### `
|
|
23
|
+
#### `const core = new Hypercore(storage, [key], [options])`
|
|
52
24
|
|
|
53
|
-
|
|
25
|
+
Make a new Hypercore instance.
|
|
54
26
|
|
|
55
|
-
`storage` should be set to a directory where you want to store the data and
|
|
27
|
+
`storage` should be set to a directory where you want to store the data and core metadata.
|
|
56
28
|
|
|
57
29
|
``` js
|
|
58
|
-
|
|
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
|
|
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
|
-
|
|
65
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
83
|
-
overwrite: false, // overwrite any old
|
|
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
|
-
|
|
86
|
-
|
|
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
|
-
|
|
73
|
+
#### `const seq = await core.append(block)`
|
|
119
74
|
|
|
120
|
-
|
|
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
|
|
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
|
|
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
|
|
90
|
+
valueEncoding: 'json' | 'utf-8' | 'binary' // defaults to the core's valueEncoding
|
|
135
91
|
}
|
|
136
92
|
```
|
|
137
93
|
|
|
138
|
-
|
|
94
|
+
#### `await core.truncate(newLength, [forkId])`
|
|
139
95
|
|
|
140
|
-
|
|
96
|
+
Truncate the core to a smaller length.
|
|
141
97
|
|
|
142
|
-
|
|
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
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
#### `
|
|
153
|
-
|
|
154
|
-
Cancel a pending get.
|
|
114
|
+
#### `const range = core.download([range])`
|
|
155
115
|
|
|
156
|
-
|
|
116
|
+
Download a range of data.
|
|
157
117
|
|
|
158
|
-
|
|
159
|
-
appended block.
|
|
118
|
+
You can await when the range has been fully downloaded by doing:
|
|
160
119
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
212
|
-
|
|
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
|
-
|
|
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
|
-
#### `
|
|
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
|
-
|
|
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
|
-
|
|
333
|
-
|
|
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
|
-
|
|
173
|
+
#### `await core.close()`
|
|
345
174
|
|
|
346
|
-
|
|
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
|
-
#### `
|
|
177
|
+
#### `core.on('close')`
|
|
374
178
|
|
|
375
|
-
|
|
179
|
+
Emitted when then core has been fully closed.
|
|
376
180
|
|
|
377
|
-
|
|
181
|
+
#### `await core.ready()`
|
|
378
182
|
|
|
379
|
-
|
|
183
|
+
Wait for the core to fully open.
|
|
380
184
|
|
|
381
|
-
|
|
185
|
+
After this has called `core.length` and other properties have been set.
|
|
382
186
|
|
|
383
|
-
|
|
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
|
-
#### `
|
|
190
|
+
#### `core.on('ready')`
|
|
386
191
|
|
|
387
|
-
|
|
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
|
-
|
|
194
|
+
#### `core.writable`
|
|
391
195
|
|
|
392
|
-
|
|
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
|
-
#### `
|
|
200
|
+
#### `core.readable`
|
|
408
201
|
|
|
409
|
-
Can we read from this
|
|
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
|
-
#### `
|
|
206
|
+
#### `core.key`
|
|
414
207
|
|
|
415
|
-
Buffer containing the public key identifying this
|
|
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
|
-
#### `
|
|
212
|
+
#### `core.discoveryKey`
|
|
420
213
|
|
|
421
|
-
Buffer containing a key derived from the
|
|
422
|
-
In contrast to `
|
|
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
|
-
#### `
|
|
219
|
+
#### `core.encryptionKey`
|
|
427
220
|
|
|
428
|
-
|
|
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
|
-
#### `
|
|
223
|
+
#### `core.length`
|
|
433
224
|
|
|
434
|
-
How
|
|
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
|
-
#### `
|
|
229
|
+
#### `core.byteLength`
|
|
439
230
|
|
|
440
|
-
|
|
231
|
+
How much data is available on this core in bytes?
|
|
441
232
|
|
|
442
|
-
|
|
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
|
-
|
|
235
|
+
#### `core.fork`
|
|
464
236
|
|
|
465
|
-
|
|
237
|
+
What is the current fork id of this core?
|
|
466
238
|
|
|
467
|
-
|
|
239
|
+
Populated after `ready` has been emitted. Will be `0` before the event.
|
|
468
240
|
|
|
469
|
-
#### `
|
|
241
|
+
#### `core.padding`
|
|
470
242
|
|
|
471
|
-
|
|
243
|
+
How much padding is applied to each block of this core? Will be `0` unless block encryption is enabled.
|
|
472
244
|
|
|
473
|
-
#### `
|
|
245
|
+
#### `const stream = core.replicate(isInitiatorOrReplicationStream)`
|
|
474
246
|
|
|
475
|
-
|
|
247
|
+
Create a replication stream. You should pipe this to another Hypercore instance.
|
|
476
248
|
|
|
477
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
486
|
-
|
|
487
|
-
|
|
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
|
-
#### `
|
|
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
|
-
|
|
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
|
-
|
|
274
|
+
#### `core.on('truncate')`
|
|
548
275
|
|
|
549
|
-
|
|
276
|
+
Emitted when the core has been truncated, either locally or remotely.
|