@agoric/swingset-vat 0.33.0-upgrade-16-dev-0df76a7.0 → 0.33.0-upgrade-17-dev-a1453b2.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.
Files changed (76) hide show
  1. package/README.md +1 -1
  2. package/package.json +31 -30
  3. package/src/controller/controller.js +48 -1
  4. package/src/controller/initializeKernel.js +35 -10
  5. package/src/controller/initializeSwingset.js +6 -3
  6. package/src/controller/startXSnap.js +1 -1
  7. package/src/controller/upgradeSwingset.js +212 -0
  8. package/src/devices/bridge/device-bridge.js +1 -1
  9. package/src/devices/bundle/device-bundle.js +1 -1
  10. package/src/devices/command/command.js +1 -2
  11. package/src/devices/command/device-command.js +1 -2
  12. package/src/devices/lib/deviceTools.js +1 -1
  13. package/src/devices/loopbox/device-loopbox.js +1 -1
  14. package/src/devices/loopbox/loopbox.js +1 -1
  15. package/src/devices/mailbox/device-mailbox.js +1 -2
  16. package/src/devices/mailbox/mailbox.js +1 -2
  17. package/src/devices/plugin/device-plugin.js +1 -1
  18. package/src/devices/timer/device-timer.js +1 -1
  19. package/src/devices/timer/timer.js +1 -1
  20. package/src/devices/vat-admin/device-vat-admin.js +4 -2
  21. package/src/index.js +1 -1
  22. package/src/kernel/deviceManager.js +1 -1
  23. package/src/kernel/deviceSlots.js +1 -1
  24. package/src/kernel/deviceTranslator.js +1 -1
  25. package/src/kernel/dummyMeterControl.js +1 -1
  26. package/src/kernel/gc-actions.js +55 -34
  27. package/src/kernel/kernel.js +216 -51
  28. package/src/kernel/kernelSyscall.js +2 -13
  29. package/src/kernel/parseKernelSlots.js +1 -1
  30. package/src/kernel/slogger.js +2 -2
  31. package/src/kernel/state/deviceKeeper.js +1 -1
  32. package/src/kernel/state/kernelKeeper.js +427 -81
  33. package/src/kernel/state/reachable.js +1 -1
  34. package/src/kernel/state/stats.js +1 -1
  35. package/src/kernel/state/storageHelper.js +1 -1
  36. package/src/kernel/state/vatKeeper.js +159 -44
  37. package/src/kernel/vat-admin-hooks.js +4 -1
  38. package/src/kernel/vat-loader/manager-factory.js +1 -2
  39. package/src/kernel/vat-loader/manager-helper.js +1 -1
  40. package/src/kernel/vat-loader/manager-local.js +1 -1
  41. package/src/kernel/vat-loader/manager-subprocess-node.js +1 -1
  42. package/src/kernel/vat-loader/manager-subprocess-xsnap.js +1 -1
  43. package/src/kernel/vat-loader/vat-loader.js +2 -2
  44. package/src/kernel/vat-warehouse.js +5 -1
  45. package/src/kernel/vatTranslator.js +1 -4
  46. package/src/lib/assertOptions.js +1 -1
  47. package/src/lib/capdata.js +1 -1
  48. package/src/lib/id.js +1 -1
  49. package/src/lib/message.js +1 -1
  50. package/src/lib/parseVatSlots.js +1 -1
  51. package/src/lib/recordVatOptions.js +18 -6
  52. package/src/lib/runPolicies.js +50 -4
  53. package/src/lib/storageAPI.js +1 -1
  54. package/src/lib/workerOptions.js +1 -1
  55. package/src/supervisors/subprocess-node/supervisor-subprocess-node.js +1 -1
  56. package/src/types-external.js +71 -22
  57. package/src/types-internal.js +56 -3
  58. package/src/vats/comms/clist-inbound.js +1 -1
  59. package/src/vats/comms/clist-kernel.js +1 -1
  60. package/src/vats/comms/clist-outbound.js +1 -1
  61. package/src/vats/comms/controller.js +1 -1
  62. package/src/vats/comms/delivery.js +1 -1
  63. package/src/vats/comms/dispatch.js +1 -1
  64. package/src/vats/comms/gc-comms.js +1 -1
  65. package/src/vats/comms/parseLocalSlots.js +1 -1
  66. package/src/vats/comms/parseRemoteSlot.js +1 -1
  67. package/src/vats/comms/remote.js +1 -1
  68. package/src/vats/comms/state.js +1 -1
  69. package/src/vats/timer/vat-timer.js +9 -9
  70. package/src/vats/vat-admin/vat-vat-admin.js +23 -8
  71. package/src/vats/vattp/vat-vattp.js +1 -1
  72. package/tools/bootstrap-relay.js +1 -3
  73. package/tools/bundleTool.js +9 -1
  74. package/tools/dvo-test-harness.js +1 -1
  75. package/tools/manual-timer.js +1 -1
  76. package/tools/run-utils.js +1 -1
