-
Notifications
You must be signed in to change notification settings - Fork 206
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(swingset): persist xsnap bundle IDs at vat creation/upgrade
When launching an xsnap worker, we must load two special bundles into the worker's empty JS engine: xsnap-lockdown (which turns it into a SES environment), and swingset-xsnap-supervisor (which loads liveslots and the command handlers). We get these bundles from packages of the same names. Previously, we would load the current versions of these bundles each time the controller/kernel started, and use them for all vats started or upgraded during that incarnation of the controller (i.e. until the process exited). This did not maintain stable behavior for a vat which e.g. does not record a heap snapshot before its initial controller incarnation finishes: if the xsnap-lockdown package were updated between controller incarnations, the second incarnation would launch the worker with a different bundle than the first, potentially causing divergence between the vat's original behavior (as recorded in its transcript) and the replay. If there were any local-manager liveslots -based vats, these would suffer the same problem on every kernel reboot, since only xsnap-hosted vats can use heap snapshots. With this commit, the lockdown and supervisor bundles are stored in the swing-store `bundleStore`, and their IDs are recorded in the metadata for each vat. We check the bundle-providing packages each time we start a new vat (or upgrade an existing one), so the new worker will use the latest bundles. But by recording the IDs separately for each vat, we ensure that every launch of that vat worker will the same bundles. This stability will help us maintain the deterministic behavior of a vat despite changes to the packages depended upon by any given version of the kernel. Unit tests and replay tools can use `options.overrideBundles=[..]` to replace the usual bundles with alternates: either no bundles, or custom lockdown/supervisor bundles. closes #7208
- Loading branch information
Showing
15 changed files
with
534 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { getLockdownBundleSHA256, getLockdownBundle } from '@agoric/xsnap-lockdown'; | ||
import { getSupervisorBundleSHA256, getSupervisorBundle } from '@agoric/swingset-xsnap-supervisor'; | ||
|
||
|
||
export const makeXsnapBundleData = harden(() => { | ||
return harden({ | ||
getLockdownBundleSHA256, | ||
getLockdownBundle, | ||
getSupervisorBundleSHA256, | ||
getSupervisorBundle, | ||
}); | ||
}); | ||
|
||
/** | ||
* @typedef {import('../types-external.js').BundleID} BundleID | ||
* @typedef {import('../types-external.js').Bundle} Bundle | ||
* | ||
* @typedef {object} BundleHandler | ||
* @property {() => Promise<BundleID[]>} getCurrentBundleIDs | ||
* @property {(id: BundleID) => Promise<Bundle>} getBundle | ||
*/ | ||
|
||
/** | ||
* @param {import('@agoric/swing-store').BundleStore} bundleStore | ||
* @param {ReturnType<makeXsnapBundleData>} bundleData | ||
* @returns {BundleHandler} | ||
*/ | ||
export const makeWorkerBundleHandler = harden((bundleStore, bundleData) => { | ||
const { | ||
getLockdownBundleSHA256, | ||
getLockdownBundle, | ||
getSupervisorBundleSHA256, | ||
getSupervisorBundle, | ||
} = bundleData; | ||
|
||
return harden({ | ||
getCurrentBundleIDs: async () => { | ||
const lockdownHash = await getLockdownBundleSHA256(); | ||
const lockdownID = `b0-${lockdownHash}`; | ||
if (!bundleStore.hasBundle(lockdownID)) { | ||
const lockdownBundle = await getLockdownBundle(); | ||
bundleStore.addBundle(lockdownID, lockdownBundle); | ||
} | ||
|
||
const supervisorHash = await getSupervisorBundleSHA256(); | ||
const supervisorID = `b0-${supervisorHash}`; | ||
if (!bundleStore.hasBundle(supervisorID)) { | ||
const supervisorBundle = await getSupervisorBundle(); | ||
bundleStore.addBundle(supervisorID, supervisorBundle); | ||
} | ||
|
||
return [lockdownID, supervisorID]; // order is important | ||
}, | ||
getBundle: async id => { | ||
return bundleStore.getBundle(id); | ||
}, | ||
}); | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.