autobee 2.0.0-rc.2 → 2.0.0-rc.21

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 CHANGED
@@ -78,7 +78,10 @@ Options:
78
78
  encryptionKey: Buffer, // 32-byte key to encrypt all data at rest
79
79
  encrypted: false, // set true if using encryptionKey
80
80
  keyPair: { publicKey, secretKey }, // custom signing key pair for the local writer
81
- optimistic: true // allow optimistic writes from unknown writers
81
+ optimistic: true, // allow optimistic writes from unknown writers
82
+ isTrusted (key, reference) {}, // do we trust this writer, see Fast-forward
83
+ mostRecentTrusted (target, reference) {}, // the head we vouch for, see Fast-forward
84
+ fastForward: {} // see Fast-forward
82
85
  }
83
86
  ```
84
87
 
@@ -222,6 +225,50 @@ Create an anchor node. Returns `{ key, length }`. Anchors are used to create a v
222
225
 
223
226
  `true` if the system has not yet processed any nodes. Use this to bootstrap the first writer.
224
227
 
228
+ ### Fast-forward
229
+
230
+ Fast-forward only ever deals in oplog heads — `{ key, length }` of a writer's core, never a system head.
231
+
232
+ Each flush stamps the head you vouch for into your own oplog, and peers read those stamps out of the writers they wake up on, so trust travels with the log.
233
+
234
+ #### `isTrusted(key, reference)`
235
+
236
+ Return whether `key` is a writer you trust, judged against the `reference` view.
237
+
238
+ Positive answers are cached until an undo rewinds the view, and the default is `true` unless you supply `mostRecentTrusted`, in which case it is `false`.
239
+
240
+ #### `mostRecentTrusted(target, reference)`
241
+
242
+ Return the oplog head you most recently vouched for, given the `target` view being considered.
243
+
244
+ Called at flush time to stamp your own oplog (with your view as `target` and a `null` reference), and again per candidate during discovery.
245
+
246
+ #### `fastForward.boot`
247
+
248
+ ```js
249
+ {
250
+ head: { key, length }, // oplog head to boot from
251
+ legacy: { key, length }, // pre-2.0 pointer, see below
252
+ bootCondition (target, reference) {} // optional gate on the view we would land on
253
+ }
254
+ ```
255
+
256
+ Pass one of `head` or `legacy`, not both.
257
+
258
+ Without `bootCondition` this is a single attempt that gives up if the head cannot be read; with one it parks until the condition is satisfied, which today means indefinitely if it never is.
259
+
260
+ `legacy` is for records written before boot heads were oplog heads: the key is a _system_ head and a `0` length is resolved from the core. It boots ungated - `bootCondition` does not apply - and will be removed, so don't reach for it. A bare `{ key, length }` in place of the whole struct means the same thing, older still.
261
+
262
+ #### `fastForward.conservative`
263
+
264
+ Defaults to `true`: only fast-forward onto a head a connected peer can serve whole.
265
+
266
+ The check covers the oplog head only, not the system and view cores the fast-forward then reads.
267
+
268
+ #### `await db.moveTo(head)`
269
+
270
+ Fast-forward onto an oplog head, ignoring the usual distance and conservative checks. Resolves `{ to, from }`.
271
+
225
272
  ### Encryption
226
273
 
227
274
  Pass an `encryptionKey` to encrypt all writer cores and the view at rest.
@@ -169,7 +169,7 @@ module.exports = function buildAutobaseSchema(schema, DIR) {
169
169
  },
170
170
  {
171
171
  name: 'value',
172
- type: 'buffer',
172
+ type: 'optionalBuffer',
173
173
  required: true
174
174
  }
175
175
  ]
@@ -153,18 +153,18 @@ const Node = {
153
153
  preencode(state, m) {
154
154
  Clock.preencode(state, m.heads)
155
155
  c.uint.preencode(state, m.batch)
156
- c.buffer.preencode(state, m.value)
156
+ c.optionalBuffer.preencode(state, m.value)
157
157
  },
158
158
  encode(state, m) {
159
159
  Clock.encode(state, m.heads)
160
160
  c.uint.encode(state, m.batch)
161
- c.buffer.encode(state, m.value)
161
+ c.optionalBuffer.encode(state, m.value)
162
162
  },
163
163
  decode(state, m) {
164
164
  return {
165
165
  heads: Clock.decode(state),
166
166
  batch: c.uint.decode(state),
167
- value: c.buffer.decode(state)
167
+ value: c.optionalBuffer.decode(state)
168
168
  }
169
169
  }
170
170
  }
@@ -97,8 +97,9 @@ const encoding4 = {
97
97
  // @autobase-compat/boot-record
98
98
  const encoding5 = {
99
99
  preencode(state, m) {
100
- c.uint.preencode(state, m.version)
101
- switch (m.version) {
100
+ const v = m.version ?? 3
101
+ c.uint.preencode(state, v)
102
+ switch (v) {
102
103
  case 0:
103
104
  encoding3.preencode(state, m)
104
105
  break
@@ -112,8 +113,9 @@ const encoding5 = {
112
113
  }
113
114
  },
114
115
  encode(state, m) {
115
- c.uint.encode(state, m.version)
116
- switch (m.version) {
116
+ const v = m.version ?? 3
117
+ c.uint.encode(state, v)
118
+ switch (v) {
117
119
  case 0:
118
120
  encoding3.encode(state, m)
119
121
  break
@@ -236,17 +238,17 @@ const encoding9 = {
236
238
  preencode(state, m) {
237
239
  encoding1.preencode(state, m.heads)
238
240
  c.uint.preencode(state, m.batch)
239
- c.buffer.preencode(state, m.value)
241
+ c.optionalBuffer.preencode(state, m.value)
240
242
  },
241
243
  encode(state, m) {
242
244
  encoding1.encode(state, m.heads)
243
245
  c.uint.encode(state, m.batch)
244
- c.buffer.encode(state, m.value)
246
+ c.optionalBuffer.encode(state, m.value)
245
247
  },
246
248
  decode(state) {
247
249
  const r0 = encoding1.decode(state)
248
250
  const r1 = c.uint.decode(state)
249
- const r2 = c.buffer.decode(state)
251
+ const r2 = c.optionalBuffer.decode(state)
250
252
 
251
253
  return {
252
254
  heads: r0,
@@ -496,8 +498,9 @@ const encoding18 = {
496
498
  // @autobee/system-info
497
499
  const encoding19 = {
498
500
  preencode(state, m) {
499
- c.uint.preencode(state, m.version)
500
- switch (m.version) {
501
+ const v = m.version ?? 3
502
+ c.uint.preencode(state, v)
503
+ switch (v) {
501
504
  case 0:
502
505
  case 1:
503
506
  encoding15.preencode(state, m)
@@ -513,8 +516,9 @@ const encoding19 = {
513
516
  }
514
517
  },
515
518
  encode(state, m) {
516
- c.uint.encode(state, m.version)
517
- switch (m.version) {
519
+ const v = m.version ?? 3
520
+ c.uint.encode(state, v)
521
+ switch (v) {
518
522
  case 0:
519
523
  case 1:
520
524
  encoding15.encode(state, m)
@@ -603,8 +607,9 @@ const encoding20 = {
603
607
  // @autobee/system-writer
604
608
  const encoding21 = {
605
609
  preencode(state, m) {
606
- c.uint.preencode(state, m.version)
607
- switch (m.version) {
610
+ const v = m.version ?? 4
611
+ c.uint.preencode(state, v)
612
+ switch (v) {
608
613
  case 0:
609
614
  case 1:
610
615
  case 2:
@@ -619,8 +624,9 @@ const encoding21 = {
619
624
  }
620
625
  },
621
626
  encode(state, m) {
622
- c.uint.encode(state, m.version)
623
- switch (m.version) {
627
+ const v = m.version ?? 4
628
+ c.uint.encode(state, v)
629
+ switch (v) {
624
630
  case 0:
625
631
  case 1:
626
632
  case 2:
@@ -850,15 +856,28 @@ const encoding29_7 = c.array(c.frame(encoding28))
850
856
  // @autobee/oplog-message-v3
851
857
  const encoding29 = {
852
858
  preencode(state, m) {
859
+ let flags =
860
+ (m.batch ? 1 : 0) |
861
+ (m.views ? 2 : 0) |
862
+ (m.optimistic ? 8 : 0) |
863
+ (m.value ? 16 : 0) |
864
+ (m.witness ? 32 : 0) |
865
+ (m.attestations ? 64 : 0) |
866
+ (m.trusted ? 128 : 0)
867
+ if (m.views) {
868
+ flags |= m.views.view ? 4 : 0
869
+ }
870
+
853
871
  c.uint.preencode(state, m.timestamp)
854
872
  encoding29_1.preencode(state, m.links)
855
- state.end++ // max flag is 64 so always one byte
873
+ c.uint.preencode(state, flags)
856
874
 
857
875
  if (m.batch) encoding24.preencode(state, m.batch)
858
876
  if (m.views) encoding25_inline.preencode(state, m.views)
859
877
  if (m.value) c.buffer.preencode(state, m.value)
860
878
  if (m.witness) encoding29_6.preencode(state, m.witness)
861
879
  if (m.attestations) encoding29_7.preencode(state, m.attestations)
880
+ if (m.trusted) encoding29_8.preencode(state, m.trusted)
862
881
  },
863
882
  encode(state, m) {
864
883
  let flags =
@@ -867,7 +886,8 @@ const encoding29 = {
867
886
  (m.optimistic ? 8 : 0) |
868
887
  (m.value ? 16 : 0) |
869
888
  (m.witness ? 32 : 0) |
870
- (m.attestations ? 64 : 0)
889
+ (m.attestations ? 64 : 0) |
890
+ (m.trusted ? 128 : 0)
871
891
  if (m.views) {
872
892
  flags |= m.views.view ? 4 : 0
873
893
  }
@@ -881,6 +901,7 @@ const encoding29 = {
881
901
  if (m.value) c.buffer.encode(state, m.value)
882
902
  if (m.witness) encoding29_6.encode(state, m.witness)
883
903
  if (m.attestations) encoding29_7.encode(state, m.attestations)
904
+ if (m.trusted) encoding29_8.encode(state, m.trusted)
884
905
  },
885
906
  decode(state) {
886
907
  const v = c.uint.decode(state)
@@ -897,7 +918,8 @@ const encoding29 = {
897
918
  optimistic: (flags & 8) !== 0,
898
919
  value: (flags & 16) !== 0 ? c.buffer.decode(state) : null,
899
920
  witness: (flags & 32) !== 0 ? encoding29_6.decode(state) : null,
900
- attestations: (flags & 64) !== 0 ? encoding29_7.decode(state) : null
921
+ attestations: (flags & 64) !== 0 ? encoding29_7.decode(state) : null,
922
+ trusted: (flags & 128) !== 0 ? encoding29_8.decode(state) : null
901
923
  }
902
924
  }
903
925
  }
@@ -905,8 +927,9 @@ const encoding29 = {
905
927
  // @autobee/oplog
906
928
  const encoding30 = {
907
929
  preencode(state, m) {
908
- c.uint.preencode(state, m.version)
909
- switch (m.version) {
930
+ const v = m.version ?? 3
931
+ c.uint.preencode(state, v)
932
+ switch (v) {
910
933
  case 0:
911
934
  encoding12.preencode(state, m)
912
935
  break
@@ -924,8 +947,9 @@ const encoding30 = {
924
947
  }
925
948
  },
926
949
  encode(state, m) {
927
- c.uint.encode(state, m.version)
928
- switch (m.version) {
950
+ const v = m.version ?? 3
951
+ c.uint.encode(state, v)
952
+ switch (v) {
929
953
  case 0:
930
954
  encoding12.encode(state, m)
931
955
  break
@@ -999,12 +1023,66 @@ const encoding31 = {
999
1023
  }
1000
1024
  }
1001
1025
 
1026
+ // @autobee/trusted-head
1027
+ const encoding32 = {
1028
+ preencode(state, m) {
1029
+ c.fixed32.preencode(state, m.key)
1030
+ c.uint.preencode(state, m.length)
1031
+ c.uint.preencode(state, m.flushes)
1032
+ },
1033
+ encode(state, m) {
1034
+ c.fixed32.encode(state, m.key)
1035
+ c.uint.encode(state, m.length)
1036
+ c.uint.encode(state, m.flushes)
1037
+ },
1038
+ decode(state) {
1039
+ const r0 = c.fixed32.decode(state)
1040
+ const r1 = c.uint.decode(state)
1041
+ const r2 = c.uint.decode(state)
1042
+
1043
+ return {
1044
+ key: r0,
1045
+ length: r1,
1046
+ flushes: r2
1047
+ }
1048
+ }
1049
+ }
1050
+
1051
+ // @autobee/migrated-head
1052
+ const encoding33 = {
1053
+ preencode(state, m) {
1054
+ encoding22.preencode(state, m.system)
1055
+ state.end++ // flags are fixed size
1056
+
1057
+ if (m.view) encoding22.preencode(state, m.view)
1058
+ },
1059
+ encode(state, m) {
1060
+ const flags = m.view ? 1 : 0
1061
+
1062
+ encoding22.encode(state, m.system)
1063
+ c.uint8.encode(state, flags)
1064
+
1065
+ if (m.view) encoding22.encode(state, m.view)
1066
+ },
1067
+ decode(state) {
1068
+ const r0 = encoding22.decode(state)
1069
+ const flags = c.uint8.decode(state)
1070
+
1071
+ return {
1072
+ system: r0,
1073
+ view: (flags & 1) !== 0 ? encoding22.decode(state) : null
1074
+ }
1075
+ }
1076
+ }
1077
+
1002
1078
  // @autobee/system-info-v3.heads, deferred due to recusive use
1003
1079
  const encoding18_3 = c.array(encoding22)
1004
1080
  // @autobee/system-info-v3.indexers, deferred due to recusive use
1005
1081
  const encoding18_4 = encoding18_3
1006
1082
  // @autobee/oplog-message-v3.links, deferred due to recusive use
1007
1083
  const encoding29_1 = encoding18_3
1084
+ // @autobee/oplog-message-v3.trusted, deferred due to recusive use
1085
+ const encoding29_8 = c.array(c.frame(encoding32))
1008
1086
 
1009
1087
  function setVersion(v) {
1010
1088
  version = v
@@ -1093,6 +1171,10 @@ function getEncoding(name) {
1093
1171
  return encoding30
1094
1172
  case '@autobee/manifest-data':
1095
1173
  return encoding31
1174
+ case '@autobee/trusted-head':
1175
+ return encoding32
1176
+ case '@autobee/migrated-head':
1177
+ return encoding33
1096
1178
  default:
1097
1179
  throw new Error('Encoder not found ' + name)
1098
1180
  }
@@ -194,7 +194,7 @@
194
194
  {
195
195
  "name": "value",
196
196
  "required": true,
197
- "type": "buffer",
197
+ "type": "optionalBuffer",
198
198
  "version": 1
199
199
  }
200
200
  ]
@@ -750,6 +750,12 @@
750
750
  "array": true,
751
751
  "type": "@autobee/attestation",
752
752
  "version": 1
753
+ },
754
+ {
755
+ "name": "trusted",
756
+ "array": true,
757
+ "type": "@autobee/trusted-head",
758
+ "version": 1
753
759
  }
754
760
  ]
755
761
  },
@@ -804,6 +810,62 @@
804
810
  "version": 1
805
811
  }
806
812
  ]
813
+ },
814
+ {
815
+ "name": "trusted-head",
816
+ "namespace": "autobee",
817
+ "compact": false,
818
+ "flagsPosition": -1,
819
+ "fields": [
820
+ {
821
+ "name": "key",
822
+ "required": true,
823
+ "type": "fixed32",
824
+ "version": 1
825
+ },
826
+ {
827
+ "name": "length",
828
+ "required": true,
829
+ "type": "uint",
830
+ "version": 1
831
+ },
832
+ {
833
+ "name": "flushes",
834
+ "required": true,
835
+ "type": "uint",
836
+ "version": 1
837
+ }
838
+ ]
839
+ },
840
+ {
841
+ "name": "migrated-head",
842
+ "namespace": "autobee",
843
+ "compact": true,
844
+ "flagsPosition": 1,
845
+ "fields": [
846
+ {
847
+ "name": "system",
848
+ "required": true,
849
+ "type": "@autobee/link",
850
+ "version": 1
851
+ },
852
+ {
853
+ "name": "view",
854
+ "required": false,
855
+ "type": "@autobee/link",
856
+ "version": 1
857
+ }
858
+ ]
859
+ }
860
+ ],
861
+ "namespaces": [
862
+ {
863
+ "name": "autobee",
864
+ "external": "../../legacy.js"
865
+ },
866
+ {
867
+ "name": "autobase-compat",
868
+ "external": "../../legacy.js"
807
869
  }
808
870
  ]
809
871
  }