From 0a208056bc8d6201cf87f93f3a292a322f635d3f Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Tue, 8 Feb 2022 16:37:27 -0800 Subject: [PATCH] fix(zoe): teach fakeVatAdmin to createVatByName(zcf) Zoe needs a way to create a new ZCF vat. Inside swingset, zoe uses `vatAdminService`, and this is used from unit tests (zoe and other packages that use zoe) when they are willing to take the time to run a full swingset environment. Unit tests that use zoe, but not swingset, use `tools/fakeVatAdmin.js` as a replacement, which implements `createVat(bundle)` but not `createVatByName(name)`. This is used to evaluate the ZCF bundle in a new Compartment (using `importBundle` and `evalContractBundle`). The primary export of `@agoric/zoe` is `makeZoeKit()`, which is called with `vatAdminService` and an optional `zcfBundleName`. This function runs `setupCreateZCFVat(vatAdminService)` to attenuate the vat-making power into one that can only create ZCF vats. Previously, `setupCreateZCFVat` closed over a copy of the ZCF bundle, and passed it to `vatAdminService~.createVat(zcfBundle)`. This hides the existence of the ZCF bundle from other packages that just want to use Zoe. However, to remove these large code bundles from userspace messages, we need the ZCF bundle to be installed "off to the side", by the code that prepares the swingset environment (usually as `config.bundles.zcf=`). This commit changes `fakeVatAdmin.js` to implement `createVatByName('zcf')`, and to move the copy of the zcfBundle out of `makeZoeKit()` and into `fakeVatAdmin.js` . In addition, it changes `createZCFVat.js` to provide a default bundle name of 'zcf'. Any unit test that uses `fakeVatAdmin.js` can continue to do so without changes, and the fake service will magically know how to create Zoe's ZCF vat without any additional configuration. Unit tests that use swingset, however, need to be updated to install the ZCF bundle into the kernel, with something like: ``` import zcfBundle from `@agoric/zoe/bundles/bundle-contractFacet.js`; ... config.bundles.zcf = { bundle: zcfBundle }; ``` Note: if we used `{ sourceSpec: '@agoric/zoe/contractFacet.js' }`, then we would not depend upon a recent `cd packages/zoe && yarn build`, and each kernel instance would bundle its own copy. This would be slower, but perhaps less prone to stale-bundle surprises, and might be a nicer export commitment). refs #4487 --- packages/zoe/src/zoeService/createZCFVat.js | 11 ++++----- packages/zoe/tools/fakeVatAdmin.js | 25 ++++++++++++++++++--- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/zoe/src/zoeService/createZCFVat.js b/packages/zoe/src/zoeService/createZCFVat.js index 2b15c4e804d6..74bfcf08c5ef 100644 --- a/packages/zoe/src/zoeService/createZCFVat.js +++ b/packages/zoe/src/zoeService/createZCFVat.js @@ -1,6 +1,5 @@ import { E } from '@agoric/eventual-send'; - -import zcfContractBundle from '../../bundles/bundle-contractFacet.js'; +import { assert } from '@agoric/assert'; /** * Attenuate the power of vatAdminSvc by restricting it such that only @@ -10,13 +9,11 @@ import zcfContractBundle from '../../bundles/bundle-contractFacet.js'; * @param {string=} zcfBundleName * @returns {CreateZCFVat} */ -export const setupCreateZCFVat = (vatAdminSvc, zcfBundleName = undefined) => { +export const setupCreateZCFVat = (vatAdminSvc, zcfBundleName = 'zcf') => { /** @type {CreateZCFVat} */ const createZCFVat = async () => { - const rootAndAdminNodeP = - typeof zcfBundleName === 'string' - ? E(vatAdminSvc).createVatByName(zcfBundleName) - : E(vatAdminSvc).createVat(zcfContractBundle); + assert.typeof(zcfBundleName, 'string'); + const rootAndAdminNodeP = E(vatAdminSvc).createVatByName(zcfBundleName); const rootAndAdminNode = await rootAndAdminNodeP; return rootAndAdminNode; }; diff --git a/packages/zoe/tools/fakeVatAdmin.js b/packages/zoe/tools/fakeVatAdmin.js index 86c981c99b30..1071b7d58948 100644 --- a/packages/zoe/tools/fakeVatAdmin.js +++ b/packages/zoe/tools/fakeVatAdmin.js @@ -4,9 +4,10 @@ import { E } from '@agoric/eventual-send'; import { makePromiseKit } from '@agoric/promise-kit'; import { Far } from '@endo/marshal'; -import { assert, details as X } from '@agoric/assert'; +import { assert } from '@agoric/assert'; import { evalContractBundle } from '../src/contractFacet/evalContractCode.js'; import { handlePKitWarning } from '../src/handleWarning.js'; +import zcfContractBundle from '../bundles/bundle-contractFacet.js'; /** * @param { (...args) => unknown } [testContextSetter] @@ -54,8 +55,26 @@ function makeFakeVatAdmin(testContextSetter = undefined, makeRemote = x => x) { }), }); }, - createVatByName: _name => { - assert.fail(X`createVatByName not supported in fake mode`); + createVatByName: name => { + assert.equal(name, 'zcf', `only name='zcf' accepted, not ${name}`); + const bundle = zcfContractBundle; + return harden({ + root: makeRemote( + E(evalContractBundle(bundle)).buildRootObject( + fakeVatPowers, + undefined, + testContextSetter, + ), + ), + adminNode: Far('adminNode', { + done: () => { + const kit = makePromiseKit(); + handlePKitWarning(kit); + return kit.promise; + }, + terminateWithFailure: () => {}, + }), + }); }, }); const vatAdminState = {