autobee 2.0.0-rc.25 → 2.0.0-rc.27

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
@@ -14,6 +14,7 @@ const asserts = require('./lib/asserts.js')
14
14
  const boot = require('./lib/boot.js')
15
15
  const { resolveWeight, currentWeight } = require('./lib/witness.js')
16
16
  const encoding = require('./lib/encoding.js')
17
+ const { LEGACY_OPLOG_VERSION } = require('./lib/constants.js')
17
18
  const FastForward = require('./lib/fast-forward.js')
18
19
  const System = require('./lib/system.js')
19
20
  const ApplyCalls = require('./lib/apply-calls.js')
@@ -176,6 +177,7 @@ module.exports = class Autobee extends ReadyResource {
176
177
  this._bootingAll.catch(safetyCatch)
177
178
 
178
179
  await this.bee.ready()
180
+ await this._workingBee.ready()
179
181
  await this._bootingState
180
182
 
181
183
  this._localSystemStart = this.system.bee.context.local.length
@@ -527,12 +529,12 @@ module.exports = class Autobee extends ReadyResource {
527
529
  this.stats.drains++
528
530
 
529
531
  if (this.bootFrom) {
530
- const { head = null, legacy = null, bootCondition = null } = this.bootFrom
532
+ const { head = null, legacy = null, bootCondition = null, wait = false } = this.bootFrom
531
533
 
532
534
  this.bootFrom = null
533
535
 
534
536
  if (legacy) await this._bootFromSystem(legacy)
535
- else if (head) await this._bootFromHead(head, bootCondition)
537
+ else if (head) await this._bootFromHead(head, bootCondition, wait)
536
538
  }
537
539
 
538
540
  this._ackRequired = false
@@ -1041,12 +1043,7 @@ module.exports = class Autobee extends ReadyResource {
1041
1043
 
1042
1044
  this.writers.attest(witnessed)
1043
1045
 
1044
- for (const { key, added, isAnchor } of changed) {
1045
- if (isAnchor) {
1046
- // no Writer/ActiveWriters tracking, but still wake anything linked to it
1047
- this.writers.triggers.trigger(b4a.toString(key, 'hex'), 1)
1048
- continue
1049
- }
1046
+ for (const { key, added } of changed) {
1050
1047
  if (added) await this.writers.add(key)
1051
1048
  else await this.writers.remove(key)
1052
1049
  }
@@ -1195,9 +1192,9 @@ module.exports = class Autobee extends ReadyResource {
1195
1192
 
1196
1193
  // the boot head seeds the view every trust decision here is made against,
1197
1194
  // since our own view is still empty
1198
- async _bootFromHead(head, bootCondition) {
1195
+ async _bootFromHead(head, bootCondition, wait = false) {
1199
1196
  // just a head: one attempt, we do not wait around if it cannot be read
1200
- if (bootCondition === null) {
1197
+ if (bootCondition === null && !wait) {
1201
1198
  try {
1202
1199
  const ff = await FastForward.fromHead(this, head, null, {
1203
1200
  force: true,
@@ -1211,8 +1208,8 @@ module.exports = class Autobee extends ReadyResource {
1211
1208
  }
1212
1209
  }
1213
1210
 
1214
- // a condition needs the view at head to check against, so park until we
1215
- // can read it and something acceptable turns up
1211
+ // park until the head can be read and, if a condition is set, something
1212
+ // acceptable turns up
1216
1213
  let opened = null
1217
1214
 
1218
1215
  try {
@@ -1220,10 +1217,28 @@ module.exports = class Autobee extends ReadyResource {
1220
1217
  this._bootWait = rrp()
1221
1218
 
1222
1219
  try {
1223
- if (opened === null) opened = await this._bootReference(head)
1224
-
1225
- if (opened !== null && (await this._bootAttempt(head, bootCondition, opened.view))) {
1226
- return true
1220
+ if (bootCondition === null) {
1221
+ const ff = await FastForward.fromHead(this, head, null, {
1222
+ force: true,
1223
+ timeout: FastForward.DEFAULT_TIMEOUT
1224
+ })
1225
+
1226
+ if (ff !== null && (await this._runFastForward(ff))) return true
1227
+ } else {
1228
+ if (opened === null) opened = await this._bootReference(head)
1229
+
1230
+ if (opened !== null) {
1231
+ if (await this._bootAttempt(head, bootCondition, opened.view)) {
1232
+ return true
1233
+ }
1234
+
1235
+ // the reference may be stale - resolve it afresh next attempt
1236
+ await opened.close()
1237
+ opened = null
1238
+ } else if (await this._bootLegacyHead(head)) {
1239
+ // boot legacy head through the migration pathway
1240
+ return true
1241
+ }
1227
1242
  }
1228
1243
  } catch (err) {
1229
1244
  safetyCatch(err)
@@ -1258,6 +1273,20 @@ module.exports = class Autobee extends ReadyResource {
1258
1273
  return ff !== null && (await this._runFastForward(ff))
1259
1274
  }
1260
1275
 
1276
+ async _bootLegacyHead(head) {
1277
+ const oplog = await FastForward.flushHead(this, head, {
1278
+ timeout: FastForward.DEFAULT_TIMEOUT
1279
+ })
1280
+ if (oplog === null || oplog.op.version > LEGACY_OPLOG_VERSION) return false
1281
+
1282
+ const ff = await FastForward.fromHead(this, head, null, {
1283
+ force: true,
1284
+ timeout: FastForward.DEFAULT_TIMEOUT
1285
+ })
1286
+
1287
+ return ff !== null && (await this._runFastForward(ff))
1288
+ }
1289
+
1261
1290
  async _bootReference(head) {
1262
1291
  const oplog = await FastForward.flushHead(this, head, {
1263
1292
  timeout: FastForward.DEFAULT_TIMEOUT
package/lib/system.js CHANGED
@@ -85,8 +85,8 @@ module.exports = class Systembee {
85
85
  this.update(key, length, -1, 0, false, false, true, false, false, -1, false)
86
86
  }
87
87
 
88
- addAnchor(key, { length = 1 } = {}) {
89
- this.update(key, length, -1, -1, false, true, false, false, true, -1, false)
88
+ addAnchor(key) {
89
+ this.update(key, 0, -1, -1, false, true, false, false, true, -1, false)
90
90
  }
91
91
 
92
92
  isGenesis() {
package/lib/topo.js CHANGED
@@ -1,7 +1,8 @@
1
1
  const b4a = require('b4a')
2
2
  const encoding = require('./encoding.js')
3
- const { createNode } = require('./writers.js')
3
+ const { createNode, finalizeNodeBatch } = require('./writers.js')
4
4
  const asserts = require('./asserts.js')
5
+ const { LEGACY_OPLOG_VERSION } = require('./constants.js')
5
6
 
6
7
  const EMPTY_HEAD = { length: 0, key: null }
7
8
  const INFO_LEGACY_KEY = b4a.concat([b4a.from([0, 0]), b4a.from('info')])
@@ -275,8 +276,20 @@ async function getOplogBatch(undo, core, length, weight, index, opts = null) {
275
276
  const seq = length - 1
276
277
  const block = await core.get(seq, opts)
277
278
  if (block === null) return null
279
+
278
280
  const oplog = encoding.decodeOplog(block)
279
281
  const head = createNode(core, length, weight, oplog)
282
+ const legacy = oplog.version <= LEGACY_OPLOG_VERSION
283
+
284
+ // if this is legacy the start pointer is always 0, fix
285
+ if (legacy) {
286
+ for (let i = length - 1; i > 0; i--) {
287
+ const block = await core.get(i - 1, opts)
288
+ const oplog = encoding.decodeOplog(block)
289
+ if (oplog.batch.end === 0) break
290
+ head.batch.start++
291
+ }
292
+ }
280
293
 
281
294
  const batch = []
282
295
  const result = { undo, batch, index }
@@ -304,6 +317,8 @@ async function getOplogBatch(undo, core, length, weight, index, opts = null) {
304
317
  }
305
318
 
306
319
  batch.push(head)
320
+ finalizeNodeBatch(batch)
321
+
307
322
  return result
308
323
  }
309
324
 
package/lib/writers.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const b4a = require('b4a')
2
2
  const encoding = require('./encoding.js')
3
3
  const Triggers = require('./triggers.js')
4
+ const { LEGACY_OPLOG_VERSION } = require('./constants.js')
4
5
  const { signAttestation, resolveWeight } = require('./witness.js')
5
6
  const { WriterEncryption } = require('autobee-encryption')
6
7
 
@@ -59,21 +60,23 @@ class ActiveWriters {
59
60
  let w = this.active.get(id)
60
61
 
61
62
  if (w === this.localWriter) return
63
+
64
+ let added = false
62
65
  if (!w) {
63
- // anchors are local-only and never replicated - nothing to fetch
64
- const info = await this.auto.system.get(key, { unflushed: true })
65
- if (info && info.isAnchor) return
66
66
  w = await this.add(key)
67
67
  if (!w) return
68
+ added = true
68
69
  }
69
70
 
71
+ const advanced = length > w.hintedLength
72
+
70
73
  // remember the announced length so gc doesn't drop a writer we haven't caught up on
71
74
  w.hint(length)
72
75
 
73
76
  // prefetch the oplog head for the fast-forward that runs right after us
74
77
  if (w && length > 0) w.core.get(length - 1).catch(noop)
75
78
 
76
- this.bump()
79
+ if (added || advanced) this.bump()
77
80
  }
78
81
 
79
82
  getLatestLocalOplog() {
@@ -448,7 +451,9 @@ class Writer {
448
451
  async update() {
449
452
  const info = await this.system.get(this.core.key)
450
453
 
451
- if (info && info.isAnchor && this !== this.writers.localWriter) {
454
+ // an anchor core is prologue-only, so once its single node has applied
455
+ // nothing more can ever come - retire the writer
456
+ if (info && info.isAnchor && info.length > 0 && this !== this.writers.localWriter) {
452
457
  await this.detachAndClose()
453
458
  return info.length
454
459
  }
@@ -567,7 +572,7 @@ class Writer {
567
572
  }
568
573
 
569
574
  batch.push(node)
570
- if (b.end === 0) return batch
575
+ if (b.end === 0) return finalizeNodeBatch(batch)
571
576
 
572
577
  // TODO: mark as dead
573
578
  if (batch.length >= BATCH_WRITER_SANITY) return null
@@ -758,6 +763,7 @@ function sortsBefore(a, b) {
758
763
  exports.ActiveWriters = ActiveWriters
759
764
  exports.Writer = Writer
760
765
  exports.createNode = createNode
766
+ exports.finalizeNodeBatch = finalizeNodeBatch
761
767
 
762
768
  function createNode(core, length, weight, oplog) {
763
769
  return {
@@ -779,4 +785,14 @@ function createNode(core, length, weight, oplog) {
779
785
  }
780
786
  }
781
787
 
788
+ function finalizeNodeBatch(batch) {
789
+ if (batch.length === 0 || batch[0].version > LEGACY_OPLOG_VERSION) return batch
790
+
791
+ for (let i = 0; i < batch.length; i++) {
792
+ batch[i].batch.start = i
793
+ }
794
+
795
+ return batch
796
+ }
797
+
782
798
  function noop() {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autobee",
3
- "version": "2.0.0-rc.25",
3
+ "version": "2.0.0-rc.27",
4
4
  "description": "Bee based autobase",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Holepunch Inc.",
@@ -43,6 +43,7 @@
43
43
  "lunte": "^1.6.0",
44
44
  "prettier": "^3.8.1",
45
45
  "prettier-config-holepunch": "^2.0.0",
46
- "protomux-wakeup": "^2.9.0"
46
+ "protomux-wakeup": "^2.9.0",
47
+ "replication-simulator": "^3.0.0"
47
48
  }
48
49
  }