hypercore 11.3.0 → 11.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/index.js +17 -56
- package/lib/caps.js +2 -2
- package/lib/default-encryption.js +116 -0
- package/lib/messages.js +23 -13
- package/lib/verifier.js +11 -4
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -68,6 +68,8 @@ You can also set valueEncoding to any [compact-encoding](https://github.com/comp
|
|
|
68
68
|
|
|
69
69
|
valueEncodings will be applied to individual blocks, even if you append batches. If you want to control encoding at the batch-level, you can use the `encodeBatch` option, which is a function that takes a batch and returns a binary-encoded batch. If you provide a custom valueEncoding, it will not be applied prior to `encodeBatch`.
|
|
70
70
|
|
|
71
|
+
The user may provide a custom encryption module as `opts.encryption`, which should satisfy the [HypercoreEncryption](https://github.com/holepunchto/hypercore-encryption) interface.
|
|
72
|
+
|
|
71
73
|
#### `const { length, byteLength } = await core.append(block)`
|
|
72
74
|
|
|
73
75
|
Append a block of data (or an array of blocks) to the core.
|
package/index.js
CHANGED
|
@@ -3,10 +3,8 @@ const isOptions = require('is-options')
|
|
|
3
3
|
const crypto = require('hypercore-crypto')
|
|
4
4
|
const CoreStorage = require('hypercore-storage')
|
|
5
5
|
const c = require('compact-encoding')
|
|
6
|
-
const sodium = require('sodium-universal')
|
|
7
6
|
const b4a = require('b4a')
|
|
8
7
|
const NoiseSecretStream = require('@hyperswarm/secret-stream')
|
|
9
|
-
const HypercoreEncryption = require('hypercore-encryption')
|
|
10
8
|
const Protomux = require('protomux')
|
|
11
9
|
const id = require('hypercore-id-encoding')
|
|
12
10
|
const safetyCatch = require('safety-catch')
|
|
@@ -15,6 +13,7 @@ const unslab = require('unslab')
|
|
|
15
13
|
const Core = require('./lib/core')
|
|
16
14
|
const Info = require('./lib/info')
|
|
17
15
|
const Download = require('./lib/download')
|
|
16
|
+
const DefaultEncryption = require('./lib/default-encryption')
|
|
18
17
|
const caps = require('./lib/caps')
|
|
19
18
|
const { manifestHash, createManifest } = require('./lib/verifier')
|
|
20
19
|
const { ReadStream, WriteStream, ByteStream } = require('./lib/streams')
|
|
@@ -35,37 +34,6 @@ const inspect = Symbol.for('nodejs.util.inspect.custom')
|
|
|
35
34
|
// but we enforce 15mb to ensure smooth replication (each block is transmitted atomically)
|
|
36
35
|
const MAX_SUGGESTED_BLOCK_SIZE = 15 * 1024 * 1024
|
|
37
36
|
|
|
38
|
-
class DefaultEncryption extends HypercoreEncryption {
|
|
39
|
-
constructor (encryptionKey, isBlock, opts) {
|
|
40
|
-
super(opts)
|
|
41
|
-
|
|
42
|
-
this.encryptionKey = encryptionKey
|
|
43
|
-
this.isBlock = !!isBlock
|
|
44
|
-
|
|
45
|
-
this.blockKey = null
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
_init (context) {
|
|
49
|
-
this.blockKey = getLegacyBlockKey(context.key, this.encryptionKey, context.compat, this.isBlock)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
_getBlockKey (id, context) {
|
|
53
|
-
if (!this.blockKey) this._init(context)
|
|
54
|
-
|
|
55
|
-
return {
|
|
56
|
-
id: 0,
|
|
57
|
-
version: context.manifest.version <= 1 ? 0 : 1,
|
|
58
|
-
key: this.blockKey
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
_getBlindingKey (context) {
|
|
63
|
-
if (!this.blockKey) this._init(context)
|
|
64
|
-
|
|
65
|
-
return crypto.hash(this.blockKey)
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
37
|
class Hypercore extends EventEmitter {
|
|
70
38
|
constructor (storage, key, opts) {
|
|
71
39
|
super()
|
|
@@ -171,6 +139,8 @@ class Hypercore extends EventEmitter {
|
|
|
171
139
|
|
|
172
140
|
static MAX_SUGGESTED_BLOCK_SIZE = MAX_SUGGESTED_BLOCK_SIZE
|
|
173
141
|
|
|
142
|
+
static DefaultEncryption = DefaultEncryption
|
|
143
|
+
|
|
174
144
|
static key (manifest, { compat, version, namespace } = {}) {
|
|
175
145
|
if (b4a.isBuffer(manifest)) manifest = { version, signers: [{ publicKey: manifest, namespace }] }
|
|
176
146
|
return compat ? manifest.signers[0].publicKey : manifestHash(createManifest(manifest))
|
|
@@ -181,7 +151,7 @@ class Hypercore extends EventEmitter {
|
|
|
181
151
|
}
|
|
182
152
|
|
|
183
153
|
static blockEncryptionKey (key, encryptionKey) {
|
|
184
|
-
return
|
|
154
|
+
return DefaultEncryption.blockEncryptionKey(key, encryptionKey)
|
|
185
155
|
}
|
|
186
156
|
|
|
187
157
|
static getProtocolMuxer (stream) {
|
|
@@ -278,8 +248,8 @@ class Hypercore extends EventEmitter {
|
|
|
278
248
|
return
|
|
279
249
|
}
|
|
280
250
|
|
|
281
|
-
if (!(encryption
|
|
282
|
-
throw new Error('
|
|
251
|
+
if (!isEncryptionProvider(encryption)) {
|
|
252
|
+
throw new Error('Provider does not satisfy HypercoreEncryption interface')
|
|
283
253
|
}
|
|
284
254
|
|
|
285
255
|
this.encryption = encryption
|
|
@@ -361,7 +331,7 @@ class Hypercore extends EventEmitter {
|
|
|
361
331
|
|
|
362
332
|
const e = getEncryptionOption(opts)
|
|
363
333
|
if (!this.core.encryption && e) {
|
|
364
|
-
if (e
|
|
334
|
+
if (isEncryptionProvider(e)) {
|
|
365
335
|
this.core.encryption = e
|
|
366
336
|
} else {
|
|
367
337
|
this.core.encryption = this._getEncryptionProvider(e.key, e.block)
|
|
@@ -624,7 +594,7 @@ class Hypercore extends EventEmitter {
|
|
|
624
594
|
|
|
625
595
|
get padding () {
|
|
626
596
|
if (this.encryption && this.key && this.manifest) {
|
|
627
|
-
return this.encryption.padding(this.core)
|
|
597
|
+
return this.encryption.padding(this.core, this.length)
|
|
628
598
|
}
|
|
629
599
|
|
|
630
600
|
return 0
|
|
@@ -820,7 +790,7 @@ class Hypercore extends EventEmitter {
|
|
|
820
790
|
await this.encryption.decrypt(index, block, this.core)
|
|
821
791
|
}
|
|
822
792
|
|
|
823
|
-
return this._decode(encoding, block)
|
|
793
|
+
return this._decode(encoding, block, index)
|
|
824
794
|
}
|
|
825
795
|
|
|
826
796
|
async clear (start, end = start + 1, opts) {
|
|
@@ -966,7 +936,6 @@ class Hypercore extends EventEmitter {
|
|
|
966
936
|
blocks = Array.isArray(blocks) ? blocks : [blocks]
|
|
967
937
|
|
|
968
938
|
const preappend = this.encryption && this._preappend
|
|
969
|
-
await this._ensureEncryption()
|
|
970
939
|
|
|
971
940
|
const buffers = this.encodeBatch !== null ? this.encodeBatch(blocks) : new Array(blocks.length)
|
|
972
941
|
|
|
@@ -1085,8 +1054,8 @@ class Hypercore extends EventEmitter {
|
|
|
1085
1054
|
return state.buffer
|
|
1086
1055
|
}
|
|
1087
1056
|
|
|
1088
|
-
_decode (enc, block) {
|
|
1089
|
-
if (this.
|
|
1057
|
+
_decode (enc, block, index) {
|
|
1058
|
+
if (this.encryption) block = block.subarray(this.encryption.padding(this.core, index))
|
|
1090
1059
|
try {
|
|
1091
1060
|
if (enc) return c.decode(enc, block)
|
|
1092
1061
|
} catch {
|
|
@@ -1095,14 +1064,9 @@ class Hypercore extends EventEmitter {
|
|
|
1095
1064
|
return block
|
|
1096
1065
|
}
|
|
1097
1066
|
|
|
1098
|
-
_ensureEncryption () {
|
|
1099
|
-
if (!this.encryption) return
|
|
1100
|
-
if (this.encryption.version === -1) return this.encryption.load(-1, this.core)
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
1067
|
_getEncryptionProvider (encryptionKey, block) {
|
|
1104
1068
|
if (!encryptionKey) return null
|
|
1105
|
-
return new DefaultEncryption(encryptionKey, block)
|
|
1069
|
+
return new DefaultEncryption(encryptionKey, this.key, { block, compat: this.core.compat })
|
|
1106
1070
|
}
|
|
1107
1071
|
}
|
|
1108
1072
|
|
|
@@ -1189,13 +1153,10 @@ function getEncryptionOption (opts) {
|
|
|
1189
1153
|
return b4a.isBuffer(opts.encryption) ? { key: opts.encryption } : opts.encryption
|
|
1190
1154
|
}
|
|
1191
1155
|
|
|
1192
|
-
function
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
const key = b4a.alloc(HypercoreEncryption.KEYBYTES)
|
|
1196
|
-
|
|
1197
|
-
if (compat) sodium.crypto_generichash_batch(key, [encryptionKey], hypercoreKey)
|
|
1198
|
-
else sodium.crypto_generichash_batch(key, [caps.LEGACY_BLOCK_ENCRYPTION, hypercoreKey, encryptionKey])
|
|
1156
|
+
function isEncryptionProvider (e) {
|
|
1157
|
+
return e && isFunction(e.padding) && isFunction(e.encrypt) && isFunction(e.decrypt)
|
|
1158
|
+
}
|
|
1199
1159
|
|
|
1200
|
-
|
|
1160
|
+
function isFunction (fn) {
|
|
1161
|
+
return !!fn && typeof fn === 'function'
|
|
1201
1162
|
}
|
package/lib/caps.js
CHANGED
|
@@ -12,12 +12,12 @@ const [
|
|
|
12
12
|
REPLICATE_RESPONDER,
|
|
13
13
|
MANIFEST,
|
|
14
14
|
DEFAULT_NAMESPACE,
|
|
15
|
-
|
|
15
|
+
DEFAULT_ENCRYPTION
|
|
16
16
|
] = crypto.namespace('hypercore', 6)
|
|
17
17
|
|
|
18
18
|
exports.MANIFEST = MANIFEST
|
|
19
19
|
exports.DEFAULT_NAMESPACE = DEFAULT_NAMESPACE
|
|
20
|
-
exports.
|
|
20
|
+
exports.DEFAULT_ENCRYPTION = DEFAULT_ENCRYPTION
|
|
21
21
|
|
|
22
22
|
exports.replicate = function (isInitiator, key, handshakeHash) {
|
|
23
23
|
const out = b4a.allocUnsafe(32)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const sodium = require('sodium-universal')
|
|
2
|
+
const c = require('compact-encoding')
|
|
3
|
+
const b4a = require('b4a')
|
|
4
|
+
const { DEFAULT_ENCRYPTION } = require('./caps')
|
|
5
|
+
|
|
6
|
+
const nonce = b4a.alloc(sodium.crypto_stream_NONCEBYTES)
|
|
7
|
+
|
|
8
|
+
module.exports = class DefaultEncryption {
|
|
9
|
+
static PADDING = 8
|
|
10
|
+
|
|
11
|
+
constructor (encryptionKey, hypercoreKey, { block = false, compat = true } = {}) {
|
|
12
|
+
this.key = encryptionKey
|
|
13
|
+
this.compat = compat
|
|
14
|
+
|
|
15
|
+
const keys = DefaultEncryption.deriveKeys(encryptionKey, hypercoreKey, block, compat)
|
|
16
|
+
|
|
17
|
+
this.blockKey = keys.block
|
|
18
|
+
this.blindingKey = keys.blinding
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static deriveKeys (encryptionKey, hypercoreKey, block, compat) {
|
|
22
|
+
const subKeys = b4a.alloc(2 * sodium.crypto_stream_KEYBYTES)
|
|
23
|
+
|
|
24
|
+
const blockKey = block ? encryptionKey : subKeys.subarray(0, sodium.crypto_stream_KEYBYTES)
|
|
25
|
+
const blindingKey = subKeys.subarray(sodium.crypto_stream_KEYBYTES)
|
|
26
|
+
|
|
27
|
+
if (!block) {
|
|
28
|
+
if (compat) sodium.crypto_generichash_batch(blockKey, [encryptionKey], hypercoreKey)
|
|
29
|
+
else sodium.crypto_generichash_batch(blockKey, [DEFAULT_ENCRYPTION, hypercoreKey, encryptionKey])
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
sodium.crypto_generichash(blindingKey, blockKey)
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
blinding: blindingKey,
|
|
36
|
+
block: blockKey
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static blockEncryptionKey (hypercoreKey, encryptionKey) {
|
|
41
|
+
const blockKey = b4a.alloc(sodium.crypto_stream_KEYBYTES)
|
|
42
|
+
sodium.crypto_generichash_batch(blockKey, [DEFAULT_ENCRYPTION, hypercoreKey, encryptionKey])
|
|
43
|
+
return blockKey
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static encrypt (index, block, fork, blockKey, blindingKey) {
|
|
47
|
+
const padding = block.subarray(0, DefaultEncryption.PADDING)
|
|
48
|
+
block = block.subarray(DefaultEncryption.PADDING)
|
|
49
|
+
|
|
50
|
+
c.uint64.encode({ start: 0, end: 8, buffer: padding }, fork)
|
|
51
|
+
c.uint64.encode({ start: 0, end: 8, buffer: nonce }, index)
|
|
52
|
+
|
|
53
|
+
// Zero out any previous padding.
|
|
54
|
+
nonce.fill(0, 8, 8 + padding.byteLength)
|
|
55
|
+
|
|
56
|
+
// Blind the fork ID, possibly risking reusing the nonce on a reorg of the
|
|
57
|
+
// Hypercore. This is fine as the blinding is best-effort and the latest
|
|
58
|
+
// fork ID shared on replication anyway.
|
|
59
|
+
sodium.crypto_stream_xor(
|
|
60
|
+
padding,
|
|
61
|
+
padding,
|
|
62
|
+
nonce,
|
|
63
|
+
blindingKey
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
nonce.set(padding, 8)
|
|
67
|
+
|
|
68
|
+
// The combination of a (blinded) fork ID and a block index is unique for a
|
|
69
|
+
// given Hypercore and is therefore a valid nonce for encrypting the block.
|
|
70
|
+
sodium.crypto_stream_xor(
|
|
71
|
+
block,
|
|
72
|
+
block,
|
|
73
|
+
nonce,
|
|
74
|
+
blockKey
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static decrypt (index, block, blockKey) {
|
|
79
|
+
const padding = block.subarray(0, DefaultEncryption.PADDING)
|
|
80
|
+
block = block.subarray(DefaultEncryption.PADDING)
|
|
81
|
+
|
|
82
|
+
c.uint64.encode({ start: 0, end: 8, buffer: nonce }, index)
|
|
83
|
+
|
|
84
|
+
nonce.set(padding, 8)
|
|
85
|
+
|
|
86
|
+
// Decrypt the block using the blinded fork ID.
|
|
87
|
+
sodium.crypto_stream_xor(
|
|
88
|
+
block,
|
|
89
|
+
block,
|
|
90
|
+
nonce,
|
|
91
|
+
blockKey
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
encrypt (index, block, fork, core) {
|
|
96
|
+
if (core.compat !== this.compat) this._reload(core)
|
|
97
|
+
return DefaultEncryption.encrypt(index, block, fork, this.blockKey, this.blindingKey)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
decrypt (index, block, core) {
|
|
101
|
+
if (core.compat !== this.compat) this._reload(core)
|
|
102
|
+
return DefaultEncryption.decrypt(index, block, this.blockKey)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
padding () {
|
|
106
|
+
return DefaultEncryption.PADDING
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
_reload (core) {
|
|
110
|
+
const block = b4a.equals(this.key, this.blockKey)
|
|
111
|
+
const keys = DefaultEncryption.deriveKeys(this.key, core.key, { block, compat: core.compat })
|
|
112
|
+
|
|
113
|
+
this.blockKey = keys.blockKey
|
|
114
|
+
this.blindingKey = keys.blindingKey
|
|
115
|
+
}
|
|
116
|
+
}
|
package/lib/messages.js
CHANGED
|
@@ -9,6 +9,7 @@ const EMPTY = b4a.alloc(0)
|
|
|
9
9
|
const MANIFEST_PATCH = 0b00000001
|
|
10
10
|
const MANIFEST_PROLOGUE = 0b00000010
|
|
11
11
|
const MANIFEST_LINKED = 0b00000100
|
|
12
|
+
const MANIFEST_USER_DATA = 0b00001000
|
|
12
13
|
|
|
13
14
|
const hashes = {
|
|
14
15
|
preencode (state, m) {
|
|
@@ -141,7 +142,8 @@ const manifestv0 = {
|
|
|
141
142
|
hash: c.fixed32.decode(state),
|
|
142
143
|
length: 0
|
|
143
144
|
},
|
|
144
|
-
linked: null
|
|
145
|
+
linked: null,
|
|
146
|
+
userData: null
|
|
145
147
|
}
|
|
146
148
|
}
|
|
147
149
|
|
|
@@ -153,7 +155,8 @@ const manifestv0 = {
|
|
|
153
155
|
quorum: 1,
|
|
154
156
|
signers: [signer.decode(state)],
|
|
155
157
|
prologue: null,
|
|
156
|
-
linked: null
|
|
158
|
+
linked: null,
|
|
159
|
+
userData: null
|
|
157
160
|
}
|
|
158
161
|
}
|
|
159
162
|
|
|
@@ -166,7 +169,8 @@ const manifestv0 = {
|
|
|
166
169
|
quorum: c.uint.decode(state),
|
|
167
170
|
signers: signerArray.decode(state),
|
|
168
171
|
prologue: null,
|
|
169
|
-
linked: null
|
|
172
|
+
linked: null,
|
|
173
|
+
userData: null
|
|
170
174
|
}
|
|
171
175
|
}
|
|
172
176
|
}
|
|
@@ -176,6 +180,7 @@ const fixed32Array = c.array(c.fixed32)
|
|
|
176
180
|
const manifest = exports.manifest = {
|
|
177
181
|
preencode (state, m) {
|
|
178
182
|
state.end++ // version
|
|
183
|
+
|
|
179
184
|
if (m.version === 0) return manifestv0.preencode(state, m)
|
|
180
185
|
|
|
181
186
|
state.end++ // flags
|
|
@@ -183,34 +188,35 @@ const manifest = exports.manifest = {
|
|
|
183
188
|
|
|
184
189
|
c.uint.preencode(state, m.quorum)
|
|
185
190
|
signerArray.preencode(state, m.signers)
|
|
186
|
-
if (m.prologue) prologue.preencode(state, m.prologue)
|
|
187
191
|
|
|
188
|
-
if (m.
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
if (m.prologue) prologue.preencode(state, m.prologue)
|
|
193
|
+
if (m.linked) fixed32Array.preencode(state, m.linked)
|
|
194
|
+
if (m.userData) c.buffer.preencode(state, m.userData)
|
|
191
195
|
},
|
|
192
196
|
encode (state, m) {
|
|
193
197
|
c.uint.encode(state, m.version)
|
|
198
|
+
|
|
194
199
|
if (m.version === 0) return manifestv0.encode(state, m)
|
|
195
200
|
|
|
196
201
|
let flags = 0
|
|
197
202
|
if (m.allowPatch) flags |= MANIFEST_PATCH
|
|
198
203
|
if (m.prologue) flags |= MANIFEST_PROLOGUE
|
|
199
204
|
if (m.linked) flags |= MANIFEST_LINKED
|
|
205
|
+
if (m.userData) flags |= MANIFEST_USER_DATA
|
|
200
206
|
|
|
201
207
|
c.uint.encode(state, flags)
|
|
202
208
|
hashes.encode(state, m.hash)
|
|
203
209
|
|
|
204
210
|
c.uint.encode(state, m.quorum)
|
|
205
211
|
signerArray.encode(state, m.signers)
|
|
206
|
-
if (m.prologue) prologue.encode(state, m.prologue)
|
|
207
212
|
|
|
208
|
-
if (m.
|
|
209
|
-
|
|
210
|
-
|
|
213
|
+
if (m.prologue) prologue.encode(state, m.prologue)
|
|
214
|
+
if (m.linked) fixed32Array.encode(state, m.linked)
|
|
215
|
+
if (m.userData) c.buffer.encode(state, m.userData)
|
|
211
216
|
},
|
|
212
217
|
decode (state) {
|
|
213
218
|
const version = c.uint.decode(state)
|
|
219
|
+
|
|
214
220
|
if (version === 0) return manifestv0.decode(state)
|
|
215
221
|
if (version > 2) throw new Error('Unknown version: ' + version)
|
|
216
222
|
|
|
@@ -222,6 +228,7 @@ const manifest = exports.manifest = {
|
|
|
222
228
|
const hasPatch = (flags & MANIFEST_PATCH) !== 0
|
|
223
229
|
const hasPrologue = (flags & MANIFEST_PROLOGUE) !== 0
|
|
224
230
|
const hasLinked = (flags & MANIFEST_LINKED) !== 0
|
|
231
|
+
const hasUserData = (flags & MANIFEST_USER_DATA) !== 0
|
|
225
232
|
|
|
226
233
|
return {
|
|
227
234
|
version,
|
|
@@ -230,7 +237,8 @@ const manifest = exports.manifest = {
|
|
|
230
237
|
quorum,
|
|
231
238
|
signers,
|
|
232
239
|
prologue: hasPrologue ? prologue.decode(state) : null,
|
|
233
|
-
linked: hasLinked ? fixed32Array.decode(state) : null
|
|
240
|
+
linked: hasLinked ? fixed32Array.decode(state) : null,
|
|
241
|
+
userData: hasUserData ? c.buffer.decode(state) : null
|
|
234
242
|
}
|
|
235
243
|
}
|
|
236
244
|
}
|
|
@@ -936,7 +944,9 @@ oplog.header = {
|
|
|
936
944
|
namespace: DEFAULT_NAMESPACE,
|
|
937
945
|
publicKey: old.signer.publicKey
|
|
938
946
|
}],
|
|
939
|
-
prologue: null
|
|
947
|
+
prologue: null,
|
|
948
|
+
linked: null,
|
|
949
|
+
userData: null
|
|
940
950
|
},
|
|
941
951
|
keyPair: old.signer.secretKey ? old.signer : null,
|
|
942
952
|
userData: old.userData,
|
package/lib/verifier.js
CHANGED
|
@@ -183,7 +183,8 @@ module.exports = class Verifier {
|
|
|
183
183
|
publicKey
|
|
184
184
|
}],
|
|
185
185
|
prologue: null,
|
|
186
|
-
linked: null
|
|
186
|
+
linked: null,
|
|
187
|
+
userData: null
|
|
187
188
|
}
|
|
188
189
|
}
|
|
189
190
|
|
|
@@ -196,13 +197,14 @@ module.exports = class Verifier {
|
|
|
196
197
|
if (!inp) return null
|
|
197
198
|
|
|
198
199
|
const manifest = {
|
|
199
|
-
version: getManifestVersion(inp), //
|
|
200
|
+
version: getManifestVersion(inp), // defaults to v1
|
|
200
201
|
hash: 'blake2b',
|
|
201
202
|
allowPatch: !!inp.allowPatch,
|
|
202
203
|
quorum: defaultQuorum(inp),
|
|
203
204
|
signers: inp.signers ? inp.signers.map(parseSigner) : [],
|
|
204
205
|
prologue: null,
|
|
205
|
-
linked: null
|
|
206
|
+
linked: null,
|
|
207
|
+
userData: inp.userData || null
|
|
206
208
|
}
|
|
207
209
|
|
|
208
210
|
if (inp.hash && inp.hash !== 'blake2b') throw BAD_ARGUMENT('Only Blake2b hashes are supported')
|
|
@@ -216,8 +218,12 @@ module.exports = class Verifier {
|
|
|
216
218
|
manifest.prologue.hash = unslab(manifest.prologue.hash)
|
|
217
219
|
}
|
|
218
220
|
|
|
221
|
+
if (manifest.userData !== null && manifest.version < 2) {
|
|
222
|
+
throw BAD_ARGUMENT('Invalid field: userData')
|
|
223
|
+
}
|
|
224
|
+
|
|
219
225
|
if (inp.linked && inp.linked.length) {
|
|
220
|
-
if (manifest.version < 2) throw BAD_ARGUMENT('Invalid field')
|
|
226
|
+
if (manifest.version < 2) throw BAD_ARGUMENT('Invalid field: linked')
|
|
221
227
|
|
|
222
228
|
for (const key of inp.linked) {
|
|
223
229
|
if (!(b4a.isBuffer(key) && key.byteLength === 32)) {
|
|
@@ -328,5 +334,6 @@ function proofToVersion1 (proof) {
|
|
|
328
334
|
function getManifestVersion (inp) {
|
|
329
335
|
if (typeof inp.version === 'number') return inp.version
|
|
330
336
|
if (inp.linked && inp.linked.length) return 2
|
|
337
|
+
if (inp.userData !== null) return 2
|
|
331
338
|
return 1
|
|
332
339
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hypercore",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.4.0",
|
|
4
4
|
"description": "Hypercore is a secure, distributed append-only log",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -50,7 +50,6 @@
|
|
|
50
50
|
"fast-fifo": "^1.3.0",
|
|
51
51
|
"flat-tree": "^1.9.0",
|
|
52
52
|
"hypercore-crypto": "^3.2.1",
|
|
53
|
-
"hypercore-encryption": "^2.0.0",
|
|
54
53
|
"hypercore-errors": "^1.2.0",
|
|
55
54
|
"hypercore-id-encoding": "^1.2.0",
|
|
56
55
|
"hypercore-storage": "^1.0.0",
|