hypercore 10.32.7 → 10.33.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/lib/caps.js CHANGED
@@ -25,11 +25,11 @@ exports.replicate = function (isInitiator, key, handshakeHash) {
25
25
  return out
26
26
  }
27
27
 
28
- exports.treeSignable = function (namespace, hash, length, fork) {
28
+ exports.treeSignable = function (manifestHash, treeHash, length, fork) {
29
29
  const state = { start: 0, end: 112, buffer: b4a.allocUnsafe(112) }
30
- c.raw.encode(state, TREE)
31
- c.raw.encode(state, namespace)
32
- c.raw.encode(state, hash)
30
+ c.fixed32.encode(state, TREE)
31
+ c.fixed32.encode(state, manifestHash)
32
+ c.fixed32.encode(state, treeHash)
33
33
  c.uint64.encode(state, length)
34
34
  c.uint64.encode(state, fork)
35
35
  return state.buffer
@@ -38,8 +38,8 @@ exports.treeSignable = function (namespace, hash, length, fork) {
38
38
  exports.treeSignableCompat = function (hash, length, fork, noHeader) {
39
39
  const end = noHeader ? 48 : 80
40
40
  const state = { start: 0, end, buffer: b4a.allocUnsafe(end) }
41
- if (!noHeader) c.raw.encode(state, TREE) // ultra legacy mode, kill in future major
42
- c.raw.encode(state, hash)
41
+ if (!noHeader) c.fixed32.encode(state, TREE) // ultra legacy mode, kill in future major
42
+ c.fixed32.encode(state, hash)
43
43
  c.uint64.encode(state, length)
44
44
  c.uint64.encode(state, fork)
45
45
  return state.buffer
package/lib/core.js CHANGED
@@ -158,7 +158,7 @@ module.exports = class Core {
158
158
  while (bitfield.get(header.hints.contiguousLength)) header.hints.contiguousLength++
159
159
  }
160
160
 
161
- const verifier = header.manifest ? new Verifier(header.manifest, { compat: Verifier.isCompat(header.key, header.manifest), crypto, legacy }) : null
161
+ const verifier = header.manifest ? new Verifier(header.key, header.manifest, { crypto, legacy }) : null
162
162
 
163
163
  for (const e of entries) {
164
164
  if (e.userData) {
@@ -197,13 +197,12 @@ module.exports = class Core {
197
197
  if (!manifest && b4a.equals(keyPair.publicKey, this.header.key)) manifest = Verifier.defaultSignerManifest(this.header.key)
198
198
  if (!manifest) return
199
199
 
200
- const compat = Verifier.isCompat(this.header.key, manifest)
201
- const verifier = new Verifier(manifest, { compat, crypto: this.crypto, legacy: this._legacy })
200
+ const verifier = new Verifier(this.header.key, manifest, { crypto: this.crypto, legacy: this._legacy })
202
201
 
203
202
  if (verifier.prologue) this.tree.setPrologue(verifier.prologue)
204
203
 
205
- this.compat = compat
206
204
  this.header.manifest = manifest
205
+ this.compat = verifier.compat
207
206
  this.verifier = verifier
208
207
  this._manifestFlushed = false
209
208
 
@@ -681,15 +680,15 @@ module.exports = class Core {
681
680
  }
682
681
  }
683
682
 
684
- const verifier = this.verifier || new Verifier(manifest, { compat: Verifier.isCompat(this.header.key, manifest), crypto: this.crypto, legacy: this._legacy })
683
+ const verifier = this.verifier || new Verifier(this.header.key, manifest, { crypto: this.crypto, legacy: this._legacy })
685
684
 
686
685
  if (!verifier.verify(batch, batch.signature)) {
687
686
  throw INVALID_SIGNATURE('Proof contains an invalid signature')
688
687
  }
689
688
 
690
689
  if (!this.header.manifest) {
691
- this.compat = Verifier.isCompat(this.header.key, manifest)
692
690
  this.header.manifest = manifest
691
+ this.compat = verifier.compat
693
692
  this.verifier = verifier
694
693
  this.onupdate(0b10000, null, null, null)
695
694
  }
@@ -79,8 +79,8 @@ class MerkleTreeBatch {
79
79
  return this.hashCached
80
80
  }
81
81
 
82
- signable (namespace) {
83
- return caps.treeSignable(namespace, this.hash(), this.length, this.fork)
82
+ signable (manifestHash) {
83
+ return caps.treeSignable(manifestHash, this.hash(), this.length, this.fork)
84
84
  }
85
85
 
86
86
  signableCompat (noHeader) {
package/lib/verifier.js CHANGED
@@ -9,29 +9,35 @@ const multisig = require('./multisig')
9
9
  const caps = require('./caps')
10
10
 
11
11
  class Signer {
12
- constructor (crypto, index, { signature = 'ed25519', publicKey, namespace = caps.DEFAULT_NAMESPACE } = {}) {
12
+ constructor (crypto, manifestHash, version, index, { signature = 'ed25519', publicKey, namespace = caps.DEFAULT_NAMESPACE } = {}) {
13
13
  if (!publicKey) throw BAD_ARGUMENT('public key is required for a signer')
14
14
  if (signature !== 'ed25519') throw BAD_ARGUMENT('Only Ed25519 signatures are supported')
15
15
 
16
16
  this.crypto = crypto
17
+ this.manifestHash = manifestHash
18
+ this.version = version
17
19
  this.signer = index
18
20
  this.signature = signature
19
21
  this.publicKey = publicKey
20
22
  this.namespace = namespace
21
23
  }
22
24
 
25
+ _ctx () {
26
+ return this.version === 0 ? this.namespace : this.manifestHash
27
+ }
28
+
23
29
  verify (batch, signature) {
24
- return this.crypto.verify(batch.signable(this.namespace), signature, this.publicKey)
30
+ return this.crypto.verify(batch.signable(this._ctx()), signature, this.publicKey)
25
31
  }
26
32
 
27
33
  sign (batch, keyPair) {
28
- return this.crypto.sign(batch.signable(this.namespace), keyPair.secretKey)
34
+ return this.crypto.sign(batch.signable(this._ctx()), keyPair.secretKey)
29
35
  }
30
36
  }
31
37
 
32
38
  class CompatSigner extends Signer {
33
39
  constructor (crypto, index, signer, legacy) {
34
- super(crypto, index, signer)
40
+ super(crypto, null, 0, index, signer)
35
41
  this.legacy = legacy
36
42
  }
37
43
 
@@ -45,16 +51,24 @@ class CompatSigner extends Signer {
45
51
  }
46
52
 
47
53
  module.exports = class Verifier {
48
- constructor (manifest, { compat = false, crypto = defaultCrypto, legacy = false } = {}) {
54
+ constructor (manifestHash, manifest, { compat = isCompat(manifestHash, manifest), crypto = defaultCrypto, legacy = false } = {}) {
55
+ const self = this
56
+
57
+ this.manifestHash = manifestHash
49
58
  this.compat = compat || manifest === null
50
59
  this.version = this.compat ? 0 : typeof manifest.version === 'number' ? manifest.version : 1
51
60
  this.hash = manifest.hash || 'blake2b'
52
61
  this.allowPatch = !this.compat && !!manifest.allowPatch
53
62
  this.quorum = this.compat ? 1 : defaultQuorum(manifest)
54
- this.signers = manifest.signers
55
- ? manifest.signers.map((s, index) => this.compat ? new CompatSigner(crypto, index, s, legacy) : new Signer(crypto, index, s))
56
- : []
63
+
64
+ this.signers = manifest.signers ? manifest.signers.map(createSigner) : []
57
65
  this.prologue = this.compat ? null : (manifest.prologue || null)
66
+
67
+ function createSigner (signer, index) {
68
+ return self.compat
69
+ ? new CompatSigner(crypto, index, signer, legacy)
70
+ : new Signer(crypto, manifestHash, self.version, index, signer)
71
+ }
58
72
  }
59
73
 
60
74
  _verifyCompat (batch, signature) {
@@ -129,21 +143,22 @@ module.exports = class Verifier {
129
143
  // TODO: better api for this that is more ... multisig-ey
130
144
  sign (batch, keyPair) {
131
145
  if (!keyPair || !keyPair.secretKey) throw BAD_ARGUMENT('No key pair was passed')
132
- if (this.signers.length > 1 || this.allowPatch) throw BAD_ARGUMENT('Can only sign directly for single signers')
133
146
 
134
- const signature = this.signers[0].sign(batch, keyPair)
135
- if (this.version !== 1) return signature
136
- return this.assemble([{ signer: 0, signature, patch: 0, nodes: null }])
147
+ for (const s of this.signers) {
148
+ if (b4a.equals(s.publicKey, keyPair.publicKey)) {
149
+ const signature = s.sign(batch, keyPair)
150
+ if (this.signers.length !== 1 || this.version === 0) return signature
151
+ return this.assemble([{ signer: 0, signature, patch: 0, nodes: null }])
152
+ }
153
+ }
154
+
155
+ throw new BAD_ARGUMENT('Public key is not a declared signer')
137
156
  }
138
157
 
139
158
  assemble (inputs) {
140
159
  return this.version === 0 ? multisig.assemblev0(inputs) : multisig.assemble(inputs)
141
160
  }
142
161
 
143
- manifestHash () {
144
- return manifestHash(this)
145
- }
146
-
147
162
  static manifestHash (manifest) {
148
163
  return manifestHash(manifest)
149
164
  }
@@ -163,6 +178,11 @@ module.exports = class Verifier {
163
178
  }
164
179
  }
165
180
 
181
+ static fromManifest (manifest, opts) {
182
+ const m = this.createManifest(manifest)
183
+ return new this(manifestHash(m), m, opts)
184
+ }
185
+
166
186
  static createManifest (inp) {
167
187
  if (!inp) return null
168
188
 
@@ -192,12 +212,11 @@ module.exports = class Verifier {
192
212
  }
193
213
 
194
214
  static isCompat (key, manifest) {
195
- return !!(manifest && manifest.signers.length === 1 && b4a.equals(key, manifest.signers[0].publicKey))
215
+ return isCompat(key, manifest)
196
216
  }
197
217
 
198
218
  static sign (manifest, batch, keyPair, opts) {
199
- const v = new Verifier(manifest, opts)
200
- return v.sign(batch, keyPair)
219
+ return Verifier.fromManifest(manifest, opts).sign(batch, keyPair)
201
220
  }
202
221
  }
203
222
 
@@ -207,6 +226,10 @@ function toMap (nodes) {
207
226
  return m
208
227
  }
209
228
 
229
+ function isCompat (key, manifest) {
230
+ return !!(manifest && manifest.signers.length === 1 && b4a.equals(key, manifest.signers[0].publicKey))
231
+ }
232
+
210
233
  function defaultQuorum (man) {
211
234
  if (typeof man.quorum === 'number') return man.quorum
212
235
  if (!man.signers || !man.signers.length) return 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore",
3
- "version": "10.32.7",
3
+ "version": "10.33.0",
4
4
  "description": "Hypercore is a secure, distributed append-only log",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -34,7 +34,7 @@
34
34
  "messages.js",
35
35
  "lib/**.js"
36
36
  ],
37
- "import": {
37
+ "imports": {
38
38
  "events": {
39
39
  "bare": "bare-events",
40
40
  "default": "events"