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

create new swingset-worker-xsnap-v1 package #7101

Closed
wants to merge 11 commits into from
4 changes: 4 additions & 0 deletions .github/workflows/test-all-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,10 @@ jobs:
run: cd packages/time && yarn ${{ steps.vars.outputs.test }} | $TEST_COLLECT
- name: yarn test (swingset-liveslots)
run: cd packages/swingset-liveslots && yarn ${{ steps.vars.outputs.test }} | $TEST_COLLECT
- name: yarn test (swingset-xsnap-supervisor)
run: cd packages/swingset-xsnap-supervisor && yarn ${{ steps.vars.outputs.test }} | $TEST_COLLECT
- name: yarn test (swingset-worker-xsnap-v1)
run: cd packages/swingset-worker-xsnap-v1 && yarn ${{ steps.vars.outputs.test }} | $TEST_COLLECT

# The meta-test!
- name: Check for untested packages
Expand Down
1 change: 1 addition & 0 deletions packages/SwingSet/misc-tools/measure-metering/measure.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
// run as `node tools/measure-metering/measure.js`

// eslint-disable-next-line import/order
Expand Down
38 changes: 11 additions & 27 deletions packages/SwingSet/misc-tools/replay-transcript.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* global WeakRef FinalizationRegistry */
/* eslint-disable no-constant-condition */
/* eslint-disable import/no-extraneous-dependencies */
import fs from 'fs';
// import '@endo/init';
import '../tools/install-ses-debug.js';
Expand All @@ -16,22 +17,17 @@ import { file as tmpFile, tmpName } from 'tmp';
import bundleSource from '@endo/bundle-source';
import { makeMeasureSeconds } from '@agoric/internal';
import { makeSnapStore } from '@agoric/swing-store';
import { entryPaths } from '@agoric/xsnap-lockdown/src/paths.js';
import { entryPaths as lockdownEntryPaths } from '@agoric/xsnap-lockdown/src/paths.js';
import { entryPaths as supervisorEntryPaths } from '@agoric/swingset-xsnap-supervisor/src/paths.js';
import { waitUntilQuiescent } from '../src/lib-nodejs/waitUntilQuiescent.js';
import { makeStartXSnap } from '../src/controller/controller.js';
import { makeStartXSnap } from '../src/controller/startXSnap.js';
import { makeXsSubprocessFactory } from '../src/kernel/vat-loader/manager-subprocess-xsnap.js';
import { makeLocalVatManagerFactory } from '../src/kernel/vat-loader/manager-local.js';
import { requireIdentical } from '../src/kernel/vat-loader/transcript.js';
import { makeDummyMeterControl } from '../src/kernel/dummyMeterControl.js';
import { makeGcAndFinalize } from '../src/lib-nodejs/gc-and-finalize.js';
import engineGC from '../src/lib-nodejs/engine-gc.js';

// Set the absolute path of the SDK to use for bundling
// This can help if there are symlinks in the path that should be respected
// to match the path of the SDK that produced the initial transcript
// For e.g. set to '/src' if replaying a docker based loadgen transcript
const ABSOLUTE_SDK_PATH = null;

// Rebuild the bundles when starting the replay.
// Disable if bundles were previously extracted form a Kernel DB, or
// to save a few seconds and rely upon previously built versions instead
Expand Down Expand Up @@ -71,22 +67,13 @@ function makeSnapStoreIO() {
}

