@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.
- package/README.md +1 -1
- package/package.json +31 -30
- package/src/controller/controller.js +48 -1
- package/src/controller/initializeKernel.js +35 -10
- package/src/controller/initializeSwingset.js +6 -3
- package/src/controller/startXSnap.js +1 -1
- package/src/controller/upgradeSwingset.js +212 -0
- package/src/devices/bridge/device-bridge.js +1 -1
- package/src/devices/bundle/device-bundle.js +1 -1
- package/src/devices/command/command.js +1 -2
- package/src/devices/command/device-command.js +1 -2
- package/src/devices/lib/deviceTools.js +1 -1
- package/src/devices/loopbox/device-loopbox.js +1 -1
- package/src/devices/loopbox/loopbox.js +1 -1
- package/src/devices/mailbox/device-mailbox.js +1 -2
- package/src/devices/mailbox/mailbox.js +1 -2
- package/src/devices/plugin/device-plugin.js +1 -1
- package/src/devices/timer/device-timer.js +1 -1
- package/src/devices/timer/timer.js +1 -1
- package/src/devices/vat-admin/device-vat-admin.js +4 -2
- package/src/index.js +1 -1
- package/src/kernel/deviceManager.js +1 -1
- package/src/kernel/deviceSlots.js +1 -1
- package/src/kernel/deviceTranslator.js +1 -1
- package/src/kernel/dummyMeterControl.js +1 -1
- package/src/kernel/gc-actions.js +55 -34
- package/src/kernel/kernel.js +216 -51
- package/src/kernel/kernelSyscall.js +2 -13
- package/src/kernel/parseKernelSlots.js +1 -1
- package/src/kernel/slogger.js +2 -2
- package/src/kernel/state/deviceKeeper.js +1 -1
- package/src/kernel/state/kernelKeeper.js +427 -81
- package/src/kernel/state/reachable.js +1 -1
- package/src/kernel/state/stats.js +1 -1
- package/src/kernel/state/storageHelper.js +1 -1
- package/src/kernel/state/vatKeeper.js +159 -44
- package/src/kernel/vat-admin-hooks.js +4 -1
- package/src/kernel/vat-loader/manager-factory.js +1 -2
- package/src/kernel/vat-loader/manager-helper.js +1 -1
- package/src/kernel/vat-loader/manager-local.js +1 -1
- package/src/kernel/vat-loader/manager-subprocess-node.js +1 -1
- package/src/kernel/vat-loader/manager-subprocess-xsnap.js +1 -1
- package/src/kernel/vat-loader/vat-loader.js +2 -2
- package/src/kernel/vat-warehouse.js +5 -1
- package/src/kernel/vatTranslator.js +1 -4
- package/src/lib/assertOptions.js +1 -1
- package/src/lib/capdata.js +1 -1
- package/src/lib/id.js +1 -1
- package/src/lib/message.js +1 -1
- package/src/lib/parseVatSlots.js +1 -1
- package/src/lib/recordVatOptions.js +18 -6
- package/src/lib/runPolicies.js +50 -4
- package/src/lib/storageAPI.js +1 -1
- package/src/lib/workerOptions.js +1 -1
- package/src/supervisors/subprocess-node/supervisor-subprocess-node.js +1 -1
- package/src/types-external.js +71 -22
- package/src/types-internal.js +56 -3
- package/src/vats/comms/clist-inbound.js +1 -1
- package/src/vats/comms/clist-kernel.js +1 -1
- package/src/vats/comms/clist-outbound.js +1 -1
- package/src/vats/comms/controller.js +1 -1
- package/src/vats/comms/delivery.js +1 -1
- package/src/vats/comms/dispatch.js +1 -1
- package/src/vats/comms/gc-comms.js +1 -1
- package/src/vats/comms/parseLocalSlots.js +1 -1
- package/src/vats/comms/parseRemoteSlot.js +1 -1
- package/src/vats/comms/remote.js +1 -1
- package/src/vats/comms/state.js +1 -1
- package/src/vats/timer/vat-timer.js +9 -9
- package/src/vats/vat-admin/vat-vat-admin.js +23 -8
- package/src/vats/vattp/vat-vattp.js +1 -1
- package/tools/bootstrap-relay.js +1 -3
- package/tools/bundleTool.js +9 -1
- package/tools/dvo-test-harness.js +1 -1
- package/tools/manual-timer.js +1 -1
- 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(
|
|
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-
|
|
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/
|
|
31
|
-
"@agoric/
|
|
32
|
-
"@agoric/
|
|
33
|
-
"@agoric/store": "0.9.
|
|
34
|
-
"@agoric/
|
|
35
|
-
"@agoric/swingset-
|
|
36
|
-
"@agoric/
|
|
37
|
-
"@agoric/
|
|
38
|
-
"@agoric/
|
|
39
|
-
"@agoric/xsnap": "0.14.
|
|
40
|
-
"@
|
|
41
|
-
"@endo/
|
|
42
|
-
"@endo/
|
|
43
|
-
"@endo/
|
|
44
|
-
"@endo/
|
|
45
|
-
"@endo/
|
|
46
|
-
"@endo/eventual-send": "^1.2.
|
|
47
|
-
"@endo/far": "^1.1.
|
|
48
|
-
"@endo/import-bundle": "^1.
|
|
49
|
-
"@endo/init": "^1.1.
|
|
50
|
-
"@endo/marshal": "^1.5.
|
|
51
|
-
"@endo/nat": "^5.0.
|
|
52
|
-
"@endo/
|
|
53
|
-
"@endo/
|
|
54
|
-
"@endo/
|
|
55
|
-
"@endo/
|
|
56
|
-
"@endo/
|
|
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.
|
|
104
|
+
"atLeast": 75.7
|
|
104
105
|
},
|
|
105
|
-
"gitHead": "
|
|
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 '@
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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 '@
|
|
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 !!
|
|
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
|
-
|
|
403
|
+
neverReap: true,
|
|
401
404
|
},
|
|
402
405
|
};
|
|
403
406
|
}
|
|
@@ -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,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,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 '@
|
|
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,5 +1,5 @@
|
|
|
1
1
|
import { Nat } from '@endo/nat';
|
|
2
|
-
import { assert } from '@
|
|
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
|
-
*
|
|
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
|