Skip to content

Commit

Permalink
fix(swingset): startVat(vatParameters) are now capdata
Browse files Browse the repository at this point in the history
The `startVat()` message accepts "vat parameters", but previously these were
arbitrary (inert) data. This changes the argument to contain capdata.
Liveslots will `unserialize` this data into the `vatParameters` argument
given to `buildRootObject()`.

The kernel was updated to populate this field with capdata in all pathways
that create create/start/upgrade-vat events. Parameters passed in through
config (which must be inert data) are serialized into capdata.

Parameters passed through `E(vatAdminService).createVat(bundle, {
vatParameters })` are also treated as inert data and serialized into capdata,
however when we move to "device hooks", this will change, and dynamic vat
creators will be able to pass object references in those parameters.

refs #4381
  • Loading branch information
warner committed Mar 18, 2022
1 parent 5252f78 commit 0d273c9
Show file tree
Hide file tree
Showing 15 changed files with 76 additions and 52 deletions.
5 changes: 3 additions & 2 deletions packages/SwingSet/src/controller/initializeKernel.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable no-use-before-define */

import { makeMarshal, Far } from '@endo/marshal';
import { makeMarshal, Far, stringify } from '@endo/marshal';
import { assert, details as X } from '@agoric/assert';
import { createSHA256 } from '../lib-nodejs/hasher.js';
import { assertKnownOptions } from '../lib/assertOptions.js';
Expand Down Expand Up @@ -87,8 +87,9 @@ export function initializeKernel(config, hostStorage, verbose = false) {
const vatKeeper = kernelKeeper.provideVatKeeper(vatID);
vatKeeper.setSourceAndOptions({ bundleID }, creationOptions);
vatKeeper.initializeReapCountdown(creationOptions.reapInterval);
const vpCapData = { body: stringify(harden(vatParameters)), slots: [] };
kernelKeeper.addToAcceptanceQueue(
harden({ type: 'startVat', vatID, vatParameters }),
harden({ type: 'startVat', vatID, vatParameters: vpCapData }),
);
if (name === 'vatAdmin') {
// Create a kref for the vatAdmin root, so the kernel can tell it
Expand Down
33 changes: 23 additions & 10 deletions packages/SwingSet/src/kernel/kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -529,10 +529,11 @@ export default function buildKernel(
const { vatID, vatParameters } = message;
// console.log(`-- processStartVat(${vatID})`);
insistVatID(vatID);
insistCapData(vatParameters);
// eslint-disable-next-line no-use-before-define
assert(vatWarehouse.lookup(vatID));
/** @type { KernelDeliveryStartVat } */
const kd = harden(['startVat', vatParameters]); // TODO(4381) add vatParameters here
const kd = harden(['startVat', vatParameters]);
// eslint-disable-next-line no-use-before-define
const vd = vatWarehouse.kernelDeliveryToVatDelivery(vatID, kd);
// TODO: can we provide a computron count to the run policy?
Expand All @@ -548,6 +549,7 @@ export default function buildKernel(
async function processCreateVat(message) {
assert(vatAdminRootKref, `initializeKernel did not set vatAdminRootKref`);
const { vatID, source, vatParameters, dynamicOptions } = message;
insistCapData(vatParameters);
kernelKeeper.addDynamicVatID(vatID);
const vatKeeper = kernelKeeper.provideVatKeeper(vatID);
const options = { ...dynamicOptions };
Expand Down Expand Up @@ -602,7 +604,6 @@ export default function buildKernel(
.then(_vatinfo =>
processStartVat({ type: 'startVat', vatID, vatParameters }),
)
// TODO(4381) add vatParameters here
// If processStartVat/deliverAndLogToVat observes a worker error, it
// will return status={ terminate: problem } rather than throw an
// error, so makeSuccessResponse will sendNewVatCallback. But the
Expand All @@ -623,7 +624,8 @@ export default function buildKernel(
async function processUpgradeVat(message) {
assert(vatAdminRootKref, `initializeKernel did not set vatAdminRootKref`);
// const { upgradeID, bundleID, vatParameters } = message;
const { upgradeID } = message;
const { upgradeID, vatParameters } = message;
insistCapData(vatParameters);
// for now, all attempts to upgrade will fail

// TODO: decref the bundleID and vatParameters.slots
Expand Down Expand Up @@ -775,7 +777,7 @@ export default function buildKernel(
* } RunQueueEventCreateVat
* @typedef { { type: 'upgrade-vat', vatID: VatID, upgradeID: string,
* bundleID: BundleID, vatParameters: SwingSetCapData } } RunQueueEventUpgradeVat
* @typedef { { type: 'startVat', vatID: VatID, vatParameters: unknown } } RunQueueEventStartVat
* @typedef { { type: 'startVat', vatID: VatID, vatParameters: SwingSetCapData } } RunQueueEventStartVat
* @typedef { { type: 'dropExports', vatID: VatID, krefs: string[] } } RunQueueEventDropExports
* @typedef { { type: 'retireExports', vatID: VatID, krefs: string[] } } RunQueueEventRetireExports
* @typedef { { type: 'retireImports', vatID: VatID, krefs: string[] } } RunQueueEventRetireImports
Expand Down Expand Up @@ -1220,8 +1222,13 @@ export default function buildKernel(

await vatWarehouse.loadTestVat(vatID, setup, creationOptions);

const vpCapData = { body: stringify(harden(vatParameters)), slots: [] };
/** @type { RunQueueEventStartVat } */
const startVatMessage = { type: 'startVat', vatID, vatParameters };
const startVatMessage = {
type: 'startVat',
vatID,
vatParameters: vpCapData,
};
// eslint-disable-next-line no-unused-vars
const ds = await processStartVat(startVatMessage);
// TODO: do something with DeliveryStatus, maybe just assert it's ok
Expand All @@ -1246,9 +1253,11 @@ export default function buildKernel(
pushCreateVatBundleEvent(bundle, dynamicOptions) {
// TODO: translate dynamicOptions.vatParameters.slots from dref to kref
const source = { bundle };
const vatID = kernelKeeper.allocateUnusedVatID();
const { vatParameters, ...rest } = dynamicOptions;
const { vatParameters: rawVP, ...rest } = dynamicOptions;
const vatParameters = { body: stringify(harden(rawVP)), slots: [] };
insistCapData(vatParameters);
dynamicOptions = rest;
const vatID = kernelKeeper.allocateUnusedVatID();
const event = {
type: 'create-vat',
vatID,
Expand All @@ -1265,9 +1274,11 @@ export default function buildKernel(
assert(kernelKeeper.hasBundle(bundleID), bundleID);
// TODO: translate dynamicOptions.vatParameters.slots from dref to kref
const source = { bundleID };
const vatID = kernelKeeper.allocateUnusedVatID();
const { vatParameters, ...rest } = dynamicOptions;
const { vatParameters: rawVP, ...rest } = dynamicOptions;
const vatParameters = { body: stringify(harden(rawVP)), slots: [] };
insistCapData(vatParameters);
dynamicOptions = rest;
const vatID = kernelKeeper.allocateUnusedVatID();
const event = {
type: 'create-vat',
vatID,
Expand All @@ -1280,7 +1291,9 @@ export default function buildKernel(
// later when it is created and a root object is available
return vatID;
},
pushUpgradeVatEvent(bundleID, vatParameters) {
pushUpgradeVatEvent(bundleID, rawVP) {
const vatParameters = { body: stringify(harden(rawVP)), slots: [] };
insistCapData(vatParameters);
const upgradeID = kernelKeeper.allocateUpgradeID();
// TODO: translate vatParameters.slots from dref to kref
// TODO: incref both bundleID and slots in vatParameters
Expand Down
2 changes: 1 addition & 1 deletion packages/SwingSet/src/kernel/vatTranslator.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ function makeTranslateKernelDeliveryToVatDelivery(vatID, kernelKeeper) {

/**
*
* @param {unknown} kernelVP
* @param {SwingSetCapData} kernelVP
* @returns { VatDeliveryStartVat }
*/
function translateStartVat(kernelVP) {
Expand Down
5 changes: 3 additions & 2 deletions packages/SwingSet/src/lib/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ export function insistVatDeliveryObject(vdo) {
break;
}
case 'startVat': {
const [_vatParameters] = rest;
// TODO: insistCapData(vatParameters);
assert(rest.length === 1);
const [vatParameters] = rest;
insistCapData(vatParameters);
break;
}
case 'bringOutYourDead': {
Expand Down
9 changes: 5 additions & 4 deletions packages/SwingSet/src/liveslots/liveslots.js
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,8 @@ function build(
assert(key.match(/^[-\w.+/]+$/), X`invalid vatstore key`);
}

async function startVat(vatParameters) {
async function startVat(vatParametersCapData) {
insistCapData(vatParametersCapData);
assert(!didStartVat);
didStartVat = true;

Expand Down Expand Up @@ -1162,7 +1163,7 @@ function build(
});
}

// TODO: unserialize(vatParameters)
const vatParameters = m.unserialize(vatParametersCapData);

// Below this point, user-provided code might crash or overrun a meter, so
// any prior-to-user-code setup that can be done without reference to the
Expand Down Expand Up @@ -1235,8 +1236,8 @@ function build(
break;
}
case 'startVat': {
const [vatParameters] = args;
result = startVat(vatParameters);
const [vpCapData] = args;
result = startVat(vpCapData);
break;
}
default:
Expand Down
4 changes: 2 additions & 2 deletions packages/SwingSet/src/types-external.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export {};
* @typedef { [tag: 'dropExports', vrefs: string[] ]} VatDeliveryDropExports
* @typedef { [tag: 'retireExports', vrefs: string[] ]} VatDeliveryRetireExports
* @typedef { [tag: 'retireImports', vrefs: string[] ]} VatDeliveryRetireImports
* @typedef { [tag: 'startVat', vatParameters: unknown ]} VatDeliveryStartVat
* @typedef { [tag: 'startVat', vatParameters: SwingSetCapData ]} VatDeliveryStartVat
* @typedef { [tag: 'bringOutYourDead' ]} VatDeliveryBringOutYourDead
* @typedef { VatDeliveryMessage | VatDeliveryNotify | VatDeliveryDropExports
* | VatDeliveryRetireExports | VatDeliveryRetireImports
Expand Down Expand Up @@ -135,7 +135,7 @@ export {};
* @typedef { [tag: 'dropExports', krefs: string[] ]} KernelDeliveryDropExports
* @typedef { [tag: 'retireExports', krefs: string[] ]} KernelDeliveryRetireExports
* @typedef { [tag: 'retireImports', krefs: string[] ]} KernelDeliveryRetireImports
* @typedef { [tag: 'startVat', vatParameters: unknown ]} KernelDeliveryStartVat
* @typedef { [tag: 'startVat', vatParameters: SwingSetCapData ]} KernelDeliveryStartVat
* @typedef { [tag: 'bringOutYourDead']} KernelDeliveryBringOutYourDead
* @typedef { KernelDeliveryMessage | KernelDeliveryNotify | KernelDeliveryDropExports
* | KernelDeliveryRetireExports | KernelDeliveryRetireImports
Expand Down
6 changes: 5 additions & 1 deletion packages/SwingSet/src/vats/comms/dispatch.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { assert, details as X } from '@agoric/assert';
import { parse } from '@endo/marshal';
import { makeVatSlot } from '../../lib/parseVatSlots.js';
import { insistMessage } from '../../lib/message.js';
import { makeState } from './state.js';
Expand Down Expand Up @@ -45,7 +46,10 @@ export function buildCommsDispatch(syscall, _state, _helpers, _vatPowers) {
// our root object (o+0) is the Comms Controller
const controller = makeVatSlot('object', true, 0);

function doStartVat(vatParameters = {}) {
function doStartVat(vatParametersCapData) {
insistCapData(vatParametersCapData);
assert(vatParametersCapData.slots.length === 0, 'comms got slots');
const vatParameters = parse(vatParametersCapData.body) || {};
const { identifierBase = 0, sendExplicitSeqNums } = vatParameters;
state.initialize(controller, identifierBase);
if (sendExplicitSeqNums !== undefined) {
Expand Down
4 changes: 2 additions & 2 deletions packages/SwingSet/test/commsVatDriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { assert, details as X } from '@agoric/assert';
import buildCommsDispatch from '../src/vats/comms/index.js';
import { debugState } from '../src/vats/comms/dispatch.js';
import { flipRemoteSlot } from '../src/vats/comms/parseRemoteSlot.js';
import { makeMessage, makeResolutions } from './util.js';
import { capargs, makeMessage, makeResolutions } from './util.js';

// This module provides a power tool for testing the comms vat implementation.
// It provides support for injecting events into the comms vat and observing
Expand Down Expand Up @@ -350,7 +350,7 @@ export function commsVatDriver(t, verbose = false) {
const log = [];
const syscall = loggingSyscall(log);
const dispatch = buildCommsDispatch(syscall, 'fakestate', 'fakehelpers');
dispatch(['startVat']);
dispatch(['startVat', capargs()]);
const { state } = debugState.get(dispatch);

const remotes = new Map();
Expand Down
3 changes: 2 additions & 1 deletion packages/SwingSet/test/liveslots-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { waitUntilQuiescent } from '../src/lib-nodejs/waitUntilQuiescent.js';
import { makeGcAndFinalize } from '../src/lib-nodejs/gc-and-finalize.js';
import { makeDummyMeterControl } from '../src/kernel/dummyMeterControl.js';
import { makeLiveSlots } from '../src/liveslots/liveslots.js';
import { capargs } from './vat-util.js';

export function buildSyscall() {
const log = [];
Expand Down Expand Up @@ -131,7 +132,7 @@ export async function makeDispatch(
return { buildRootObject: build };
},
);
await startVat();
await startVat(capargs());
if (returnTestHooks) {
returnTestHooks[0] = testHooks;
}
Expand Down
11 changes: 6 additions & 5 deletions packages/SwingSet/test/test-comms.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { makeState } from '../src/vats/comms/state.js';
import { makeCListKit } from '../src/vats/comms/clist.js';
import { debugState } from '../src/vats/comms/dispatch.js';
import {
capargs,
makeMessage,
makeDropExports,
makeRetireExports,
Expand Down Expand Up @@ -127,7 +128,7 @@ test('transmit', t => {
// remote 'bob' on machine B
const { syscall, sends } = mockSyscall();
const dispatch = buildCommsDispatch(syscall, 'fakestate', 'fakehelpers');
dispatch(['startVat']);
dispatch(['startVat', capargs()]);
const { state, clistKit } = debugState.get(dispatch);
const {
provideKernelForLocal,
Expand Down Expand Up @@ -202,7 +203,7 @@ test('receive', t => {
// vat's object 'bob'
const { syscall, sends, gcs } = mockSyscall();
const dispatch = buildCommsDispatch(syscall, 'fakestate', 'fakehelpers');
dispatch(['startVat']);
dispatch(['startVat', capargs()]);
const { state, clistKit } = debugState.get(dispatch);
const {
provideLocalForKernel,
Expand Down Expand Up @@ -348,7 +349,7 @@ test('receive', t => {
test('addEgress', t => {
const { syscall } = mockSyscall();
const dispatch = buildCommsDispatch(syscall, 'fakestate', 'fakehelpers');
dispatch(['startVat']);
dispatch(['startVat', capargs()]);
const { state, clistKit } = debugState.get(dispatch);
const { getLocalForKernel, getRemoteForLocal } = clistKit;
const transmitterID = 'o-1';
Expand Down Expand Up @@ -381,7 +382,7 @@ test('addEgress', t => {
test('addIngress', t => {
const { syscall, resolves } = mockSyscall();
const dispatch = buildCommsDispatch(syscall, 'fakestate', 'fakehelpers');
dispatch(['startVat']);
dispatch(['startVat', capargs()]);
const { state, clistKit } = debugState.get(dispatch);
const { getLocalForKernel, getRemoteForLocal } = clistKit;
const transmitterID = 'o-1';
Expand Down Expand Up @@ -415,7 +416,7 @@ test('comms gc', t => {
// about various objects that are dropped and retired
const { syscall, sends, gcs } = mockSyscall();
const dispatch = buildCommsDispatch(syscall, 'fakestate', 'fakehelpers');
dispatch(['startVat']);
dispatch(['startVat', capargs()]);
const { state, clistKit: ck } = debugState.get(dispatch);
const transmitterID = 'o-1'; // vat-tp target for B
const { remoteID, receiverID } = state.addRemote('B', transmitterID);
Expand Down
30 changes: 14 additions & 16 deletions packages/SwingSet/test/test-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@ import {
initializeSwingset,
makeSwingsetController,
} from '../src/index.js';
import { checkKT } from './util.js';
import { checkKT, capdata, capargs } from './util.js';

function capdata(body, slots = []) {
return harden({ body, slots });
}
const emptyVP = capargs({});

function removeTriple(arr, a, b, c) {
for (let i = 0; i < arr.length; i += 1) {
Expand Down Expand Up @@ -69,11 +67,11 @@ async function simpleCall(t) {
controller.queueToVatRoot('vat1', 'foo', capdata('args'));
t.deepEqual(controller.dump().runQueue, []);
t.deepEqual(controller.dump().acceptanceQueue, [
{ type: 'startVat', vatID: 'v1', vatParameters: {} },
{ type: 'startVat', vatID: 'v2', vatParameters: {} },
{ type: 'startVat', vatID: 'v3', vatParameters: {} },
{ type: 'startVat', vatID: 'v4', vatParameters: {} },
{ type: 'startVat', vatID: 'v5', vatParameters: {} },
{ type: 'startVat', vatID: 'v1', vatParameters: emptyVP },
{ type: 'startVat', vatID: 'v2', vatParameters: emptyVP },
{ type: 'startVat', vatID: 'v3', vatParameters: emptyVP },
{ type: 'startVat', vatID: 'v4', vatParameters: emptyVP },
{ type: 'startVat', vatID: 'v5', vatParameters: emptyVP },
{
msg: {
method: 'foo',
Expand Down Expand Up @@ -222,13 +220,13 @@ test.serial('bootstrap export', async t => {

t.deepEqual(c.dump().runQueue, []);
t.deepEqual(c.dump().acceptanceQueue, [
{ type: 'startVat', vatID: 'v1', vatParameters: {} },
{ type: 'startVat', vatID: 'v2', vatParameters: {} },
{ type: 'startVat', vatID: 'v3', vatParameters: { argv: [] } },
{ type: 'startVat', vatID: 'v4', vatParameters: {} },
{ type: 'startVat', vatID: 'v5', vatParameters: {} },
{ type: 'startVat', vatID: 'v6', vatParameters: {} },
{ type: 'startVat', vatID: 'v7', vatParameters: {} },
{ type: 'startVat', vatID: 'v1', vatParameters: emptyVP },
{ type: 'startVat', vatID: 'v2', vatParameters: emptyVP },
{ type: 'startVat', vatID: 'v3', vatParameters: capargs({ argv: [] }) },
{ type: 'startVat', vatID: 'v4', vatParameters: emptyVP },
{ type: 'startVat', vatID: 'v5', vatParameters: emptyVP },
{ type: 'startVat', vatID: 'v6', vatParameters: emptyVP },
{ type: 'startVat', vatID: 'v7', vatParameters: emptyVP },
{
msg: {
result: 'kp40',
Expand Down
3 changes: 2 additions & 1 deletion packages/SwingSet/test/test-kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ function capargs(args, slots = []) {
}

const slot0arg = { '@qclass': 'slot', index: 0 };
const emptyVP = capargs({});

function oneResolution(promiseID, rejected, data) {
return [[promiseID, rejected, data]];
Expand Down Expand Up @@ -47,7 +48,7 @@ function makeKernel() {
return buildKernel(endowments, {}, {});
}

const tsv = [{ d: ['startVat', {}], syscalls: [] }];
const tsv = [{ d: ['startVat', emptyVP], syscalls: [] }];

test('build kernel', async t => {
const kernel = makeKernel();
Expand Down
4 changes: 2 additions & 2 deletions packages/SwingSet/test/test-liveslots.js
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ test('dropImports', async t => {
},
);
const { dispatch, startVat, possiblyDeadSet } = ls;
await startVat();
await startVat(capargs());
const allFRs = gcTools.getAllFRs();
t.is(allFRs.length, 2);
const FR = allFRs[0];
Expand Down Expand Up @@ -1095,7 +1095,7 @@ test('buildVatNamespace not called until after startVat', async t => {
() => ({ buildRootObject }),
);
t.falsy(buildCalled);
await ls.startVat();
await ls.startVat(capargs());
t.truthy(buildCalled);
});

Expand Down
2 changes: 1 addition & 1 deletion packages/SwingSet/test/test-xsnap-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ test('child termination distinguished from meter exhaustion', async t => {
schandler,
);

await m.deliver(['startVat']);
await m.deliver(['startVat', capargs()]);

const msg = { method: 'hang', args: capargs([]) };
/** @type { VatDeliveryObject } */
Expand Down
Loading

0 comments on commit 0d273c9

Please sign in to comment.