async function makeBundles() {
const controllerUrl = new URL(
`${
ABSOLUTE_SDK_PATH ? `${ABSOLUTE_SDK_PATH}/packages/SwingSet` : '..'
}/src/controller/initializeSwingset.js`,
import.meta.url,
);

// we explicitly re-bundle these entry points, rather than using
// getLockdownBundle(), because if you're calling this, you're
// probably editing the sources anyways
const lockdown = await bundleSource(entryPaths.lockdown, 'nestedEvaluate');
const srcGE = rel =>
bundleSource(new URL(rel, controllerUrl).pathname, 'getExport');
const supervisor = await srcGE(
'../supervisors/subprocess-xsnap/supervisor-subprocess-xsnap.js',
);
const lockdownPath = lockdownEntryPaths.lockdown;
const lockdown = await bundleSource(lockdownPath, 'nestedEvaluate');
const supervisorPath = supervisorEntryPaths.supervisor;
const supervisor = await bundleSource(supervisorPath, 'nestedEvaluate');
fs.writeFileSync('lockdown-bundle', JSON.stringify(lockdown));
fs.writeFileSync('supervisor-bundle', JSON.stringify(supervisor));
console.log(`xs bundles written`);
Expand Down Expand Up @@ -166,20 +153,17 @@ async function replay(transcriptFile) {
JSON.parse(fs.readFileSync('lockdown-bundle')),
JSON.parse(fs.readFileSync('supervisor-bundle')),
];
const env = {};
if (RECORD_XSNAP_TRACE) {
env.XSNAP_TEST_RECORD = process.cwd();
}

const capturePIDSpawn = (...args) => {
const child = spawn(...args);
xsnapPID = child.pid;
return child;
};
const startXSnap = makeStartXSnap(bundles, {
const startXSnap = makeStartXSnap({
snapStore,
env,
spawn: capturePIDSpawn,
traceFile: RECORD_XSNAP_TRACE ? process.cwd() : undefined,
overrideBundles: bundles,
});
factory = makeXsSubprocessFactory({
kernelKeeper: fakeKernelKeeper,
Expand Down
6 changes: 4 additions & 2 deletions packages/SwingSet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
"lint:eslint": "eslint ."
},
"devDependencies": {
"@agoric/swingset-xsnap-supervisor": "^0.9.0",
"@agoric/xsnap": "^0.13.2",
"@agoric/xsnap-lockdown": "^0.13.2",
"@types/better-sqlite3": "^7.5.0",
"@types/microtime": "^2.1.0",
"@types/tmp": "^0.2.0",
Expand All @@ -34,10 +37,9 @@
"@agoric/store": "^0.8.3",
"@agoric/swing-store": "^0.8.1",
"@agoric/swingset-liveslots": "^0.9.0",
"@agoric/swingset-worker-xsnap-v1": "^0.9.0",
"@agoric/time": "^0.2.1",
"@agoric/vat-data": "^0.4.3",
"@agoric/xsnap": "^0.13.2",
"@agoric/xsnap-lockdown": "^0.13.2",
"@endo/base64": "^0.2.28",
"@endo/bundle-source": "^2.4.2",
"@endo/captp": "^2.0.18",
Expand Down
97 changes: 4 additions & 93 deletions packages/SwingSet/src/controller/controller.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
/* global globalThis, WeakRef, FinalizationRegistry */
/* eslint-disable @typescript-eslint/prefer-ts-expect-error -- https://github.com/Agoric/agoric-sdk/issues/4620 */

import fs from 'fs';
import path from 'path';
import process from 'process';
import crypto from 'crypto';
import { performance } from 'perf_hooks';
import { spawn as ambientSpawn } from 'child_process';
import { type as osType } from 'os';
import anylogger from 'anylogger';
import microtime from 'microtime';

import { assert, Fail } from '@agoric/assert';
import { importBundle } from '@endo/import-bundle';
import { xsnap, recordXSnap } from '@agoric/xsnap';
import { initSwingStore } from '@agoric/swing-store';

import { checkBundle } from '@endo/check-bundle/lite.js';
Expand All @@ -27,8 +23,7 @@ import {
swingsetIsInitialized,
initializeSwingset,
} from './initializeSwingset.js';

const NETSTRING_MAX_CHUNK_SIZE = 12_000_000;
import { makeStartXSnap } from './startXSnap.js';

/** @param {Uint8Array} bytes */
export function computeSha512(bytes) {
Expand Down Expand Up @@ -77,85 +72,6 @@ function unhandledRejectionHandler(e, pr) {
console.error('UnhandledPromiseRejectionWarning:', e);
}

/**
* @param {{ moduleFormat: string, source: string }[]} bundles
* @param {{
* snapStore?: SnapStore,
* spawn: typeof import('child_process').spawn
* env: Record<string, string | undefined>,
* }} opts
*/
export function makeStartXSnap(bundles, { snapStore, env, spawn }) {
/** @type { import('@agoric/xsnap/src/xsnap').XSnapOptions } */
const xsnapOpts = {
os: osType(),
spawn,
stdout: 'inherit',
stderr: 'inherit',
debug: !!env.XSNAP_DEBUG,
netstringMaxChunkSize: NETSTRING_MAX_CHUNK_SIZE,
};

let doXSnap = xsnap;
const { XSNAP_TEST_RECORD } = env;
if (XSNAP_TEST_RECORD) {
console.log('SwingSet xs-worker tracing:', { XSNAP_TEST_RECORD });
let serial = 0;
doXSnap = opts => {
const workerTrace =
path.resolve(`${XSNAP_TEST_RECORD}/${serial}`) + path.sep;
serial += 1;
fs.mkdirSync(workerTrace, { recursive: true });
return recordXSnap(opts, workerTrace, {
writeFileSync: fs.writeFileSync,
});
};
}

/**
* @param {string} vatID
* @param {string} name
* @param {(request: Uint8Array) => Promise<Uint8Array>} handleCommand
* @param {boolean} [metered]
* @param {boolean} [reload]
*/
async function startXSnap(
vatID,
name,
handleCommand,
metered,
reload = false,
) {
const meterOpts = metered ? {} : { meteringLimit: 0 };
if (snapStore && reload) {
// console.log('startXSnap from', { snapshotHash });
return snapStore.loadSnapshot(vatID, async snapshot => {
const xs = doXSnap({
snapshot,
name,
handleCommand,
...meterOpts,
...xsnapOpts,
});
await xs.isReady();
return xs;
});
}
// console.log('fresh xsnap', { snapStore: snapStore });
const worker = doXSnap({ handleCommand, name, ...meterOpts, ...xsnapOpts });

for (const bundle of bundles) {
bundle.moduleFormat === 'getExport' ||
bundle.moduleFormat === 'nestedEvaluate' ||
Fail`unexpected: ${bundle.moduleFormat}`;
// eslint-disable-next-line no-await-in-loop, @jessie.js/no-nested-await
await worker.evaluate(`(${bundle.source}\n)()`.trim());
}
return worker;
}
return startXSnap;
}

/**
*
* @param {SwingStoreKernelStorage} kernelStorage
Expand Down Expand Up @@ -264,16 +180,11 @@ export async function makeSwingsetController(
// all vats get these in their global scope, plus a vat-specific 'console'
const vatEndowments = harden({});

const bundles = [
// @ts-ignore assume lockdownBundle is set
JSON.parse(kvStore.get('lockdownBundle')),
// @ts-ignore assume supervisorBundle is set
JSON.parse(kvStore.get('supervisorBundle')),
];
const startXSnap = makeStartXSnap(bundles, {
const startXSnap = makeStartXSnap({
snapStore: kernelStorage.snapStore,
env,
spawn,
debug: !!env.XSNAP_DEBUG,
traceFile: env.XSNAP_TEST_RECORD,
});

const kernelEndowments = {
Expand Down
16 changes: 0 additions & 16 deletions packages/SwingSet/src/controller/initializeSwingset.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import path from 'path';

import { assert, Fail } from '@agoric/assert';
import { makeTracer } from '@agoric/internal';
import { getLockdownBundle } from '@agoric/xsnap-lockdown';
import bundleSource from '@endo/bundle-source';
import { resolve as resolveModuleSpecifier } from 'import-meta-resolve';
import { kdebugEnable } from '../lib/kdebug.js';
Expand Down Expand Up @@ -35,10 +34,6 @@ const allValues = async obj =>

const bundleRelative = rel =>
bundleSource(new URL(rel, import.meta.url).pathname);
const bundleRelativeCallable = rel =>
bundleSource(new URL(rel, import.meta.url).pathname, {
format: 'nestedEvaluate',
});

/**
* Build the source bundles for the kernel. makeSwingsetController()
Expand All @@ -56,18 +51,12 @@ export async function buildKernelBundle() {
* xsnap vat worker.
*/
export async function buildVatAndDeviceBundles() {
const lockdownP = getLockdownBundle(); // throws if bundle is not built
const bundles = await allValues({
adminDevice: bundleRelative('../devices/vat-admin/device-vat-admin.js'),
adminVat: bundleRelative('../vats/vat-admin/vat-vat-admin.js'),
comms: bundleRelative('../vats/comms/index.js'),
vattp: bundleRelative('../vats/vattp/vat-vattp.js'),
timer: bundleRelative('../vats/timer/vat-timer.js'),

lockdown: lockdownP,
supervisor: bundleRelativeCallable(
'../supervisors/subprocess-xsnap/supervisor-subprocess-xsnap.js',
),
});

return harden(bundles);
Expand Down Expand Up @@ -348,11 +337,6 @@ export async function initializeSwingset(
addTimer = true,
} = initializationOptions;

assert.typeof(kernelBundles.lockdown, 'object');
assert.typeof(kernelBundles.supervisor, 'object');
kvStore.set('lockdownBundle', JSON.stringify(kernelBundles.lockdown));
kvStore.set('supervisorBundle', JSON.stringify(kernelBundles.supervisor));

if (config.bootstrap && argv) {
const bootConfig = config.vats[config.bootstrap];
if (bootConfig) {
Expand Down
52 changes: 52 additions & 0 deletions packages/SwingSet/src/controller/startXSnap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import path from 'path';
import { makeStartXSnapV1 } from '@agoric/swingset-worker-xsnap-v1';

/**
* @param {{
* snapStore?: SnapStore,
* spawn: typeof import('child_process').spawn
* debug?: boolean,
* traceFile?: string,
* overrideBundles?: { moduleFormat: string, source: string }[],
* }} options
*/
export function makeStartXSnap(options) {
// our job is to simply curry some authorities and settings into the
// 'startXSnap' function we return

const { traceFile, ...other } = options;
let serial = 0;
const makeTraceFile = traceFile
? () => {
const workerTrace = path.resolve(`${traceFile}/${serial}`) + path.sep;
serial += 1;
return workerTrace;
}
: undefined;

const startXSnapV1 = makeStartXSnapV1({ makeTraceFile, ...other });

/**
* @param {string} workerVersion
* @param {string} vatID
* @param {string} name
* @param {(request: Uint8Array) => Promise<Uint8Array>} handleCommand
* @param {boolean} [metered]
* @param {boolean} [reload]
*/
async function startXSnap(
workerVersion,
vatID,
name,
handleCommand,
metered,
reload = false,
) {
if (workerVersion === 'xsnap-v1') {
return startXSnapV1(vatID, name, handleCommand, metered, reload);
}
throw Error(`unsupported worker version ${workerVersion}`);
}

return startXSnap;
}
5 changes: 4 additions & 1 deletion packages/SwingSet/src/kernel/kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ import { makeVatAdminHooks } from './vat-admin-hooks.js';

/**
* @typedef {import('@agoric/swingset-liveslots').VatDeliveryObject} VatDeliveryObject
* @typedef {import('@agoric/swingset-liveslots').VatDeliveryResult} VatDeliveryResult
* @typedef {import('@agoric/swingset-liveslots').VatSyscallObject} VatSyscallObject
* @typedef {import('@agoric/swingset-liveslots').VatSyscallResult} VatSyscallResult
*/

function abbreviateReplacer(_, arg) {
Expand Down Expand Up @@ -345,7 +348,7 @@ export default function buildKernel(

/**
*
* @typedef { import('../types-external.js').MeterConsumption } MeterConsumption
* @typedef { import('@agoric/swingset-liveslots').MeterConsumption } MeterConsumption
* @typedef { import('../types-internal.js').MeterID } MeterID
*
* Any delivery crank (send, notify, start-vat.. anything which is allowed
Expand Down
3 changes: 3 additions & 0 deletions packages/SwingSet/src/kernel/vat-loader/manager-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { makeTranscriptManager } from './transcript.js';

/**
* @typedef {import('@agoric/swingset-liveslots').VatDeliveryObject} VatDeliveryObject
* @typedef {import('@agoric/swingset-liveslots').VatDeliveryResult} VatDeliveryResult
* @typedef {import('@agoric/swingset-liveslots').VatSyscallObject} VatSyscallObject
* @typedef {import('@agoric/swingset-liveslots').VatSyscallResult} VatSyscallResult
*/

// We use vat-centric terminology here, so "inbound" means "into a vat",
Expand Down
Loading