hypercore 10.0.0-alpha.32 → 10.0.0-alpha.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/index.js +38 -11
- package/lib/core.js +25 -14
- package/lib/replicator.js +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -280,6 +280,13 @@ const socket = net.connect(...)
|
|
|
280
280
|
socket.pipe(localCore.replicate(true)).pipe(socket)
|
|
281
281
|
```
|
|
282
282
|
|
|
283
|
+
#### `const done = core.findingPeers()`
|
|
284
|
+
|
|
285
|
+
Create a hook that tells Hypercore you are finding peers for this core in the background. Call `done` when your current discovery iteration is done.
|
|
286
|
+
If you're using Hyperswarm, you'd normally call this after a `swarm.flush()` finishes.
|
|
287
|
+
|
|
288
|
+
This allows `core.update` to wait for either the `findingPeers` hook to finish or one peer to appear before deciding whether it should wait for a merkle tree update before returning.
|
|
289
|
+
|
|
283
290
|
#### `core.on('append')`
|
|
284
291
|
|
|
285
292
|
Emitted when the core has been appended to (i.e. has a new length / byteLength), either locally or remotely.
|
package/index.js
CHANGED
|
@@ -65,7 +65,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
65
65
|
this.opened = false
|
|
66
66
|
this.closed = false
|
|
67
67
|
this.sessions = opts._sessions || [this]
|
|
68
|
-
this.
|
|
68
|
+
this.auth = opts.auth || null
|
|
69
69
|
this.autoClose = !!opts.autoClose
|
|
70
70
|
|
|
71
71
|
this.closing = null
|
|
@@ -74,6 +74,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
74
74
|
|
|
75
75
|
this._preappend = preappend.bind(this)
|
|
76
76
|
this._snapshot = opts.snapshot || null
|
|
77
|
+
this._findingPeers = 0
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
[inspect] (depth, opts) {
|
|
@@ -123,7 +124,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
123
124
|
}
|
|
124
125
|
if (opts.keepAlive !== false) {
|
|
125
126
|
noiseStream.setKeepAlive(5000)
|
|
126
|
-
noiseStream.setTimeout(
|
|
127
|
+
noiseStream.setTimeout(10000)
|
|
127
128
|
}
|
|
128
129
|
noiseStream.userData = protocol
|
|
129
130
|
}
|
|
@@ -168,13 +169,13 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
168
169
|
}
|
|
169
170
|
|
|
170
171
|
_passCapabilities (o) {
|
|
171
|
-
if (!this.
|
|
172
|
+
if (!this.auth) this.auth = o.auth
|
|
172
173
|
this.crypto = o.crypto
|
|
173
174
|
this.key = o.key
|
|
174
175
|
this.core = o.core
|
|
175
176
|
this.replicator = o.replicator
|
|
176
177
|
this.encryption = o.encryption
|
|
177
|
-
this.writable = !!this.sign
|
|
178
|
+
this.writable = !!(this.auth && this.auth.sign)
|
|
178
179
|
this.autoClose = o.autoClose
|
|
179
180
|
}
|
|
180
181
|
|
|
@@ -184,6 +185,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
184
185
|
this._passCapabilities(from)
|
|
185
186
|
this.sessions = from.sessions
|
|
186
187
|
this.storage = from.storage
|
|
188
|
+
this.replicator.findingPeers += this._findingPeers
|
|
187
189
|
|
|
188
190
|
this.sessions.push(this)
|
|
189
191
|
}
|
|
@@ -204,10 +206,12 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
204
206
|
// but we only do this to validate the keypair to help catch bugs so yolo
|
|
205
207
|
if (this.key && keyPair) keyPair.publicKey = this.key
|
|
206
208
|
|
|
207
|
-
if (opts.
|
|
208
|
-
this.
|
|
209
|
+
if (opts.auth) {
|
|
210
|
+
this.auth = opts.auth
|
|
211
|
+
} else if (opts.sign) {
|
|
212
|
+
this.auth = Core.createAuth(this.crypto, keyPair, opts)
|
|
209
213
|
} else if (keyPair && keyPair.secretKey) {
|
|
210
|
-
this.
|
|
214
|
+
this.auth = Core.createAuth(this.crypto, keyPair)
|
|
211
215
|
}
|
|
212
216
|
|
|
213
217
|
if (isFirst) {
|
|
@@ -219,8 +223,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
219
223
|
}
|
|
220
224
|
}
|
|
221
225
|
|
|
222
|
-
if (!this.
|
|
223
|
-
this.writable = !!this.sign
|
|
226
|
+
if (!this.auth) this.auth = this.core.defaultAuth
|
|
227
|
+
this.writable = !!this.auth.sign
|
|
224
228
|
|
|
225
229
|
if (opts.valueEncoding) {
|
|
226
230
|
this.valueEncoding = c.from(codecs(opts.valueEncoding))
|
|
@@ -249,6 +253,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
249
253
|
keyPair,
|
|
250
254
|
crypto: this.crypto,
|
|
251
255
|
legacy: opts.legacy,
|
|
256
|
+
auth: opts.auth,
|
|
252
257
|
onupdate: this._oncoreupdate.bind(this)
|
|
253
258
|
})
|
|
254
259
|
|
|
@@ -268,6 +273,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
268
273
|
onupload: this._onupload.bind(this)
|
|
269
274
|
})
|
|
270
275
|
|
|
276
|
+
this.replicator.findingPeers += this._findingPeers
|
|
277
|
+
|
|
271
278
|
if (!this.encryption && opts.encryptionKey) {
|
|
272
279
|
this.encryption = new BlockEncryption(opts.encryptionKey, this.key)
|
|
273
280
|
}
|
|
@@ -298,9 +305,12 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
298
305
|
for (const ext of gc) ext.destroy()
|
|
299
306
|
|
|
300
307
|
if (this.replicator !== null) {
|
|
308
|
+
this.replicator.findingPeers -= this._findingPeers
|
|
301
309
|
this.replicator.clearRequests(this.activeRequests)
|
|
302
310
|
}
|
|
303
311
|
|
|
312
|
+
this._findingPeers = 0
|
|
313
|
+
|
|
304
314
|
if (this.sessions.length) {
|
|
305
315
|
// if this is the last session and we are auto closing, trigger that first to enforce error handling
|
|
306
316
|
if (this.sessions.length === 1 && this.autoClose) await this.sessions[0].close()
|
|
@@ -429,6 +439,22 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
429
439
|
return null
|
|
430
440
|
}
|
|
431
441
|
|
|
442
|
+
findingPeers () {
|
|
443
|
+
this._findingPeers++
|
|
444
|
+
if (this.replicator !== null && !this.closing) this.replicator.findingPeers++
|
|
445
|
+
|
|
446
|
+
let once = true
|
|
447
|
+
|
|
448
|
+
return () => {
|
|
449
|
+
if (this.closing || !once) return
|
|
450
|
+
once = false
|
|
451
|
+
this._findingPeers--
|
|
452
|
+
if (this.replicator !== null && --this.replicator.findingPeers === 0) {
|
|
453
|
+
this.replicator.updateAll()
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
432
458
|
async update (opts) {
|
|
433
459
|
if (this.opened === false) await this.opening
|
|
434
460
|
|
|
@@ -438,6 +464,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
438
464
|
const activeRequests = (opts && opts.activeRequests) || this.activeRequests
|
|
439
465
|
const req = this.replicator.addUpgrade(activeRequests)
|
|
440
466
|
|
|
467
|
+
// TODO: if snapshot, also update the length/byteLength to latest
|
|
441
468
|
return req.promise
|
|
442
469
|
}
|
|
443
470
|
|
|
@@ -543,7 +570,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
543
570
|
if (this.writable === false) throw new Error('Core is not writable')
|
|
544
571
|
|
|
545
572
|
if (fork === -1) fork = this.core.tree.fork + 1
|
|
546
|
-
await this.core.truncate(newLength, fork, this.
|
|
573
|
+
await this.core.truncate(newLength, fork, this.auth)
|
|
547
574
|
|
|
548
575
|
// TODO: Should propagate from an event triggered by the oplog
|
|
549
576
|
this.replicator.updateAll()
|
|
@@ -565,7 +592,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
565
592
|
}
|
|
566
593
|
}
|
|
567
594
|
|
|
568
|
-
return await this.core.append(buffers, this.
|
|
595
|
+
return await this.core.append(buffers, this.auth, { preappend })
|
|
569
596
|
}
|
|
570
597
|
|
|
571
598
|
async treeHash (length) {
|
package/lib/core.js
CHANGED
|
@@ -8,7 +8,7 @@ const Bitfield = require('./bitfield')
|
|
|
8
8
|
const m = require('./messages')
|
|
9
9
|
|
|
10
10
|
module.exports = class Core {
|
|
11
|
-
constructor (header, crypto, oplog, tree, blocks, bitfield,
|
|
11
|
+
constructor (header, crypto, oplog, tree, blocks, bitfield, auth, legacy, onupdate) {
|
|
12
12
|
this.onupdate = onupdate
|
|
13
13
|
this.header = header
|
|
14
14
|
this.crypto = crypto
|
|
@@ -16,7 +16,7 @@ module.exports = class Core {
|
|
|
16
16
|
this.tree = tree
|
|
17
17
|
this.blocks = blocks
|
|
18
18
|
this.bitfield = bitfield
|
|
19
|
-
this.
|
|
19
|
+
this.defaultAuth = auth
|
|
20
20
|
this.truncating = 0
|
|
21
21
|
|
|
22
22
|
this._maxOplogSize = 65536
|
|
@@ -51,10 +51,21 @@ module.exports = class Core {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
static createAuth (crypto, { publicKey, secretKey }, opts = {}) {
|
|
55
|
+
if (secretKey && !crypto.validateKeyPair({ publicKey, secretKey })) throw new Error('Invalid key pair')
|
|
56
|
+
|
|
57
|
+
const sign = opts.sign
|
|
58
|
+
? opts.sign
|
|
59
|
+
: secretKey
|
|
60
|
+
? (signable) => crypto.sign(signable, secretKey)
|
|
61
|
+
: undefined
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
sign,
|
|
65
|
+
verify (signable, signature) {
|
|
66
|
+
return crypto.verify(signable, signature, publicKey)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
58
69
|
}
|
|
59
70
|
|
|
60
71
|
static async resume (oplogFile, treeFile, bitfieldFile, dataFile, opts) {
|
|
@@ -116,7 +127,7 @@ module.exports = class Core {
|
|
|
116
127
|
await bitfield.clear()
|
|
117
128
|
}
|
|
118
129
|
|
|
119
|
-
const
|
|
130
|
+
const auth = opts.auth || this.createAuth(crypto, header.signer)
|
|
120
131
|
|
|
121
132
|
for (const e of entries) {
|
|
122
133
|
if (e.userData) {
|
|
@@ -147,7 +158,7 @@ module.exports = class Core {
|
|
|
147
158
|
}
|
|
148
159
|
}
|
|
149
160
|
|
|
150
|
-
return new this(header, crypto, oplog, tree, blocks, bitfield,
|
|
161
|
+
return new this(header, crypto, oplog, tree, blocks, bitfield, auth, !!opts.legacy, opts.onupdate || noop)
|
|
151
162
|
}
|
|
152
163
|
|
|
153
164
|
_shouldFlush () {
|
|
@@ -212,13 +223,13 @@ module.exports = class Core {
|
|
|
212
223
|
}
|
|
213
224
|
}
|
|
214
225
|
|
|
215
|
-
async truncate (length, fork,
|
|
226
|
+
async truncate (length, fork, auth = this.defaultAuth) {
|
|
216
227
|
this.truncating++
|
|
217
228
|
await this._mutex.lock()
|
|
218
229
|
|
|
219
230
|
try {
|
|
220
231
|
const batch = await this.tree.truncate(length, fork)
|
|
221
|
-
batch.signature = await sign(batch.signable())
|
|
232
|
+
batch.signature = await auth.sign(batch.signable())
|
|
222
233
|
await this._truncate(batch, null)
|
|
223
234
|
} finally {
|
|
224
235
|
this.truncating--
|
|
@@ -226,7 +237,7 @@ module.exports = class Core {
|
|
|
226
237
|
}
|
|
227
238
|
}
|
|
228
239
|
|
|
229
|
-
async append (values,
|
|
240
|
+
async append (values, auth = this.defaultAuth, hooks = {}) {
|
|
230
241
|
await this._mutex.lock()
|
|
231
242
|
|
|
232
243
|
try {
|
|
@@ -238,7 +249,7 @@ module.exports = class Core {
|
|
|
238
249
|
for (const val of values) batch.append(val)
|
|
239
250
|
|
|
240
251
|
const hash = batch.hash()
|
|
241
|
-
batch.signature = await sign(this._legacy ? batch.signableLegacy(hash) : batch.signable(hash))
|
|
252
|
+
batch.signature = await auth.sign(this._legacy ? batch.signableLegacy(hash) : batch.signable(hash))
|
|
242
253
|
|
|
243
254
|
const entry = {
|
|
244
255
|
userData: null,
|
|
@@ -270,9 +281,9 @@ module.exports = class Core {
|
|
|
270
281
|
}
|
|
271
282
|
}
|
|
272
283
|
|
|
273
|
-
_signed (batch, hash) {
|
|
284
|
+
_signed (batch, hash, auth = this.defaultAuth) {
|
|
274
285
|
const signable = this._legacy ? batch.signableLegacy(hash) : batch.signable(hash)
|
|
275
|
-
return
|
|
286
|
+
return auth.verify(signable, batch.signature)
|
|
276
287
|
}
|
|
277
288
|
|
|
278
289
|
async _verifyExclusive ({ batch, bitfield, value, from }) {
|
package/lib/replicator.js
CHANGED
|
@@ -842,6 +842,7 @@ module.exports = class Replicator {
|
|
|
842
842
|
this.onpeerupdate = onpeerupdate
|
|
843
843
|
this.onupload = onupload
|
|
844
844
|
this.peers = []
|
|
845
|
+
this.findingPeers = 0 // updateable from the outside
|
|
845
846
|
|
|
846
847
|
this._inflight = new InflightTracker()
|
|
847
848
|
this._blocks = new BlockTracker(core)
|
|
@@ -854,6 +855,7 @@ module.exports = class Replicator {
|
|
|
854
855
|
this._reorgs = []
|
|
855
856
|
this._ranges = []
|
|
856
857
|
|
|
858
|
+
this._hadPeers = false
|
|
857
859
|
this._ifAvailable = 0
|
|
858
860
|
this._updatesPending = 0
|
|
859
861
|
this._applyingReorg = false
|
|
@@ -959,6 +961,7 @@ module.exports = class Replicator {
|
|
|
959
961
|
// Do this when we have more tests.
|
|
960
962
|
_checkUpgradeIfAvailable () {
|
|
961
963
|
if (this._ifAvailable > 0 || this._upgrade === null || this._upgrade.refs.length === 0) return
|
|
964
|
+
if (this._hadPeers === false && this.findingPeers > 0) return
|
|
962
965
|
|
|
963
966
|
// check if a peer can upgrade us
|
|
964
967
|
|
|
@@ -1047,6 +1050,7 @@ module.exports = class Replicator {
|
|
|
1047
1050
|
}
|
|
1048
1051
|
|
|
1049
1052
|
_addPeer (peer) {
|
|
1053
|
+
this._hadPeers = true
|
|
1050
1054
|
this.peers.push(peer)
|
|
1051
1055
|
this.updatePeer(peer)
|
|
1052
1056
|
this.onpeerupdate(true, peer)
|