hypercore 11.0.0 → 11.0.2

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/index.js CHANGED
@@ -207,7 +207,7 @@ class Hypercore extends EventEmitter {
207
207
  }
208
208
 
209
209
  const wait = opts.wait === false ? false : this.wait
210
- const writable = opts.writable === false ? false : !this._readonly
210
+ const writable = opts.writable === undefined ? !this._readonly : opts.writable === true
211
211
  const onwait = opts.onwait === undefined ? this.onwait : opts.onwait
212
212
  const timeout = opts.timeout === undefined ? this.timeout : opts.timeout
213
213
  const weak = opts.weak === undefined ? this.weak : opts.weak
@@ -245,7 +245,6 @@ class Hypercore extends EventEmitter {
245
245
 
246
246
  _setupSession (parent) {
247
247
  if (!this.keyPair) this.keyPair = parent.keyPair
248
- this.writable = this._isWritable()
249
248
 
250
249
  const s = parent.state
251
250
 
@@ -341,13 +340,13 @@ class Hypercore extends EventEmitter {
341
340
  }
342
341
 
343
342
  const parent = opts.parent || this.core
343
+ const checkout = opts.checkout === undefined ? -1 : opts.checkout
344
344
 
345
345
  if (opts.atom) {
346
- this.state = await parent.state.createSession(null, -1, false, opts.atom)
346
+ this.state = await parent.state.createSession(null, checkout, false, opts.atom)
347
347
  } else if (opts.name) {
348
348
  // todo: need to make named sessions safe before ready
349
349
  // atm we always copy the state in passCapabilities
350
- const checkout = opts.checkout === undefined ? -1 : opts.checkout
351
350
  const state = this.state
352
351
 
353
352
  this.state = await parent.state.createSession(opts.name, checkout, !!opts.overwrite, null)
@@ -360,6 +359,8 @@ class Hypercore extends EventEmitter {
360
359
  this.state = this.core.state.ref()
361
360
  }
362
361
 
362
+ this.writable = this._isWritable()
363
+
363
364
  if (this.snapshotted && this.core) this._updateSnapshot()
364
365
 
365
366
  this.state.addSession(this)
@@ -404,8 +405,9 @@ class Hypercore extends EventEmitter {
404
405
  }
405
406
 
406
407
  _isWritable () {
407
- if (this.draft) return true
408
- return !this._readonly && !!(this.keyPair && this.keyPair.secretKey)
408
+ if (this._readonly) return false
409
+ if (this.state && !this.state.isDefault()) return true
410
+ return !!(this.keyPair && this.keyPair.secretKey)
409
411
  }
410
412
 
411
413
  close ({ error } = {}) {
@@ -126,7 +126,7 @@ async function flushBatch (prologue, src, dst, batch) {
126
126
  }
127
127
 
128
128
  for (const { key, value } of userData) {
129
- tx.setUserData(key, value)
129
+ tx.putUserData(key, value)
130
130
  }
131
131
 
132
132
  let upgraded = batch.first && !head
package/lib/core.js CHANGED
@@ -8,7 +8,7 @@ const BlockStore = require('./block-store')
8
8
  const BitInterlude = require('./bit-interlude')
9
9
  const Bitfield = require('./bitfield')
10
10
  const RemoteBitfield = require('./remote-bitfield')
11
- const { BAD_ARGUMENT, STORAGE_EMPTY, STORAGE_CONFLICT, INVALID_OPERATION, INVALID_SIGNATURE, INVALID_CHECKSUM } = require('hypercore-errors')
11
+ const { BAD_ARGUMENT, STORAGE_EMPTY, STORAGE_CONFLICT, INVALID_SIGNATURE, INVALID_CHECKSUM } = require('hypercore-errors')
12
12
  const Verifier = require('./verifier')
13
13
  const audit = require('./audit')
14
14
  const copyPrologue = require('./copy-prologue')
@@ -189,7 +189,8 @@ module.exports = class Core {
189
189
  manifest,
190
190
  keyPair,
191
191
  discoveryKey,
192
- userData: opts.userData || []
192
+ userData: opts.userData || [],
193
+ alias: opts.alias || null
193
194
  })
194
195
  }
195
196
 
@@ -373,21 +374,23 @@ module.exports = class Core {
373
374
 
374
375
  async _validateCommit (state, treeLength) {
375
376
  if (this.state.length > state.length) {
376
- throw new Error('Invalid commit: partial commit') // TODO: partial commit in the future if possible
377
+ return false // TODO: partial commit in the future if possible
377
378
  }
378
379
 
379
380
  if (this.state.length > treeLength) {
380
381
  for (const root of this.state.roots) {
381
382
  const batchRoot = await state.tree.get(root.index)
382
383
  if (batchRoot.size !== root.size || !b4a.equals(batchRoot.hash, root.hash)) {
383
- throw new Error('Invalid commit: tree conflict')
384
+ return false
384
385
  }
385
386
  }
386
387
  }
387
388
 
388
389
  if (this.verifier === null) {
389
- throw INVALID_OPERATION('Cannot commit without manifest') // easier to assert than upsert
390
+ return false // easier to assert than upsert
390
391
  }
392
+
393
+ return true
391
394
  }
392
395
 
393
396
  _verifyBatchUpgrade (batch, manifest) {
package/lib/multisig.js CHANGED
@@ -21,7 +21,7 @@ function inflate (data) {
21
21
  }
22
22
 
23
23
  async function partialSignature (core, signer, from, to = core.state.length, signature = core.state.signature) {
24
- if (from > core.tree.length) return null
24
+ if (from > core.state.length) return null
25
25
  const nodes = to <= from ? null : await upgradeNodes(core, from, to)
26
26
 
27
27
  if (signature.byteLength !== 64) signature = c.decode(multiSignature, signature).proofs[0].signature
@@ -35,10 +35,10 @@ async function partialSignature (core, signer, from, to = core.state.length, sig
35
35
  }
36
36
 
37
37
  async function upgradeNodes (core, from, to) {
38
- const batch = core.storage.read()
38
+ const rx = core.state.storage.read()
39
39
  const treeBatch = core.state.createTreeBatch()
40
- const p = await core.tree.proof(batch, treeBatch, { upgrade: { start: from, length: to - from } })
41
- batch.tryFlush()
40
+ const p = await core.state.tree.proof(rx, treeBatch, { upgrade: { start: from, length: to - from } })
41
+ rx.tryFlush()
42
42
  return (await p.settle()).upgrade.nodes
43
43
  }
44
44
 
@@ -35,6 +35,7 @@ module.exports = class SessionState {
35
35
  const deps = this.storage.dependencies
36
36
  this.dependencyLength = deps.length ? deps[deps.length - 1].length : Infinity
37
37
 
38
+ if (treeInfo.length < this.dependencyLength) this.dependencyLength = treeInfo.length
38
39
  if (treeInfo.roots.length) this.setRoots(treeInfo.roots)
39
40
 
40
41
  this.snapshotCompatLength = this.isSnapshot() ? this.length : -1
@@ -109,7 +110,8 @@ module.exports = class SessionState {
109
110
  fork: this.fork,
110
111
  roots: this.roots.slice(),
111
112
  length: this.length,
112
- prologue: this.prologue
113
+ prologue: this.prologue,
114
+ signature: this.signature
113
115
  }
114
116
  }
115
117
 
@@ -144,11 +146,11 @@ module.exports = class SessionState {
144
146
  return s
145
147
  }
146
148
 
147
- updateDependency (storage, length) {
149
+ updateDependency (tx, length) {
148
150
  const dependency = updateDependency(this, length)
149
151
  if (dependency) {
150
152
  this.dependencyLength = dependency.length
151
- storage.setDependency(dependency)
153
+ tx.setDependency(dependency)
152
154
  }
153
155
 
154
156
  return dependency
@@ -202,6 +204,8 @@ module.exports = class SessionState {
202
204
  }
203
205
 
204
206
  async _oncommit (src, bitfield) {
207
+ const currLength = this.length
208
+
205
209
  this.fork = src.fork
206
210
  this.length = src.length
207
211
  this.roots = src.roots.slice()
@@ -229,11 +233,16 @@ module.exports = class SessionState {
229
233
  this._moveToCore(src.core)
230
234
  }
231
235
 
232
- if (!bitfield || !bitfield.drop) {
233
- this.onappend(tree, bitfield, true)
234
- } else {
235
- this.ontruncate(tree, bitfield.start, bitfield.start + bitfield.length, true)
236
+ const truncated = (bitfield && bitfield.truncated !== -1)
237
+ ? bitfield.truncated
238
+ : src.dependencyLength
239
+
240
+ if (truncated < currLength) {
241
+ this.ontruncate(tree, truncated, currLength, true)
242
+ if (!bitfield || bitfield.length === 0) return
236
243
  }
244
+
245
+ this.onappend(tree, bitfield, true)
237
246
  }
238
247
 
239
248
  flushed () {
@@ -511,22 +520,40 @@ module.exports = class SessionState {
511
520
  }
512
521
 
513
522
  _updateBitfield (bitfield, flushed) {
523
+ if (!bitfield) return
524
+
514
525
  const p = this._pendingBitfield
526
+ const b = bitfield
515
527
 
516
- if (p === null) {
517
- if (bitfield) this._pendingBitfield = bitfield
528
+ if (b.drop) {
529
+ if (p === null) {
530
+ this._pendingBitfield = { truncated: b.start, start: b.start, length: 0, drop: false }
531
+ return
532
+ }
533
+
534
+ if (p.drop) {
535
+ if (p.truncated !== b.start + b.length) throw INVALID_OPERATION('Atomic truncations must be contiguous')
536
+ p.truncated = b.start
537
+ return
538
+ }
539
+
540
+ if (b.start < p.start) throw INVALID_OPERATION('Atomic truncations must be contiguous')
541
+ p.length = b.start - p.start
542
+
543
+ if (p.length === 0) this._pendingBitfield = null
518
544
  return
519
545
  }
520
546
 
521
- if (p.drop) {
522
- const from = bitfield.start + bitfield.length
523
- if (!bitfield.drop || p.start !== from) throw INVALID_OPERATION('Atomic truncations must be contiguous')
547
+ if (p === null) {
548
+ this._pendingBitfield = { truncated: -1, start: b.start, length: b.length, drop: false }
549
+ return
550
+ }
524
551
 
525
- p.length += bitfield.length
526
- p.start = bitfield.start
527
- } else {
528
- p.length = bitfield.start + bitfield.length - p.start
552
+ if (b.start !== p.start + p.length) {
553
+ throw INVALID_OPERATION('Atomic operations must be contiguous')
529
554
  }
555
+
556
+ p.length += b.length
530
557
  }
531
558
 
532
559
  async _overwrite (source, fork, length, treeLength, signature, isDependent, shallow) {
@@ -670,7 +697,7 @@ module.exports = class SessionState {
670
697
  await state.mutex.lock()
671
698
  srcLocked = true
672
699
 
673
- await this.core._validateCommit(state, treeLength)
700
+ if (!(await this.core._validateCommit(state, treeLength))) return null
674
701
 
675
702
  if (this.length < length && !signature) {
676
703
  if (!keyPair) keyPair = this.core.header.keyPair
@@ -729,6 +756,8 @@ module.exports = class SessionState {
729
756
  head.fork = this.fork
730
757
  head.rootHash = rootHash
731
758
 
759
+ if (length === this.length) head.signature = this.signature
760
+
732
761
  return head
733
762
  }
734
763
 
@@ -739,6 +768,10 @@ module.exports = class SessionState {
739
768
  this.core = core
740
769
  this.index = this.core.sessionStates.push(this) - 1
741
770
 
771
+ // storage was updated
772
+ const deps = this.storage.dependencies
773
+ this.dependencyLength = deps[deps.length - 1].length
774
+
742
775
  for (let i = this.sessions.length - 1; i >= 0; i--) this.sessions[i].transferSession(this.core)
743
776
  }
744
777
 
@@ -831,7 +864,8 @@ module.exports = class SessionState {
831
864
  fork: this.fork,
832
865
  roots: length === this.length ? this.roots.slice() : await tree.getRoots(length),
833
866
  length,
834
- prologue: this.prologue
867
+ prologue: this.prologue,
868
+ signature: length === this.length ? this.signature : null
835
869
  }
836
870
 
837
871
  const state = new SessionState(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore",
3
- "version": "11.0.0",
3
+ "version": "11.0.2",
4
4
  "description": "Hypercore is a secure, distributed append-only log",
5
5
  "main": "index.js",
6
6
  "scripts": {