autobee 2.0.0-rc.8 → 2.0.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 +48 -1
- package/encoding/compat.js +1 -1
- package/encoding/legacy.js +33 -8
- package/encoding/spec/autobee/index.js +312 -25
- package/encoding/spec/autobee/schema.json +228 -2
- package/index.js +555 -310
- package/lib/apply-calls.js +5 -6
- package/lib/apply-view.js +25 -0
- package/lib/boot.js +14 -182
- package/lib/constants.js +3 -6
- package/lib/encoding.js +72 -3
- package/lib/fast-forward.js +346 -0
- package/lib/migrations.js +457 -0
- package/lib/promotions.js +164 -0
- package/lib/system.js +97 -179
- package/lib/topo.js +110 -52
- package/lib/trusted.js +44 -0
- package/lib/updates.js +1 -38
- package/lib/witness.js +34 -65
- package/lib/writers.js +180 -116
- package/package.json +5 -4
- package/lib/reboot.js +0 -238
package/lib/writers.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const b4a = require('b4a')
|
|
2
2
|
const encoding = require('./encoding.js')
|
|
3
3
|
const Triggers = require('./triggers.js')
|
|
4
|
-
const {
|
|
4
|
+
const { LEGACY_OPLOG_VERSION } = require('./constants.js')
|
|
5
|
+
const { resolveWeight } = require('./witness.js')
|
|
5
6
|
const { WriterEncryption } = require('autobee-encryption')
|
|
6
7
|
|
|
7
8
|
const WRITER_PREFETCH = 10
|
|
@@ -17,17 +18,20 @@ class ActiveWriters {
|
|
|
17
18
|
|
|
18
19
|
this.auto = auto
|
|
19
20
|
this.active = new Map()
|
|
20
|
-
this._adding = new Map()
|
|
21
21
|
this.triggers = new Triggers()
|
|
22
|
-
this.localWriter =
|
|
22
|
+
this.localWriter = null
|
|
23
23
|
this.writable = false
|
|
24
24
|
this.pending = []
|
|
25
|
-
this.witnesses = []
|
|
26
|
-
this.attestations = []
|
|
27
25
|
|
|
26
|
+
this._pendingBuffer = new Map()
|
|
27
|
+
this._adding = new Map()
|
|
28
|
+
|
|
29
|
+
this.localWriter = new Writer(this, auto.system, true, local, b4a.toString(local.key, 'hex'))
|
|
28
30
|
this.localWriter.attach()
|
|
31
|
+
}
|
|
29
32
|
|
|
30
|
-
|
|
33
|
+
get size() {
|
|
34
|
+
return this.active.size
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
[Symbol.iterator]() {
|
|
@@ -57,24 +61,31 @@ class ActiveWriters {
|
|
|
57
61
|
let w = this.active.get(id)
|
|
58
62
|
|
|
59
63
|
if (w === this.localWriter) return
|
|
64
|
+
|
|
65
|
+
let added = false
|
|
60
66
|
if (!w) {
|
|
61
|
-
// anchors are local-only and never replicated - nothing to fetch
|
|
62
|
-
const info = await this.auto.system.get(key, { unflushed: true })
|
|
63
|
-
if (info && info.isAnchor) return
|
|
64
67
|
w = await this.add(key)
|
|
68
|
+
if (!w) return
|
|
69
|
+
added = true
|
|
65
70
|
}
|
|
66
71
|
|
|
67
|
-
|
|
72
|
+
const advanced = length > w.hintedLength
|
|
73
|
+
|
|
74
|
+
// remember the announced length so gc doesn't drop a writer we haven't caught up on
|
|
75
|
+
w.hint(length)
|
|
76
|
+
|
|
77
|
+
// prefetch the oplog head for the fast-forward that runs right after us
|
|
78
|
+
if (w && length > 0) w.core.get(length - 1).catch(noop)
|
|
68
79
|
|
|
69
|
-
this.bump()
|
|
80
|
+
if (added || advanced) this.bump()
|
|
70
81
|
}
|
|
71
82
|
|
|
72
83
|
getLatestLocalOplog() {
|
|
73
84
|
return this.localWriter.getLatest()
|
|
74
85
|
}
|
|
75
86
|
|
|
76
|
-
appendLocal(value, timestamp, batch, links, optimistic, witness) {
|
|
77
|
-
return this.localWriter.append(value, timestamp, batch, links, optimistic, witness)
|
|
87
|
+
appendLocal(value, timestamp, batch, links, optimistic, witness, approvals = null) {
|
|
88
|
+
return this.localWriter.append(value, timestamp, batch, links, optimistic, witness, approvals)
|
|
78
89
|
}
|
|
79
90
|
|
|
80
91
|
async rotateLocalWriter(core) {
|
|
@@ -85,9 +96,6 @@ class ActiveWriters {
|
|
|
85
96
|
this.localWriter.addPending()
|
|
86
97
|
this.auto.emit('writer', this.localWriter)
|
|
87
98
|
|
|
88
|
-
// old local key witnesses are useless
|
|
89
|
-
this.witnesses = []
|
|
90
|
-
|
|
91
99
|
await this.updateLocalState()
|
|
92
100
|
}
|
|
93
101
|
|
|
@@ -95,19 +103,21 @@ class ActiveWriters {
|
|
|
95
103
|
return this.localWriter.clear()
|
|
96
104
|
}
|
|
97
105
|
|
|
98
|
-
flushLocal(views) {
|
|
106
|
+
async flushLocal(views) {
|
|
99
107
|
const w = this.localWriter
|
|
100
108
|
|
|
101
109
|
// only consume the queue when a flush will actually write
|
|
102
|
-
if (w.pending === null || w.processed === 0) return
|
|
110
|
+
if (w.pending === null || w.processed === 0) return
|
|
103
111
|
|
|
104
|
-
const
|
|
105
|
-
this.attestations = []
|
|
112
|
+
const trusted = await this.auto.trusted.mostRecentTrusted(this.auto._workingView.view, null)
|
|
106
113
|
|
|
107
|
-
return w.flush(views,
|
|
114
|
+
return w.flush(views, trusted)
|
|
108
115
|
}
|
|
109
116
|
|
|
110
117
|
async refresh() {
|
|
118
|
+
// peeked batches were read against the pre-reboot system, drop them
|
|
119
|
+
this._pendingBuffer.clear()
|
|
120
|
+
|
|
111
121
|
if (this.localWriter && !this.localWriter.isClosed) {
|
|
112
122
|
await this.updateLocalState()
|
|
113
123
|
}
|
|
@@ -122,6 +132,37 @@ class ActiveWriters {
|
|
|
122
132
|
await this.localWriter.update()
|
|
123
133
|
}
|
|
124
134
|
|
|
135
|
+
async nextPendingNode({ local = false } = {}) {
|
|
136
|
+
for (const w of this.pending.slice()) {
|
|
137
|
+
if (local && w !== this.localWriter) continue
|
|
138
|
+
if (this._pendingBuffer.has(w) || w.isFrozen) continue
|
|
139
|
+
|
|
140
|
+
const batch = await w.next()
|
|
141
|
+
if (batch !== null) this._pendingBuffer.set(w, batch)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (this._pendingBuffer.size === 0) return null
|
|
145
|
+
|
|
146
|
+
let writer = null
|
|
147
|
+
let best = null
|
|
148
|
+
|
|
149
|
+
for (const [w, batch] of this._pendingBuffer) {
|
|
150
|
+
if (local && w !== this.localWriter) continue
|
|
151
|
+
const head = batch[0]
|
|
152
|
+
// -1 marks a node next() has not resolved a sort weight for yet
|
|
153
|
+
if (head.weight < 0) head.weight = await resolveWeight(this.auto, head)
|
|
154
|
+
if (best === null || sortsBefore(head, best[0])) {
|
|
155
|
+
writer = w
|
|
156
|
+
best = batch
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (writer === null) return null
|
|
161
|
+
|
|
162
|
+
this._pendingBuffer.delete(writer)
|
|
163
|
+
return { writer, batch: best }
|
|
164
|
+
}
|
|
165
|
+
|
|
125
166
|
_updateLocalState() {
|
|
126
167
|
const w = this.localWriter
|
|
127
168
|
|
|
@@ -157,10 +198,7 @@ class ActiveWriters {
|
|
|
157
198
|
if (local) await this.updateLocalState()
|
|
158
199
|
|
|
159
200
|
let w = this.active.get(id)
|
|
160
|
-
if (w)
|
|
161
|
-
w.couple() // couple if we weren't ready first time
|
|
162
|
-
return w
|
|
163
|
-
}
|
|
201
|
+
if (w) return w
|
|
164
202
|
|
|
165
203
|
// no new sessions once teardown started
|
|
166
204
|
if (this.auto._interrupting) return null
|
|
@@ -168,6 +206,7 @@ class ActiveWriters {
|
|
|
168
206
|
const encryption = this.auto.encryptionKey ? new WriterEncryption(this.auto) : null
|
|
169
207
|
|
|
170
208
|
const core = this.auto.store.get({
|
|
209
|
+
active: false,
|
|
171
210
|
key,
|
|
172
211
|
encryption,
|
|
173
212
|
group: local || !this.auto.wakeupCapability ? null : this.auto.wakeupCapability.discoveryKey
|
|
@@ -184,7 +223,6 @@ class ActiveWriters {
|
|
|
184
223
|
|
|
185
224
|
w = new Writer(this, this.auto.system, false, core, id)
|
|
186
225
|
w.attach()
|
|
187
|
-
w.couple()
|
|
188
226
|
|
|
189
227
|
return w
|
|
190
228
|
}
|
|
@@ -196,42 +234,22 @@ class ActiveWriters {
|
|
|
196
234
|
const w = this.active.get(id)
|
|
197
235
|
if (!w) return
|
|
198
236
|
|
|
237
|
+
// nodes this writer appended before the removal may still sort before it,
|
|
238
|
+
// and their ordering advances its record everywhere - closing the session
|
|
239
|
+
// while we are behind strands us one node short forever. reset() closes it
|
|
240
|
+
// once we have caught up
|
|
241
|
+
if (w !== this.localWriter) {
|
|
242
|
+
const length = await w.update()
|
|
243
|
+
if (length < w.core.length || length < w.hintedLength) {
|
|
244
|
+
w.addPending()
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
199
249
|
w.detach()
|
|
200
250
|
w.decouple()
|
|
201
251
|
if (w !== this.localWriter) await w.close()
|
|
202
252
|
}
|
|
203
|
-
|
|
204
|
-
_bootstrap() {
|
|
205
|
-
const bootstrap = this.auto.bootstrap
|
|
206
|
-
|
|
207
|
-
bootstrap.setEncryption(this.auto._getEncryptionProvider())
|
|
208
|
-
bootstrap.setActive(true)
|
|
209
|
-
|
|
210
|
-
const id = b4a.toString(bootstrap.key, 'hex')
|
|
211
|
-
let w = this.active.get(id)
|
|
212
|
-
if (w) {
|
|
213
|
-
w.couple() // couple if we weren't ready first time
|
|
214
|
-
return
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const session = bootstrap.session()
|
|
218
|
-
session.setEncryption(this.auto._getEncryptionProvider())
|
|
219
|
-
|
|
220
|
-
w = new Writer(this, this.auto.system, false, session, id)
|
|
221
|
-
w.attach()
|
|
222
|
-
w.couple()
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
attest(witnessed) {
|
|
226
|
-
const local = this.localWriter
|
|
227
|
-
|
|
228
|
-
for (const { key, weight } of witnessed) {
|
|
229
|
-
if (b4a.equals(key, local.core.key)) continue // never attest about myself
|
|
230
|
-
if (this.attestations.some((a) => a.weight === weight && b4a.equals(a.key, key))) continue
|
|
231
|
-
|
|
232
|
-
this.attestations.push({ key, weight })
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
253
|
}
|
|
236
254
|
|
|
237
255
|
class Writer {
|
|
@@ -248,6 +266,7 @@ class Writer {
|
|
|
248
266
|
this.appendLength = this.core.length + 1
|
|
249
267
|
this.waiting = null
|
|
250
268
|
this.download = null
|
|
269
|
+
this.hintedLength = 0
|
|
251
270
|
|
|
252
271
|
this.isPending = false
|
|
253
272
|
this.isClosed = false
|
|
@@ -256,17 +275,26 @@ class Writer {
|
|
|
256
275
|
this.isRemoved = false
|
|
257
276
|
this.isCoupled = false
|
|
258
277
|
this.isFrozen = false
|
|
278
|
+
this.isHead = false
|
|
259
279
|
|
|
260
280
|
this._onchangeBound = this._onchange.bind(this)
|
|
261
281
|
|
|
262
282
|
if (!local) this.core.on('append', this._onchangeBound)
|
|
263
283
|
if (!local) this.core.on('download', this._onchangeBound)
|
|
264
|
-
|
|
265
|
-
this.couple()
|
|
266
284
|
}
|
|
267
285
|
|
|
268
286
|
get isIndexer() {
|
|
269
|
-
return this.weight
|
|
287
|
+
return this.weight >= 2
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
isSystemHead() {
|
|
291
|
+
if (this.core.length === 0) return false
|
|
292
|
+
|
|
293
|
+
if (this.system.heads.length === 0) {
|
|
294
|
+
return b4a.equals(this.core.key, this.writers.auto.key)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return this.system.isHead(this.core.key)
|
|
270
298
|
}
|
|
271
299
|
|
|
272
300
|
couple() {
|
|
@@ -303,6 +331,8 @@ class Writer {
|
|
|
303
331
|
if (!this.isPending) return
|
|
304
332
|
this.isPending = false
|
|
305
333
|
|
|
334
|
+
this.writers._pendingBuffer.delete(this)
|
|
335
|
+
|
|
306
336
|
const head = this.writers.pending.pop()
|
|
307
337
|
if (head !== this) {
|
|
308
338
|
this.writers.pending[this.index] = head
|
|
@@ -310,7 +340,16 @@ class Writer {
|
|
|
310
340
|
}
|
|
311
341
|
}
|
|
312
342
|
|
|
343
|
+
// a peer announced this length for us, so we're not caught up until we've seen it
|
|
344
|
+
hint(length) {
|
|
345
|
+
if (length > this.hintedLength) {
|
|
346
|
+
this.hintedLength = length
|
|
347
|
+
this.core.setActive(true)
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
313
351
|
_onchange() {
|
|
352
|
+
this.hint(this.core.length)
|
|
314
353
|
if (this.waiting === null) this.bump()
|
|
315
354
|
}
|
|
316
355
|
|
|
@@ -347,10 +386,10 @@ class Writer {
|
|
|
347
386
|
|
|
348
387
|
const length = await this.update()
|
|
349
388
|
|
|
350
|
-
// don't drop any local nodes left in buffer
|
|
351
|
-
if (length < this.core.length || this.appending) {
|
|
389
|
+
// don't drop any local nodes left in buffer, or work a peer told us about
|
|
390
|
+
if (length < this.core.length || length < this.hintedLength || this.appending) {
|
|
352
391
|
this.addPending()
|
|
353
|
-
} else if (this !== this.writers.localWriter && !this.
|
|
392
|
+
} else if (this !== this.writers.localWriter && !this.isHead) {
|
|
354
393
|
await this.detachAndClose()
|
|
355
394
|
}
|
|
356
395
|
}
|
|
@@ -370,6 +409,7 @@ class Writer {
|
|
|
370
409
|
|
|
371
410
|
detachAndClose() {
|
|
372
411
|
this.detach()
|
|
412
|
+
this.decouple()
|
|
373
413
|
return this.close()
|
|
374
414
|
}
|
|
375
415
|
|
|
@@ -396,10 +436,24 @@ class Writer {
|
|
|
396
436
|
|
|
397
437
|
async update() {
|
|
398
438
|
const info = await this.system.get(this.core.key)
|
|
439
|
+
const length = info ? info.length : 0
|
|
399
440
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
441
|
+
const isHead = this.isSystemHead()
|
|
442
|
+
|
|
443
|
+
if (isHead) {
|
|
444
|
+
this.isHead = true
|
|
445
|
+
this.couple()
|
|
446
|
+
} else {
|
|
447
|
+
this.isHead = false
|
|
448
|
+
this.decouple()
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const active = length < this.core.length || length < this.hintedLength
|
|
452
|
+
|
|
453
|
+
if (this.isHead || active) {
|
|
454
|
+
this.core.setActive(true)
|
|
455
|
+
} else {
|
|
456
|
+
this.core.setActive(false)
|
|
403
457
|
}
|
|
404
458
|
|
|
405
459
|
if (!info) {
|
|
@@ -415,7 +469,7 @@ class Writer {
|
|
|
415
469
|
this.writers._updateLocalState()
|
|
416
470
|
}
|
|
417
471
|
|
|
418
|
-
return
|
|
472
|
+
return length
|
|
419
473
|
}
|
|
420
474
|
|
|
421
475
|
next() {
|
|
@@ -493,30 +547,8 @@ class Writer {
|
|
|
493
547
|
return null
|
|
494
548
|
}
|
|
495
549
|
|
|
496
|
-
for (const att of node.attestations || []) {
|
|
497
|
-
if (!b4a.equals(att.key, this.writers.localWriter.core.key)) continue
|
|
498
|
-
|
|
499
|
-
const seen = this.writers.witnesses.some(
|
|
500
|
-
(w) =>
|
|
501
|
-
w.length === node.length &&
|
|
502
|
-
w.attestation.weight === att.weight &&
|
|
503
|
-
b4a.equals(w.key, node.key)
|
|
504
|
-
)
|
|
505
|
-
if (seen) continue
|
|
506
|
-
|
|
507
|
-
const manifest = this.core.getManifest({ raw: true })
|
|
508
|
-
if (!manifest) continue
|
|
509
|
-
|
|
510
|
-
this.writers.witnesses.push({
|
|
511
|
-
key: node.key,
|
|
512
|
-
length: node.length,
|
|
513
|
-
attestation: att,
|
|
514
|
-
manifest
|
|
515
|
-
})
|
|
516
|
-
}
|
|
517
|
-
|
|
518
550
|
batch.push(node)
|
|
519
|
-
if (b.end === 0) return batch
|
|
551
|
+
if (b.end === 0) return finalizeNodeBatch(batch)
|
|
520
552
|
|
|
521
553
|
// TODO: mark as dead
|
|
522
554
|
if (batch.length >= BATCH_WRITER_SANITY) return null
|
|
@@ -572,17 +604,24 @@ class Writer {
|
|
|
572
604
|
}
|
|
573
605
|
|
|
574
606
|
async _isLinked(node) {
|
|
575
|
-
// the backer gates like a link: present-or-wait
|
|
576
607
|
let links = node.links
|
|
577
608
|
if (node.witness) {
|
|
578
609
|
links = links.slice()
|
|
579
|
-
links.push({ key: node.witness.
|
|
610
|
+
links.push({ key: node.witness.link.key, length: node.witness.link.length })
|
|
580
611
|
}
|
|
581
612
|
|
|
582
613
|
const promises = new Array(links.length)
|
|
583
614
|
|
|
584
615
|
for (let i = 0; i < links.length; i++) {
|
|
585
|
-
|
|
616
|
+
const link = links[i]
|
|
617
|
+
|
|
618
|
+
// legacy batch nodes link their own previous node, satisfied by oplog order
|
|
619
|
+
if (link.length < node.length && b4a.equals(link.key, this.core.key)) {
|
|
620
|
+
promises[i] = true
|
|
621
|
+
continue
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
promises[i] = this.system.has(link)
|
|
586
625
|
}
|
|
587
626
|
|
|
588
627
|
const has = await Promise.all(promises)
|
|
@@ -612,16 +651,18 @@ class Writer {
|
|
|
612
651
|
return this.pending !== null
|
|
613
652
|
}
|
|
614
653
|
|
|
615
|
-
append(value, timestamp, batch, links, optimistic, witness) {
|
|
654
|
+
append(value, timestamp, batch, links, optimistic, witness, approvals = null) {
|
|
616
655
|
if (this.pending === null) this.pending = []
|
|
617
656
|
|
|
618
657
|
const oplog = {
|
|
619
658
|
version: encoding.OPLOG_VERSION,
|
|
620
659
|
timestamp,
|
|
621
660
|
links,
|
|
622
|
-
witness: witness || null,
|
|
623
661
|
batch,
|
|
624
662
|
views: null,
|
|
663
|
+
trusted: null,
|
|
664
|
+
witness: witness || null,
|
|
665
|
+
approvals,
|
|
625
666
|
optimistic: optimistic && !this.writers.writable,
|
|
626
667
|
value
|
|
627
668
|
}
|
|
@@ -646,39 +687,43 @@ class Writer {
|
|
|
646
687
|
this.processed = 0
|
|
647
688
|
}
|
|
648
689
|
|
|
649
|
-
flush(views,
|
|
650
|
-
if (this.pending === null || this.processed === 0) return
|
|
690
|
+
async flush(views, trusted) {
|
|
691
|
+
if (this.pending === null || this.processed === 0) return
|
|
651
692
|
|
|
652
693
|
const head = this.pending[this.processed - 1]
|
|
653
694
|
head.views = views
|
|
654
695
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
for (const { key, weight } of queued) {
|
|
658
|
-
const signature = signAttestation(
|
|
659
|
-
this.core.keyPair.secretKey,
|
|
660
|
-
this.core.key,
|
|
661
|
-
key,
|
|
662
|
-
head.length,
|
|
663
|
-
weight
|
|
664
|
-
)
|
|
665
|
-
attestations.push({ key, weight, signature })
|
|
666
|
-
}
|
|
667
|
-
head.attestations = attestations
|
|
668
|
-
}
|
|
696
|
+
head.trusted = trusted ? [{ key: trusted.key, length: trusted.length }] : null
|
|
697
|
+
this.writers.auto.emit('appending', this.pending)
|
|
669
698
|
|
|
670
699
|
const buffers = []
|
|
671
700
|
for (let i = 0; i < this.processed; i++) {
|
|
672
701
|
buffers.push(encoding.encodeOplog(this.pending[i]))
|
|
673
702
|
}
|
|
674
|
-
|
|
675
|
-
|
|
703
|
+
|
|
704
|
+
try {
|
|
705
|
+
await this.core.append(buffers)
|
|
706
|
+
} finally {
|
|
707
|
+
this.clear()
|
|
708
|
+
}
|
|
676
709
|
}
|
|
677
710
|
}
|
|
678
711
|
|
|
712
|
+
// mirrors topo.cmp - kept local because topo.js requires this module
|
|
713
|
+
function sortsBefore(a, b) {
|
|
714
|
+
if (a.weight !== b.weight) return a.weight > b.weight
|
|
715
|
+
if (a.timestamp !== b.timestamp) return a.timestamp < b.timestamp
|
|
716
|
+
|
|
717
|
+
const c = b4a.compare(a.key, b.key)
|
|
718
|
+
if (c !== 0) return c < 0
|
|
719
|
+
|
|
720
|
+
return a.length < b.length
|
|
721
|
+
}
|
|
722
|
+
|
|
679
723
|
exports.ActiveWriters = ActiveWriters
|
|
680
724
|
exports.Writer = Writer
|
|
681
725
|
exports.createNode = createNode
|
|
726
|
+
exports.finalizeNodeBatch = finalizeNodeBatch
|
|
682
727
|
|
|
683
728
|
function createNode(core, length, weight, oplog) {
|
|
684
729
|
return {
|
|
@@ -690,13 +735,32 @@ function createNode(core, length, weight, oplog) {
|
|
|
690
735
|
version: oplog.version,
|
|
691
736
|
timestamp: oplog.timestamp,
|
|
692
737
|
links: oplog.links,
|
|
693
|
-
witness: oplog.witness || null,
|
|
694
|
-
attestations: oplog.attestations || null,
|
|
695
738
|
batch: oplog.batch,
|
|
696
739
|
views: oplog.views,
|
|
740
|
+
trusted: oplog.trusted || [],
|
|
741
|
+
witness: oplog.witness || null,
|
|
742
|
+
approvals: oplog.approvals || null,
|
|
697
743
|
optimistic: oplog.optimistic,
|
|
698
744
|
value: oplog.value
|
|
699
745
|
}
|
|
700
746
|
}
|
|
701
747
|
|
|
748
|
+
function finalizeNodeBatch(batch) {
|
|
749
|
+
// replay batches keep unreachable blocks as null holes (topo.getOplogBatch)
|
|
750
|
+
let first = null
|
|
751
|
+
for (const node of batch) {
|
|
752
|
+
if (node !== null) {
|
|
753
|
+
first = node
|
|
754
|
+
break
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
if (first === null || first.version > LEGACY_OPLOG_VERSION) return batch
|
|
758
|
+
|
|
759
|
+
for (let i = 0; i < batch.length; i++) {
|
|
760
|
+
if (batch[i] !== null) batch[i].batch.start = i
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
return batch
|
|
764
|
+
}
|
|
765
|
+
|
|
702
766
|
function noop() {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autobee",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Bee based autobase",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Holepunch Inc.",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"autobee-encryption": "^0.1.2",
|
|
27
27
|
"autobee-wakeup": "^1.1.3",
|
|
28
28
|
"b4a": "^1.8.0",
|
|
29
|
-
"compact-encoding": "^
|
|
29
|
+
"compact-encoding": "^3.3.0",
|
|
30
30
|
"hyperbee2": "^2.10.3",
|
|
31
31
|
"hypercore": "^11.33.2",
|
|
32
32
|
"hypercore-id-encoding": "^1.3.0",
|
|
@@ -38,11 +38,12 @@
|
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"brittle": "^4.1.0",
|
|
41
|
-
"corestore": "^7.
|
|
41
|
+
"corestore": "^7.12.2",
|
|
42
42
|
"hypercore-crypto": "^3.6.1",
|
|
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
|
}
|