Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal to restart vat-admin #8595

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/SwingSet/src/controller/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,14 @@ export async function makeSwingsetController(
return kpid;
},

/**
*
* @param {string} vatName
* @param {boolean} shouldPauseFirst
* @param {string} bundleID
* @param {{upgradeMessage?: string}} options
* @returns {string | undefined}
*/
upgradeStaticVat(vatName, shouldPauseFirst, bundleID, options = {}) {
const vatID = kernel.vatNameToID(vatName);
let pauseTarget = null;
Expand Down
3 changes: 3 additions & 0 deletions packages/SwingSet/src/kernel/kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,18 +195,21 @@ export default function buildKernel(
testLog,
});

/** @type {(name: string) => string} */
function vatNameToID(name) {
const vatID = kernelKeeper.getVatIDForName(name);
insistVatID(vatID);
return vatID;
}

/** @type {(name: string) => string} */
function deviceNameToID(name) {
const deviceID = kernelKeeper.getDeviceIDForName(name);
insistDeviceID(deviceID);
return deviceID;
}

/** @type {(forVatID: string, what: string) => string} */
function addImport(forVatID, what) {
if (!started) {
throw Error('must do kernel.start() before addImport()');
Expand Down
2 changes: 1 addition & 1 deletion packages/SwingSet/src/kernel/parseKernelSlots.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { assert, Fail } from '@agoric/assert';
* id: Nat
* }
*
* @param {unknown} s The string to be parsed, as described above.
* @param {string} s The string to be parsed, as described above.
*
* @returns {{type: 'object' | 'device' | 'promise', id: bigint}} a kernel slot object corresponding to the parameter.
*
Expand Down
2 changes: 1 addition & 1 deletion packages/SwingSet/src/lib/id.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function makeVatID(index) {
* @throws {Error} if, upon inspection, the parameter is not a string or is not a
* well-formed device ID as described above.
*
* @returns {void}
* @returns {asserts s is string}
*/
export function insistDeviceID(s) {
try {
Expand Down
16 changes: 16 additions & 0 deletions packages/SwingSet/src/vats/vat-admin/vat-vat-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ export function buildRootObject(vatPowers, _vatParameters, baggage) {
const { D } = vatPowers;
const pendingVatCreations = new Map(); // vatID -> { resolve, reject } for promise
const pendingBundles = new Map(); // bundleID -> Promise<BundleCap>
/** @type {Map<string, Omit<import('@endo/promise-kit').PromiseKit<import('../../types-external.js').VatUpgradeResults>, 'promise'>>} */
const pendingUpgrades = new Map(); // upgradeID -> Promise<UpgradeResults>

/** @see device-vat-admin.js */
let vatAdminDev;

const runningVats = new Map(); // vatID -> [doneP, { resolve, reject }]
Expand Down Expand Up @@ -207,6 +209,11 @@ export function buildRootObject(vatPowers, _vatParameters, baggage) {
}
}

/**
* @param {string} vatID
* @param {string} bundleID
* @param {{ vatParameters?: never, upgradeMessage?: string}} [options]
*/
async function upgradeVat(vatID, bundleID, options = {}) {
assert(vatAdminDev, 'vatAdmin device not configured');
const { vatParameters, upgradeMessage = 'vat upgraded', ...rest } = options;
Expand All @@ -219,6 +226,7 @@ export function buildRootObject(vatPowers, _vatParameters, baggage) {
const upgradeID = D(vatAdminDev).upgradeVat(
vatID,
bundleID,
// XXX this is passed to upgradeVat in device-vat-admin but ignored
vatParameters,
upgradeMessage,
);
Expand All @@ -227,6 +235,12 @@ export function buildRootObject(vatPowers, _vatParameters, baggage) {
return upgradeCompleteP;
}

/**
* @param {string} vatID
* @param {Pick<VatAdminVat, 'pauseService' | 'resumeService'>} pauseTarget
* @param {string} bundleID
* @param {{} | undefined} [options]
*/
async function upgradeStaticVat(vatID, pauseTarget, bundleID, options) {
await null;
if (pauseTarget) {
Expand Down Expand Up @@ -597,3 +611,5 @@ export function buildRootObject(vatPowers, _vatParameters, baggage) {
upgradeStaticVat,
});
}

/** @typedef {ReturnType<typeof buildRootObject>} VatAdminVat */
61 changes: 61 additions & 0 deletions packages/boot/test/bootstrapTests/test-restart-vat-admin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/** @file Bootstrap test of restarting (almost) all vats */
import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js';
import { eventLoopIteration } from '@agoric/internal/src/testing-utils.js';

import processAmbient from 'child_process';
import { promises as fsAmbientPromises } from 'fs';

import { Offers } from '@agoric/inter-protocol/src/clientSupport.js';
import { makeAgoricNamesRemotesFromFakeStorage } from '@agoric/vats/tools/board-utils.js';
import { TestFn } from 'ava';
import { BridgeHandler } from '@agoric/vats';
import type { EconomyBootstrapSpace } from '@agoric/inter-protocol/src/proposals/econ-behaviors.js';
import {
makeProposalExtractor,
makeSwingsetTestKit,
} from '../../tools/supports.ts';
import { makeWalletFactoryDriver } from '../../tools/drivers.ts';

const { Fail } = assert;

// XXX shouldn't need any econ stuff
const PLATFORM_CONFIG = '@agoric/vm-config/decentral-itest-vaults-config.json';

export const makeTestContext = async t => {
console.time('DefaultTestContext');
const swingsetTestKit = await makeSwingsetTestKit(t.log, 'bundles/vaults', {
configSpecifier: PLATFORM_CONFIG,
});

const { EV } = swingsetTestKit.runUtils;

// XXX wait for ATOM to make it into agoricNames
await EV.vat('bootstrap').consumeItem('vaultFactoryKit');

await eventLoopIteration();

const buildProposal = makeProposalExtractor({
childProcess: processAmbient,
fs: fsAmbientPromises,
});

return {
...swingsetTestKit,
buildProposal,
};
};

const test = anyTest as TestFn<Awaited<ReturnType<typeof makeTestContext>>>;

test.before(async t => {
t.context = await makeTestContext(t);
});
test.after.always(t => t.context.shutdown?.());

test('restart vat-admin vat', async t => {
const { buildAndExecuteProposal } = t.context;
// restart vat-admin
await buildAndExecuteProposal(
'@agoric/builders/scripts/vats/restart-vat-admin.js',
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@
import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js';

import { NonNullish } from '@agoric/assert';
import process from 'process';
import type { ExecutionContext, TestFn } from 'ava';
import type { ScheduleNotification } from '@agoric/inter-protocol/src/auction/scheduler.js';
import { BridgeHandler } from '@agoric/vats';
import type { ExecutionContext, TestFn } from 'ava';
import process from 'process';
import {
LiquidationSetup,
LiquidationTestContext,
likePayouts,
makeLiquidationTestContext,
scale6,
LiquidationSetup,
} from './liquidation.ts';

const test = anyTest as TestFn<LiquidationTestContext>;
Expand Down Expand Up @@ -152,25 +151,7 @@ const checkFlow1 = async (
controller,
buildProposal,
} = t.context;
const { EV } = t.context.runUtils;

const buildAndExecuteProposal = async packageSpec => {
const proposal = await buildProposal(packageSpec);

for await (const bundle of proposal.bundles) {
await controller.validateAndInstallBundle(bundle);
}

const bridgeMessage = {
type: 'CORE_EVAL',
evals: proposal.evals,
};

const coreEvalBridgeHandler: ERef<BridgeHandler> = await EV.vat(
'bootstrap',
).consumeItem('coreEvalBridgeHandler');
await EV(coreEvalBridgeHandler).fromBridge(bridgeMessage);
};
const { buildAndExecuteProposal } = t.context;

const metricsPath = `published.vaultFactory.managers.manager${managerIndex}.metrics`;

Expand Down Expand Up @@ -288,17 +269,19 @@ const checkFlow1 = async (
// restart Zoe
// /////// Upgrading ////////////////////////////////
await buildAndExecuteProposal(
'@agoric/builders/scripts/vats/null-upgrade-zoe-proposal.js',
'@agoric/builders/scripts/vats/restart-zoe.js',
);

await buyer.tryExitOffer(`${collateralBrandKey}-bid3`);
t.like(readLatest('published.wallet.agoric1buyer'), {
status: {
id: `${collateralBrandKey}-bid3`,
payouts: likePayouts(outcome.bids[2].payouts),
},
// UNTIL https://github.com/Agoric/agoric-sdk/pull/8453
await t.throwsAsync(buyer.tryExitOffer(`${collateralBrandKey}-bid3`), {
message: 'Cannot exit; seat has already exited',
});

// restart vat-admin
await buildAndExecuteProposal(
'@agoric/builders/scripts/vats/restart-vat-admin.js',
);

// TODO express spec up top in a way it can be passed in here
// check.vaultNotification(managerIndex, 0, {
// debt: undefined,
Expand Down Expand Up @@ -327,7 +310,7 @@ const checkFlow1 = async (
// });
};

test.serial.failing(
test.serial(
'wallet survives zoe null upgrade',
checkFlow1,
{ collateralBrandKey: 'ATOM', managerIndex: 0 },
Expand Down
23 changes: 1 addition & 22 deletions packages/boot/test/bootstrapTests/test-zcf-upgrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,30 +94,9 @@ test.before(async t => {
test.after.always(t => t.context.shutdown?.());

test('run restart-vats proposal', async t => {
const { controller, buildProposal, zoeDriver } = t.context;
const { controller, buildAndExecuteProposal, zoeDriver } = t.context;
const { EV } = t.context.runUtils;

const buildAndExecuteProposal = async packageSpec => {
const proposal = await buildProposal(packageSpec);

for await (const bundle of proposal.bundles) {
await controller.validateAndInstallBundle(bundle);
}

t.log('installed', proposal.bundles.length, 'bundles');

t.log('launching proposal');
const bridgeMessage = {
type: 'CORE_EVAL',
evals: proposal.evals,
};

t.log({ bridgeMessage });
const coreEvalBridgeHandler: ERef<BridgeHandler> = await EV.vat(
'bootstrap',
).consumeItem('coreEvalBridgeHandler');
await EV(coreEvalBridgeHandler).fromBridge(bridgeMessage);
};
const source = `${dirname}/${ZCF_PROBE_SRC}`;
const zcfProbeBundle = await bundleSource(source);
await controller.validateAndInstallBundle(zcfProbeBundle);
Expand Down
25 changes: 25 additions & 0 deletions packages/boot/tools/supports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
import type { ExecutionContext as AvaT } from 'ava';

import { makeRunUtils } from '@agoric/swingset-vat/tools/run-utils.js';
import { BridgeHandler } from '@agoric/vats';

const trace = makeTracer('BSTSupport', false);

Expand Down Expand Up @@ -415,9 +416,33 @@ export const makeSwingsetTestKit = async (

const getCrankNumber = () => Number(kernelStorage.kvStore.get('crankNumber'));

const buildAndExecuteProposal = async packageSpec => {
const proposal = await buildProposal(packageSpec);

for await (const bundle of proposal.bundles) {
await controller.validateAndInstallBundle(bundle);
}

log('installed', proposal.bundles.length, 'bundles');

log('launching proposal');
const bridgeMessage = {
type: 'CORE_EVAL',
evals: proposal.evals,
};

const { EV } = runUtils;
log({ bridgeMessage });
const coreEvalBridgeHandler: ERef<BridgeHandler> = await EV.vat(
'bootstrap',
).consumeItem('coreEvalBridgeHandler');
await EV(coreEvalBridgeHandler).fromBridge(bridgeMessage);
};

return {
advanceTimeBy,
advanceTimeTo,
buildAndExecuteProposal,
buildProposal,
controller,
getCrankNumber,
Expand Down
1 change: 0 additions & 1 deletion packages/builders/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"build:add-STARS-proposal": "echo This command has been deprecated. Please run this instead: agoric run scripts/inter-protocol/add-STARS.js",
"build:restart-vats-proposal": "echo echo This command has been deprecated. Please run this instead: agoric run scripts/vats/restart-vats.js",
"build:zcf-proposal": "echo This command has been deprecated. Please run this instead: agoric run scripts/vats/replace-zoe.js",
"build:null-upgrade-zoe-proposal": "echo This command has been deprecated. Please run this instead: agoric run scripts/vats/replace-zoe.js",
"prepack": "tsc --build tsconfig.build.json",
"postpack": "git clean -f '*.d.ts*'",
"test": "ava",
Expand Down
25 changes: 25 additions & 0 deletions packages/builders/scripts/vats/restart-vat-admin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { makeHelpers } from '@agoric/deploy-script-support';
import { getManifest } from '@agoric/vats/src/proposals/restart-vat-admin-proposal.js';

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').ProposalBuilder} */
export const defaultProposalBuilder = async ({ publishRef, install }) =>
harden({
sourceSpec: '@agoric/vats/src/proposals/restart-vat-admin-proposal.js',
getManifestCall: [
getManifest.name,
{
vatAdminRef: publishRef(
// The vat is defined in @agoric/swingset-vats (packages/SwingSet )
// but this proposal is in @agoric/vats because it depends on the
// VatAdminSvc made there.
install('@agoric/swingset-vat/src/vats/vat-admin/vat-vat-admin.js'),
),
},
],
});

export default async (homeP, endowments) => {
const { writeCoreProposal } = await makeHelpers(homeP, endowments);
// restart the vat named 'vat-admin'
await writeCoreProposal('restart-vat-admin', defaultProposalBuilder);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { makeHelpers } from '@agoric/deploy-script-support';
/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').ProposalBuilder} */
export const defaultProposalBuilder = async ({ publishRef, install }) =>
harden({
sourceSpec: '@agoric/vats/src/proposals/null-upgrade-zoe-proposal.js',
sourceSpec: '@agoric/vats/src/proposals/restart-zoe-proposal.js',
getManifestCall: [
'getManifestForUpgradingZoe',
{
Expand All @@ -14,5 +14,5 @@ export const defaultProposalBuilder = async ({ publishRef, install }) =>

export default async (homeP, endowments) => {
const { writeCoreProposal } = await makeHelpers(homeP, endowments);
await writeCoreProposal('null-upgrade-zoe', defaultProposalBuilder);
await writeCoreProposal('restart-zoe', defaultProposalBuilder);
};
4 changes: 1 addition & 3 deletions packages/vats/src/core/types-ambient.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ type VattpVat = ERef<
>;

type VatAdminVat = ERef<
ReturnType<
typeof import('@agoric/swingset-vat/src/vats/vat-admin/vat-vat-admin.js').buildRootObject
>
import('@agoric/swingset-vat/src/vats/vat-admin/vat-vat-admin.js').VatAdminVat
>;

/** @see deliverToController in packages/SwingSet/src/vats/comms/controller.js */
Expand Down
Loading
Loading