package/README.md CHANGED
@@ -204,7 +204,7 @@ If wavy dot syntax is used on a Promise which rejects, the method is not invoked
204
204
  the return promise's `rejection` function is called instead:
205
205
 
206
206
  ```js
207
- const badP = Promise.reject(new Error());
207
+ const badP = Promise.reject(Error());
208
208
  const p2 = badP~.foo();
209
209
  p2.then(undefined, rej => console.log('rejected', rej));
210
210
  // prints 'rejected'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/swingset-vat",
3
- "version": "0.33.0-upgrade-16-dev-0df76a7.0+0df76a7",
3
+ "version": "0.33.0-upgrade-17-dev-a1453b2.0+a1453b2",
4
4
  "description": "Vat/Container Launcher",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -27,33 +27,34 @@
27
27
  "@types/yargs-parser": "^21.0.0"
28
28
  },
29
29
  "dependencies": {
30
- "@agoric/assert": "0.6.1-upgrade-16-dev-0df76a7.0+0df76a7",
31
- "@agoric/internal": "0.4.0-upgrade-16-dev-0df76a7.0+0df76a7",
32
- "@agoric/kmarshal": "0.1.1-upgrade-16-dev-0df76a7.0+0df76a7",
33
- "@agoric/store": "0.9.3-upgrade-16-dev-0df76a7.0+0df76a7",
34
- "@agoric/swing-store": "0.9.2-upgrade-16-dev-0df76a7.0+0df76a7",
35
- "@agoric/swingset-liveslots": "0.10.3-upgrade-16-dev-0df76a7.0+0df76a7",
36
- "@agoric/swingset-xsnap-supervisor": "0.10.3-upgrade-16-dev-0df76a7.0+0df76a7",
37
- "@agoric/time": "0.3.3-upgrade-16-dev-0df76a7.0+0df76a7",
38
- "@agoric/vat-data": "0.5.3-upgrade-16-dev-0df76a7.0+0df76a7",
39
- "@agoric/xsnap": "0.14.3-upgrade-16-dev-0df76a7.0+0df76a7",
40
- "@agoric/xsnap-lockdown": "0.14.1-upgrade-16-dev-0df76a7.0+0df76a7",
41
- "@endo/base64": "^1.0.5",
42
- "@endo/bundle-source": "^3.2.3",
43
- "@endo/captp": "^4.2.0",
44
- "@endo/check-bundle": "^1.0.7",
45
- "@endo/compartment-mapper": "^1.1.5",
46
- "@endo/eventual-send": "^1.2.2",
47
- "@endo/far": "^1.1.2",
48
- "@endo/import-bundle": "^1.1.2",
49
- "@endo/init": "^1.1.2",
50
- "@endo/marshal": "^1.5.0",
51
- "@endo/nat": "^5.0.7",
52
- "@endo/patterns": "^1.4.0",
53
- "@endo/promise-kit": "^1.1.2",
54
- "@endo/ses-ava": "^1.2.2",
55
- "@endo/stream": "^1.2.2",
56
- "@endo/zip": "^1.0.5",
30
+ "@agoric/internal": "0.4.0-upgrade-17-dev-a1453b2.0+a1453b2",
31
+ "@agoric/kmarshal": "0.1.1-upgrade-17-dev-a1453b2.0+a1453b2",
32
+ "@agoric/store": "0.9.3-upgrade-17-dev-a1453b2.0+a1453b2",
33
+ "@agoric/swing-store": "0.9.2-upgrade-17-dev-a1453b2.0+a1453b2",
34
+ "@agoric/swingset-liveslots": "0.10.3-upgrade-17-dev-a1453b2.0+a1453b2",
35
+ "@agoric/swingset-xsnap-supervisor": "0.10.3-upgrade-17-dev-a1453b2.0+a1453b2",
36
+ "@agoric/time": "0.3.3-upgrade-17-dev-a1453b2.0+a1453b2",
37
+ "@agoric/vat-data": "0.5.3-upgrade-17-dev-a1453b2.0+a1453b2",
38
+ "@agoric/xsnap": "0.14.3-upgrade-17-dev-a1453b2.0+a1453b2",
39
+ "@agoric/xsnap-lockdown": "0.14.1-upgrade-17-dev-a1453b2.0+a1453b2",
40
+ "@endo/base64": "^1.0.7",
41
+ "@endo/bundle-source": "^3.4.0",
42
+ "@endo/captp": "^4.3.0",
43
+ "@endo/check-bundle": "^1.0.9",
44
+ "@endo/compartment-mapper": "^1.2.2",
45
+ "@endo/errors": "^1.2.5",
46
+ "@endo/eventual-send": "^1.2.5",
47
+ "@endo/far": "^1.1.5",
48
+ "@endo/import-bundle": "^1.2.2",
49
+ "@endo/init": "^1.1.4",
50
+ "@endo/marshal": "^1.5.3",
51
+ "@endo/nat": "^5.0.10",
52
+ "@endo/pass-style": "^1.4.3",
53
+ "@endo/patterns": "^1.4.3",
54
+ "@endo/promise-kit": "^1.1.5",
55
+ "@endo/ses-ava": "^1.2.5",
56
+ "@endo/stream": "^1.2.5",
57
+ "@endo/zip": "^1.0.7",
57
58
  "ansi-styles": "^6.2.1",
58
59
  "anylogger": "^0.21.0",
59
60
  "better-sqlite3": "^9.1.1",
@@ -100,7 +101,7 @@
100
101
  "access": "public"
101
102
  },
102
103
  "typeCoverage": {
103
- "atLeast": 75.02
104
+ "atLeast": 75.7
104
105
  },
105
- "gitHead": "0df76a71058eda04cdc75a54fb4312d286f323a3"
106
+ "gitHead": "a1453b2877b017a7f5b43a92364067d001901953"
106
107
  }
@@ -9,7 +9,7 @@ import { tmpName } from 'tmp';
9
9
  import anylogger from 'anylogger';
10
10
  import microtime from 'microtime';
11
11
 
12
- import { assert, Fail } from '@agoric/assert';
12
+ import { assert, Fail } from '@endo/errors';
13
13
  import { importBundle } from '@endo/import-bundle';
14
14
  import { initSwingStore } from '@agoric/swing-store';
15
15
 
@@ -21,6 +21,7 @@ import { waitUntilQuiescent } from '@agoric/internal/src/lib-nodejs/waitUntilQui
21
21
  import { makeGcAndFinalize } from '@agoric/internal/src/lib-nodejs/gc-and-finalize.js';
22
22
  import { kslot, krefOf } from '@agoric/kmarshal';
23
23
  import { insistStorageAPI } from '../lib/storageAPI.js';
24
+ import { insistCapData } from '../lib/capdata.js';
24
25
  import {
25
26
  buildKernelBundle,
26
27
  swingsetIsInitialized,
@@ -33,6 +34,10 @@ import {
33
34
  import { makeStartXSnap } from './startXSnap.js';
34
35
  import { makeStartSubprocessWorkerNode } from './startNodeSubprocess.js';
35
36
 
37
+ /**
38
+ * @typedef { import('../types-internal.js').VatID } VatID
39
+ */
40
+
36
41
  const endoZipBase64Sha512Shape = harden({
37
42
  moduleFormat: 'endoZipBase64',
38
43
  endoZipBase64: M.string(harden({ stringLengthLimit: Infinity })),
@@ -441,6 +446,48 @@ export async function makeSwingsetController(
441
446
  // no emitCrankHashes here because queueToVatRoot did that
442
447
  return result;
443
448
  },
449
+
450
+ /**
451
+ * terminate a vat by ID
452
+ *
453
+ * This allows the host app to terminate any vat. The effect is
454
+ * equivalent to the holder of the vat's `adminNode` calling
455
+ * `E(adminNode).terminateWithFailure(reason)`, or the vat itself
456
+ * calling `vatPowers.exitVatWithFailure(reason)`. It accepts a
457
+ * reason capdata structure (use 'kser()' to build one), which
458
+ * will be included in rejection data for the promise available to
459
+ * `E(adminNode).done()`, just like the internal termination APIs.
460
+ * Note that no slots/krefs are allowed in 'reason' when
461
+ * terminating the vat externally.
462
+ *
463
+ * This is a superpower available only from the host app, not from
464
+ * within vats, since `vatID` is merely a string and can be forged
465
+ * trivially. The host app is responsible for supplying the right
466
+ * vatID to kill, by looking at the database or logs (note that
467
+ * vats do not know their own vatID, and `controller.vatNameToID`
468
+ * only works for static vats, not dynamic).
469
+ *
470
+ * This will cause state changes in the swing-store (specifically
471
+ * marking the vat as terminated, and rejection all its
472
+ * outstanding promises), which must be committed before they will
473
+ * be durable. Either call `hostStorage.commit()` immediately
474
+ * after calling this, or call `controller.run()` and *then*
475
+ * `hostStorage.commit()` as you would normally do in response to
476
+ * other I/O or timer activity.
477
+ *
478
+ * The first `controller.run()` after this call will delete all
479
+ * the old vat's state at once, unless you use a
480
+ * [`runPolicy`](../docs/run-policy.md) to rate-limit cleanups.
481
+ *
482
+ * @param {VatID} vatID
483
+ * @param {SwingSetCapData} reasonCD
484
+ */
485
+
486
+ terminateVat(vatID, reasonCD) {
487
+ insistCapData(reasonCD);
488
+ assert(reasonCD.slots.length === 0, 'no slots allowed in reason');
489
+ kernel.terminateVatExternally(vatID, reasonCD);
490
+ },
444
491
  });
445
492
 
446
493
  writeSlogObject({ type: 'kernel-init-finish' });
@@ -1,22 +1,40 @@
1
1
  /* eslint-disable no-use-before-define */
2
2
 
3
+ import { assert, Fail } from '@endo/errors';
3
4
  import { makeMarshal } from '@endo/marshal';
4
5
  import { Far } from '@endo/far';
5
- import { assert, Fail } from '@agoric/assert';
6
6
  import { kser, kunser } from '@agoric/kmarshal';
7
7
  import { assertKnownOptions } from '../lib/assertOptions.js';
8
8
  import { insistVatID } from '../lib/id.js';
9
9
  import { makeVatSlot } from '../lib/parseVatSlots.js';
10
10
  import { insistStorageAPI } from '../lib/storageAPI.js';
11
11
  import { makeVatOptionRecorder } from '../lib/recordVatOptions.js';
12
- import makeKernelKeeper from '../kernel/state/kernelKeeper.js';
12
+ import makeKernelKeeper, {
13
+ DEFAULT_DELIVERIES_PER_BOYD,
14
+ DEFAULT_GC_KREFS_PER_BOYD,
15
+ } from '../kernel/state/kernelKeeper.js';
13
16
  import { exportRootObject } from '../kernel/kernel.js';
14
17
  import { makeKernelQueueHandler } from '../kernel/kernelQueue.js';
15
18
 
19
+ /**
20
+ * @typedef { import('../types-external.js').SwingSetKernelConfig } SwingSetKernelConfig
21
+ * @typedef { import('../types-external.js').SwingStoreKernelStorage } SwingStoreKernelStorage
22
+ * @typedef { import('../types-internal.js').InternalKernelOptions } InternalKernelOptions
23
+ * @typedef { import('../types-internal.js').ReapDirtThreshold } ReapDirtThreshold
24
+ */
25
+
16
26
  function makeVatRootObjectSlot() {
17
27
  return makeVatSlot('object', true, 0);
18
28
  }
19
29
 
30
+ /**
31
+ * @param {SwingSetKernelConfig} config
32
+ * @param {SwingStoreKernelStorage} kernelStorage
33
+ * @param {*} [options]
34
+ * @returns {Promise<string | undefined>} KPID of the bootstrap message
35
+ * result promise
36
+ */
37
+
20
38
  export async function initializeKernel(config, kernelStorage, options = {}) {
21
39
  const {
22
40
  verbose = false,
@@ -25,22 +43,27 @@ export async function initializeKernel(config, kernelStorage, options = {}) {
25
43
  const logStartup = verbose ? console.debug : () => 0;
26
44
  insistStorageAPI(kernelStorage.kvStore);
27
45
 
28
- const kernelSlog = null;
29
- const kernelKeeper = makeKernelKeeper(kernelStorage, kernelSlog);
46
+ const kernelKeeper = makeKernelKeeper(kernelStorage, 'uninitialized');
30
47
  const optionRecorder = makeVatOptionRecorder(kernelKeeper, bundleHandler);
31
48
 
32
- const wasInitialized = kernelKeeper.getInitialized();
33
- assert(!wasInitialized);
34
49
  const {
35
50
  defaultManagerType,
36
- defaultReapInterval,
51
+ defaultReapInterval = DEFAULT_DELIVERIES_PER_BOYD,
52
+ defaultReapGCKrefs = DEFAULT_GC_KREFS_PER_BOYD,
37
53
  relaxDurabilityRules,
38
54
  snapshotInitial,
39
55
  snapshotInterval,
40
56
  } = config;
57
+ /** @type { ReapDirtThreshold } */
58
+ const defaultReapDirtThreshold = {
59
+ deliveries: defaultReapInterval,
60
+ gcKrefs: defaultReapGCKrefs,
61
+ computrons: 'never', // TODO no knob?
62
+ };
63
+ /** @type { InternalKernelOptions } */
41
64
  const kernelOptions = {
42
65
  defaultManagerType,
43
- defaultReapInterval,
66
+ defaultReapDirtThreshold,
44
67
  relaxDurabilityRules,
45
68
  snapshotInitial,
46
69
  snapshotInterval,
@@ -49,7 +72,7 @@ export async function initializeKernel(config, kernelStorage, options = {}) {
49
72
 
50
73
  for (const id of Object.keys(config.idToBundle || {})) {
51
74
  const bundle = config.idToBundle[id];
52
- assert.equal(bundle.moduleFormat, 'endoZipBase64');
75
+ assert(bundle.moduleFormat === 'endoZipBase64');
53
76
  if (!kernelKeeper.hasBundle(id)) {
54
77
  kernelKeeper.addBundle(id, bundle);
55
78
  }
@@ -64,7 +87,7 @@ export async function initializeKernel(config, kernelStorage, options = {}) {
64
87
 
65
88
  // generate the genesis vats
66
89
  await null;
67
- if (config.vats) {
90
+ if (config.vats && Object.keys(config.vats).length) {
68
91
  for (const name of Object.keys(config.vats)) {
69
92
  const {
70
93
  bundleID,
@@ -86,6 +109,8 @@ export async function initializeKernel(config, kernelStorage, options = {}) {
86
109
  'useTranscript',
87
110
  'critical',
88
111
  'reapInterval',
112
+ 'reapGCKrefs',
113
+ 'neverReap',
89
114
  'nodeOptions',
90
115
  ]);
91
116
  const vatID = kernelKeeper.allocateVatIDForNameIfNeeded(name);
@@ -2,7 +2,7 @@
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
4
 
5
- import { assert, Fail } from '@agoric/assert';
5
+ import { assert, Fail } from '@endo/errors';
6
6
  import { makeTracer } from '@agoric/internal';
7
7
  import { mustMatch } from '@agoric/store';
8
8
  import bundleSource from '@endo/bundle-source';
@@ -256,7 +256,10 @@ export async function loadSwingsetConfigFile(configPath) {
256
256
  }
257
257
 
258
258
  export function swingsetIsInitialized(kernelStorage) {
259
- return !!kernelStorage.kvStore.get('initialized');
259
+ return !!(
260
+ kernelStorage.kvStore.get('version') ||
261
+ kernelStorage.kvStore.get('initialized')
262
+ );
260
263
  }
261
264
 
262
265
  /**
@@ -397,7 +400,7 @@ export async function initializeSwingset(
397
400
  enableSetup: true,
398
401
  managerType: 'local',
399
402
  useTranscript: false,
400
- reapInterval: 'never',
403
+ neverReap: true,
401
404
  },
402
405
  };
403
406
  }
@@ -1,5 +1,5 @@
1
1
  import path from 'path';
2
- import { Fail } from '@agoric/assert';
2
+ import { Fail } from '@endo/errors';
3
3
  import { type as osType } from 'os';
4
4
  import { xsnap, recordXSnap } from '@agoric/xsnap';
5
5
 
@@ -0,0 +1,212 @@
1
+ import {
2
+ DEFAULT_REAP_DIRT_THRESHOLD_KEY,
3
+ DEFAULT_GC_KREFS_PER_BOYD,
4
+ getAllDynamicVats,
5
+ getAllStaticVats,
6
+ } from '../kernel/state/kernelKeeper.js';
7
+
8
+ const upgradeVatV0toV1 = (kvStore, defaultReapDirtThreshold, vatID) => {
9
+ // This is called, once per vat, when upgradeSwingset migrates from
10
+ // v0 to v1
11
+
12
+ // schema v0:
13
+ // Each vat has a `vNN.reapInterval` and `vNN.reapCountdown`.
14
+ // vNN.options has a `.reapInterval` property (however it was not
15
+ // updated by processChangeVatOptions). Either all are numbers, or
16
+ // all are 'never'.
17
+
18
+ const oldReapIntervalKey = `${vatID}.reapInterval`;
19
+ const oldReapCountdownKey = `${vatID}.reapCountdown`;
20
+ const vatOptionsKey = `${vatID}.options`;
21
+
22
+ // schema v1:
23
+ // Each vat has a `vNN.reapDirt`, and vNN.options has a
24
+ // `.reapDirtThreshold` property (which overrides kernel-wide
25
+ // `defaultReapDirtThreshold`)
26
+
27
+ const reapDirtKey = `${vatID}.reapDirt`;
28
+
29
+ assert(kvStore.has(oldReapIntervalKey), oldReapIntervalKey);
30
+ assert(kvStore.has(oldReapCountdownKey), oldReapCountdownKey);
31
+ assert(!kvStore.has(reapDirtKey), reapDirtKey);
32
+
33
+ const reapIntervalString = kvStore.get(oldReapIntervalKey);
34
+ const reapCountdownString = kvStore.get(oldReapCountdownKey);
35
+ assert(reapIntervalString !== undefined);
36
+ assert(reapCountdownString !== undefined);
37
+
38
+ const intervalIsNever = reapIntervalString === 'never';
39
+ const countdownIsNever = reapCountdownString === 'never';
40
+ // these were supposed to be the same
41
+ assert(
42
+ intervalIsNever === countdownIsNever,
43
+ `reapInterval=${reapIntervalString}, reapCountdown=${reapCountdownString}`,
44
+ );
45
+
46
+ // initialize or upgrade state
47
+ const reapDirt = {}; // all missing keys are treated as zero
48
+ const threshold = {};
49
+
50
+ if (intervalIsNever) {
51
+ // old vats that were never reaped (eg comms) used
52
+ // reapInterval='never', so respect that and set the other
53
+ // threshold values to never as well
54
+ threshold.never = true;
55
+ } else {
56
+ // deduce delivery count from old countdown values
57
+ const reapInterval = Number.parseInt(reapIntervalString, 10);
58
+ const reapCountdown = Number.parseInt(reapCountdownString, 10);
59
+ const deliveries = reapInterval - reapCountdown;
60
+ reapDirt.deliveries = Math.max(deliveries, 0); // just in case
61
+ if (reapInterval !== defaultReapDirtThreshold.deliveries) {
62
+ threshold.deliveries = reapInterval;
63
+ }
64
+ }
65
+
66
+ kvStore.delete(oldReapIntervalKey);
67
+ kvStore.delete(oldReapCountdownKey);
68
+ kvStore.set(reapDirtKey, JSON.stringify(reapDirt));
69
+
70
+ // Update options to use the new schema.
71
+ const options = JSON.parse(kvStore.get(vatOptionsKey));
72
+ delete options.reapInterval;
73
+ options.reapDirtThreshold = threshold;
74
+ kvStore.set(vatOptionsKey, JSON.stringify(options));
75
+ };
76
+
77
+ /**
78
+ * (maybe) upgrade the kernel state to the current schema
79
+ *
80
+ * This function is responsible for bringing the kernel's portion of
81
+ * swing-store (kernelStorage) up to the current version. The host app
82
+ * must call this each time it launches with a new version of
83
+ * swingset, before using makeSwingsetController() to build the
84
+ * kernel/controller (which will throw an error if handed an old
85
+ * database). It is ok to call it only on those reboots, but it is
86
+ * also safe to call on every reboot, because upgradeSwingset() is a
87
+ * no-op if the DB is already up-to-date.
88
+ *
89
+ * If an upgrade is needed, this function will modify the DB state, so
90
+ * the host app must be prepared for export-data callbacks being
91
+ * called during the upgrade, and it is responsible for doing a
92
+ * `hostStorage.commit()` afterwards.
93
+ *
94
+ * @param {SwingStoreKernelStorage} kernelStorage
95
+ * @returns {boolean} true if any changes were made
96
+ */
97
+ export const upgradeSwingset = kernelStorage => {
98
+ const { kvStore } = kernelStorage;
99
+ let modified = false;
100
+ let vstring = kvStore.get('version');
101
+ if (vstring === undefined) {
102
+ vstring = '0';
103
+ }
104
+ let version = Number(vstring);
105
+
106
+ /**
107
+ * @param {string} key
108
+ * @returns {string}
109
+ */
110
+ function getRequired(key) {
111
+ if (!kvStore.has(key)) {
112
+ throw Error(`storage lacks required key ${key}`);
113
+ }
114
+ // @ts-expect-error already checked .has()
115
+ return kvStore.get(key);
116
+ }
117
+
118
+ // kernelKeeper.js has a large comment that defines our current
119
+ // kvStore schema, with a section describing the deltas. The upgrade
120
+ // steps applied here must match.
121
+
122
+ // schema v0:
123
+ //
124
+ // The kernel overall has `kernel.defaultReapInterval` and
125
+ // `kernel.initialized = 'true'`.
126
+ //
127
+ // Each vat has a `vNN.reapInterval` and `vNN.reapCountdown`.
128
+ // vNN.options has a `.reapInterval` property (however it was not
129
+ // updated by processChangeVatOptions, so do not rely upon its
130
+ // value). Either all are numbers, or all are 'never'.
131
+
132
+ if (version < 1) {
133
+ // schema v1:
134
+ //
135
+ // The kernel overall has `kernel.defaultReapDirtThreshold` and
136
+ // `kernel.version = '1'` (instead of .initialized).
137
+ //
138
+ // Each vat has a `vNN.reapDirt`, and vNN.options has a
139
+ // `.reapDirtThreshold` property
140
+
141
+ // So:
142
+ // * replace `kernel.initialized` with `kernel.version`
143
+ // * replace `kernel.defaultReapInterval` with
144
+ // `kernel.defaultReapDirtThreshold`
145
+ // * replace vat's `vNN.reapInterval`/`vNN.reapCountdown` with
146
+ // `vNN.reapDirt` and a `vNN.reapDirtThreshold` in `vNN.options`
147
+ // * then do per-vat upgrades with upgradeVatV0toV1
148
+
149
+ assert(kvStore.has('initialized'));
150
+ kvStore.delete('initialized');
151
+ // 'version' will be set at the end
152
+
153
+ // upgrade from old kernel.defaultReapInterval
154
+
155
+ const oldDefaultReapIntervalKey = 'kernel.defaultReapInterval';
156
+ assert(kvStore.has(oldDefaultReapIntervalKey));
157
+ assert(!kvStore.has(DEFAULT_REAP_DIRT_THRESHOLD_KEY));
158
+
159
+ /**
160
+ * @typedef { import('../types-internal.js').ReapDirtThreshold } ReapDirtThreshold
161
+ */
162
+
163
+ /** @type ReapDirtThreshold */
164
+ const threshold = {
165
+ deliveries: 'never',
166
+ gcKrefs: 'never',
167
+ computrons: 'never',
168
+ };
169
+
170
+ const oldValue = getRequired(oldDefaultReapIntervalKey);
171
+ if (oldValue !== 'never') {
172
+ const value = Number.parseInt(oldValue, 10);
173
+ assert.typeof(value, 'number');
174
+ threshold.deliveries = value;
175
+ // if BOYD wasn't turned off entirely (eg
176
+ // defaultReapInterval='never', which only happens in unit
177
+ // tests), then pretend we wanted a gcKrefs= threshold all
178
+ // along, so all vats get a retroactive gcKrefs threshold, which
179
+ // we need for the upcoming slow-vat-deletion to not trigger
180
+ // gigantic BOYD and break the kernel
181
+ threshold.gcKrefs = DEFAULT_GC_KREFS_PER_BOYD;
182
+ }
183
+ harden(threshold);
184
+ kvStore.set(DEFAULT_REAP_DIRT_THRESHOLD_KEY, JSON.stringify(threshold));
185
+ kvStore.delete(oldDefaultReapIntervalKey);
186
+
187
+ // now upgrade all vats
188
+ for (const [_name, vatID] of getAllStaticVats(kvStore)) {
189
+ upgradeVatV0toV1(kvStore, threshold, vatID);
190
+ }
191
+ for (const vatID of getAllDynamicVats(getRequired)) {
192
+ upgradeVatV0toV1(kvStore, threshold, vatID);
193
+ }
194
+
195
+ modified = true;
196
+ version = 1;
197
+ }
198
+
199
+ if (version < 2) {
200
+ // schema v2: add vats.terminated = []
201
+ assert(!kvStore.has('vats.terminated'));
202
+ kvStore.set('vats.terminated', JSON.stringify([]));
203
+ modified = true;
204
+ version = 2;
205
+ }
206
+
207
+ if (modified) {
208
+ kvStore.set('version', `${version}`);
209
+ }
210
+ return modified;
211
+ };
212
+ harden(upgradeSwingset);
@@ -1,4 +1,4 @@
1
- import { Fail } from '@agoric/assert';
1
+ import { Fail } from '@endo/errors';
2
2
  import { Far } from '@endo/far';
3
3
 
4
4
  function sanitize(data) {
@@ -1,4 +1,4 @@
1
- import { assert } from '@agoric/assert';
1
+ import { assert } from '@endo/errors';
2
2
  import { buildSerializationTools } from '../lib/deviceTools.js';
3
3
 
4
4
  /*
@@ -1,8 +1,7 @@
1
+ import { Fail } from '@endo/errors';
1
2
  import { makePromiseKit } from '@endo/promise-kit';
2
3
  import { Nat } from '@endo/nat';
3
4
 
4
- import { Fail } from '@agoric/assert';
5
-
6
5
  export default function buildCommand(broadcastCallback) {
7
6
  broadcastCallback || Fail`broadcastCallback must be provided.`;
8
7
  let inboundCallback;
@@ -1,8 +1,7 @@
1
+ import { Fail } from '@endo/errors';
1
2
  import { Nat } from '@endo/nat';
2
3
  import { Far } from '@endo/far';
3
4
 
4
- import { Fail } from '@agoric/assert';
5
-
6
5
  export function buildRootDeviceNode(tools) {
7
6
  const { SO, getDeviceState, setDeviceState, endowments } = tools;
8
7
  const { registerInboundCallback, deliverResponse, sendBroadcast } =
@@ -1,4 +1,4 @@
1
- import { assert, Fail } from '@agoric/assert';
1
+ import { assert, Fail } from '@endo/errors';
2
2
  import { makeMarshal } from '@endo/marshal';
3
3
  import { Far } from '@endo/far';
4
4
  import { parseVatSlot } from '../../lib/parseVatSlots.js';
@@ -1,4 +1,4 @@
1
- import { Fail } from '@agoric/assert';
1
+ import { Fail } from '@endo/errors';
2
2
  import { Far } from '@endo/far';
3
3
 
4
4
  export function buildRootDeviceNode(tools) {
@@ -1,4 +1,4 @@
1
- import { Fail } from '@agoric/assert';
1
+ import { Fail } from '@endo/errors';
2
2
 
3
3
  /*
4
4
  * The "loopbox" is a special device used for unit tests, which glues one
@@ -1,8 +1,7 @@
1
+ import { assert, Fail } from '@endo/errors';
1
2
  import { Nat } from '@endo/nat';
2
3
  import { Far } from '@endo/far';
3
4
 
4
- import { assert, Fail } from '@agoric/assert';
5
-
6
5
  export function buildRootDeviceNode(tools) {
7
6
  const { SO, getDeviceState, setDeviceState, endowments } = tools;
8
7
 
@@ -64,10 +64,9 @@
64
64
 
65
65
  */
66
66
 
67
+ import { Fail } from '@endo/errors';
67
68
  import { Nat } from '@endo/nat';
68
69
 
69
- import { Fail } from '@agoric/assert';
70
-
71
70
  // This Map-based mailboxState object is a good starting point, but we may
72
71
  // replace it with one that tracks which parts of the state have been
73
72
  // modified, to build more efficient Merkle proofs.
@@ -1,6 +1,6 @@
1
+ import { Fail } from '@endo/errors';
1
2
  import { makeCapTP } from '@endo/captp';
2
3
  import { Far } from '@endo/far';
3
- import { Fail } from '@agoric/assert';
4
4
 
5
5
  export function buildRootDeviceNode(tools) {
6
6
  const { SO, getDeviceState, setDeviceState, endowments } = tools;
@@ -23,7 +23,7 @@
23
23
  */
24
24
 
25
25
  import { Nat } from '@endo/nat';
26
- import { assert, Fail } from '@agoric/assert';
26
+ import { assert, Fail } from '@endo/errors';
27
27
  import { Far } from '@endo/far';
28
28
 
29
29
  // Since we use harden when saving the state, we need to copy the arrays so they
@@ -1,6 +1,6 @@
1
1
  import { Nat } from '@endo/nat';
2
2
 
3
- import { Fail } from '@agoric/assert';
3
+ import { Fail } from '@endo/errors';
4
4
 
5
5
  /**
6
6
  * Endowments for a Timer device that can be made available to SwingSet vats.
@@ -1,5 +1,5 @@
1
1
  import { Nat } from '@endo/nat';
2
- import { assert } from '@agoric/assert';
2
+ import { assert } from '@endo/errors';
3
3
  import { kunser } from '@agoric/kmarshal';
4
4
  import { buildSerializationTools } from '../lib/deviceTools.js';
5
5
  import { insistVatID } from '../../lib/id.js';
@@ -82,6 +82,7 @@ bundleID before submitting to the kernel), or (temporarily) a full bundle.
82
82
  * @typedef { string } VatID
83
83
  * @typedef { string } UpgradeID
84
84
  * @typedef {{
85
+ * changeOptions: (vatID: string, options: {}) => void;
85
86
  * createMeter: (remaining: bigint, threshold: bigint) => MeterID
86
87
  * createUnlimitedMeter: () => MeterID
87
88
  * addMeterRemaining: (meterID: MeterID, delta: bigint) => void
@@ -89,7 +90,8 @@ bundleID before submitting to the kernel), or (temporarily) a full bundle.
89
90
  * getMeter: (meterID: MeterID) => { remaining: bigint, threshold: bigint }
90
91
  * createByBundle: (bundle: Bundle, options: {}) => VatID
91
92
  * createByBundleID: (bundleID: BundleID, options: {}) => VatID
92
- * upgradeVat: (bundleID: BundleID, vatParameters: {}) => UpgradeID
93
+ * getBundleIDByName: (name: string) => string;
94
+ * upgradeVat: (vatID: string, bundleID: BundleID, _vatParameters: unknown, upgradeMessage: string) => UpgradeID;
93
95
  * terminateWithFailure: (vatID: VatID, reason: {}) => void
94
96
  * getBundleCap: (bundleID: BundleID) => BundleCap
95
97
  * getNamedBundleCap: (name: string) => BundleCap