Skip to content

Commit

Permalink
feat(swingset): handle vc syscalls during transcript replay
Browse files Browse the repository at this point in the history
  • Loading branch information
mhofman committed Dec 13, 2022
1 parent 2c812d2 commit 79cc13c
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 10 deletions.
8 changes: 5 additions & 3 deletions packages/SwingSet/src/kernel/vat-loader/manager-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ import { makeTranscriptManager } from './transcript.js';
* @param {KernelSlog} kernelSlog
* @param {(vso: VatSyscallObject) => VatSyscallResult} vatSyscallHandler
* @param {boolean} workerCanBlock
* @param {(vatID: any, originalSyscall: any, newSyscall: any) => Error | undefined} [compareSyscalls]
* @param {(vatID: any, originalSyscall: any, newSyscall: any) => import('./transcript.js').CompareSyscallsResult} [compareSyscalls]
* @param {boolean} [useTranscript]
* @returns {ManagerKit}
*/
Expand Down Expand Up @@ -247,7 +247,9 @@ function makeManagerKit(
// but if the puppy deviates one inch from previous twitches, explode
kernelSlog.syscall(vatID, undefined, vso);
const vres = transcriptManager.simulateSyscall(vso);
return vres;
if (vres) {
return vres;
}
}

const vres = vatSyscallHandler(vso);
Expand All @@ -256,7 +258,7 @@ function makeManagerKit(
if (successFlag === 'ok' && data && !workerCanBlock) {
console.log(`warning: syscall returns data, but worker cannot get it`);
}
if (transcriptManager) {
if (transcriptManager && !transcriptManager.inReplay()) {
transcriptManager.addSyscall(vso, vres);
}
return vres;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { assert, details as X, q } from '@agoric/assert';
import { ExitCode } from '@agoric/xsnap/api.js';
import { makeManagerKit } from './manager-helper.js';
import { requireIdenticalExceptStableVCSyscalls } from './transcript.js';

import {
insistVatSyscallObject,
Expand Down Expand Up @@ -55,7 +56,7 @@ export function makeXsSubprocessFactory({
const {
name: vatName,
metered,
compareSyscalls,
compareSyscalls = requireIdenticalExceptStableVCSyscalls,
useTranscript,
sourcedConsole,
} = managerOptions;
Expand Down
74 changes: 68 additions & 6 deletions packages/SwingSet/src/kernel/vat-loader/transcript.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import djson from '../../lib/djson.js';

const missingSyscall = Symbol('missing transcript syscall');
const extraSyscall = Symbol('extra transcript syscall');

/** @typedef {typeof missingSyscall | typeof extraSyscall | Error | undefined} CompareSyscallsResult */

/**
* @param {any} vatID
* @param {object} originalSyscall
* @param {object} newSyscall
* @returns {CompareSyscallsResult}
*/
export function requireIdentical(vatID, originalSyscall, newSyscall) {
if (djson.stringify(originalSyscall) !== djson.stringify(newSyscall)) {
console.error(`anachrophobia strikes vat ${vatID}`);
Expand All @@ -10,6 +21,39 @@ export function requireIdentical(vatID, originalSyscall, newSyscall) {
return undefined;
}

const vcSyscallRE = /^vc\.\d+\.\|(?:schemata|label)$/;

/**
* @param {any} vatID
* @param {object} originalSyscall
* @param {object} newSyscall
* @returns {CompareSyscallsResult}
*/
export function requireIdenticalExceptStableVCSyscalls(
vatID,
originalSyscall,
newSyscall,
) {
const error = requireIdentical(vatID, originalSyscall, newSyscall);

if (error) {
if (
originalSyscall[0] === 'vatstoreGet' &&
vcSyscallRE.test(originalSyscall[1])
) {
console.warn(` mitigation: ignoring extra vc syscall`);
return extraSyscall;
}

if (newSyscall[0] === 'vatstoreGet' && vcSyscallRE.test(newSyscall[1])) {
console.warn(` mitigation: falling through to syscall handler`);
return missingSyscall;
}
}

return error;
}

export function makeTranscriptManager(
vatKeeper,
vatID,
Expand Down Expand Up @@ -59,13 +103,31 @@ export function makeTranscriptManager(
let replayError;

function simulateSyscall(newSyscall) {
const s = playbackSyscalls.shift();
const newReplayError = compareSyscalls(vatID, s.d, newSyscall);
if (newReplayError) {
replayError = newReplayError;
throw replayError;
while (playbackSyscalls.length) {
const compareError = compareSyscalls(
vatID,
playbackSyscalls[0].d,
newSyscall,
);

if (compareError === missingSyscall) {
return undefined;
}

const s = playbackSyscalls.shift();

if (!compareError) {
return s.response;
} else if (compareError !== extraSyscall) {
replayError = compareError;
break;
}
}

if (!replayError) {
replayError = new Error(`historical inaccuracy in replay of ${vatID}`);
}
return s.response;
throw replayError;
}

function finishReplayDelivery(dnum) {
Expand Down

0 comments on commit 79cc13c

Please sign in to comment.