From a4364481edfe8d88167e9b4b2f4950621183b3b2 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 13 Nov 2023 15:34:15 -0500 Subject: [PATCH 01/10] chore(deploy-script-support): Rename `allPowers` to clarify its limited scope --- .../src/coreProposalBehavior.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/deploy-script-support/src/coreProposalBehavior.js b/packages/deploy-script-support/src/coreProposalBehavior.js index 080a14bfbf2..e9b99cbfa87 100644 --- a/packages/deploy-script-support/src/coreProposalBehavior.js +++ b/packages/deploy-script-support/src/coreProposalBehavior.js @@ -8,7 +8,8 @@ const t = 'makeCoreProposalBehavior'; * @typedef {*} BootstrapPowers */ -// These permits apply to `allPowers` in `behavior` below. +// These permits limit the powers passed to the `behavior` function returned by +// `makeCoreProposalBehavior`. export const permits = { consume: { agoricNamesAdmin: t, vatAdminSvc: t, zoe: t }, evaluateBundleCap: t, @@ -56,9 +57,9 @@ export const makeCoreProposalBehavior = ({ return fromEntries(ents); }; - /** @param {ChainBootstrapSpace & BootstrapPowers & { evaluateBundleCap: any }} allPowers */ - const behavior = async allPowers => { - // NOTE: If updating any of these names extracted from `allPowers`, you must + /** @param {ChainBootstrapSpace & BootstrapPowers & { evaluateBundleCap: any }} powers */ + const behavior = async powers => { + // NOTE: If updating any of these names extracted from `powers`, you must // change `permits` above to reflect their accessibility. const { consume: { vatAdminSvc, zoe, agoricNamesAdmin }, @@ -67,7 +68,7 @@ export const makeCoreProposalBehavior = ({ modules: { utils: { runModuleBehaviors }, }, - } = allPowers; + } = powers; const [exportedGetManifest, ...manifestArgs] = getManifestCall; /** @type {(ref: import('./externalTypes.js').ManifestBundleRef) => Promise>} */ @@ -130,7 +131,7 @@ export const makeCoreProposalBehavior = ({ // Evaluate the manifest for our behaviors. return runModuleBehaviors({ - allPowers, + allPowers: powers, behaviors: manifestNS, manifest: overrideManifest || manifest, makeConfig: (name, _permit) => { @@ -146,7 +147,7 @@ export const makeCoreProposalBehavior = ({ export const makeEnactCoreProposalsFromBundleRef = ({ makeCoreProposalArgs, E }) => - async allPowers => { + async powers => { await Promise.all( makeCoreProposalArgs.map(async ({ ref, call, overrideManifest }) => { const subBehavior = makeCoreProposalBehavior({ @@ -155,7 +156,7 @@ export const makeEnactCoreProposalsFromBundleRef = overrideManifest, E, }); - return subBehavior(allPowers); + return subBehavior(powers); }), ); }; From 4640c8ac00bc07c9737475d6a72c2b6309cdb751 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 13 Nov 2023 15:45:46 -0500 Subject: [PATCH 02/10] chore(deploy-script-support): Move default restoreRef creation up a level --- .../src/coreProposalBehavior.js | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/packages/deploy-script-support/src/coreProposalBehavior.js b/packages/deploy-script-support/src/coreProposalBehavior.js index e9b99cbfa87..19b8ff3331d 100644 --- a/packages/deploy-script-support/src/coreProposalBehavior.js +++ b/packages/deploy-script-support/src/coreProposalBehavior.js @@ -57,6 +57,23 @@ export const makeCoreProposalBehavior = ({ return fromEntries(ents); }; + const makeRestoreRef = (vatAdminSvc, zoe) => { + /** @type {(ref: import('./externalTypes.js').ManifestBundleRef) => Promise>} */ + const defaultRestoreRef = async bundleRef => { + // extract-proposal.js creates these records, and bundleName is + // the name under which the bundle was installed into + // config.bundles + const bundleIdP = + 'bundleName' in bundleRef + ? E(vatAdminSvc).getBundleIDByName(bundleRef.bundleName) + : bundleRef.bundleID; + const bundleID = await bundleIdP; + const label = bundleID.slice(0, 8); + return E(zoe).installBundleID(bundleID, label); + }; + return defaultRestoreRef; + }; + /** @param {ChainBootstrapSpace & BootstrapPowers & { evaluateBundleCap: any }} powers */ const behavior = async powers => { // NOTE: If updating any of these names extracted from `powers`, you must @@ -71,21 +88,6 @@ export const makeCoreProposalBehavior = ({ } = powers; const [exportedGetManifest, ...manifestArgs] = getManifestCall; - /** @type {(ref: import('./externalTypes.js').ManifestBundleRef) => Promise>} */ - const defaultRestoreRef = async ref => { - // extract-proposal.js creates these records, and bundleName is - // the name under which the bundle was installed into - // config.bundles - const p = - 'bundleName' in ref - ? E(vatAdminSvc).getBundleIDByName(ref.bundleName) - : ref.bundleID; - const bundleID = await p; - const label = bundleID.slice(0, 8); - return E(zoe).installBundleID(bundleID, label); - }; - const restoreRef = overrideRestoreRef || defaultRestoreRef; - // Get the on-chain installation containing the manifest and behaviors. console.info('evaluateBundleCap', { manifestBundleRef, @@ -102,10 +104,12 @@ export const makeCoreProposalBehavior = ({ const manifestNS = await evaluateBundleCap(bundleCap); + // Get the manifest and its metadata. console.error('execute', { exportedGetManifest, behaviors: Object.keys(manifestNS), }); + const restoreRef = overrideRestoreRef || makeRestoreRef(vatAdminSvc, zoe); const { manifest, options: rawOptions, From 520ddf836e564b9a08b95ea0e73cfd01d1d24ada Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 13 Nov 2023 15:54:52 -0500 Subject: [PATCH 03/10] chore(deploy-script-support): Clarify the [methodName, ...args] structure of getManifestCall --- .../src/coreProposalBehavior.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/deploy-script-support/src/coreProposalBehavior.js b/packages/deploy-script-support/src/coreProposalBehavior.js index 19b8ff3331d..302f6bf079e 100644 --- a/packages/deploy-script-support/src/coreProposalBehavior.js +++ b/packages/deploy-script-support/src/coreProposalBehavior.js @@ -26,7 +26,7 @@ export const permits = { * * @param {object} opts * @param {import('./externalTypes.js').ManifestBundleRef} opts.manifestBundleRef - * @param {[string, ...unknown[]]} opts.getManifestCall + * @param {[methodName: string, ...args: unknown[]]} opts.getManifestCall * @param {Record>} [opts.overrideManifest] * @param {typeof import('@endo/far').E} opts.E * @param {(...args: unknown[]) => void} [opts.log] @@ -35,7 +35,7 @@ export const permits = { */ export const makeCoreProposalBehavior = ({ manifestBundleRef, - getManifestCall, + getManifestCall: [manifestGetterName, ...manifestGetterArgs], overrideManifest, E, log = console.info, @@ -86,12 +86,11 @@ export const makeCoreProposalBehavior = ({ utils: { runModuleBehaviors }, }, } = powers; - const [exportedGetManifest, ...manifestArgs] = getManifestCall; // Get the on-chain installation containing the manifest and behaviors. console.info('evaluateBundleCap', { manifestBundleRef, - exportedGetManifest, + exportedGetManifest: manifestGetterName, vatAdminSvc, }); let bcapP; @@ -106,7 +105,7 @@ export const makeCoreProposalBehavior = ({ // Get the manifest and its metadata. console.error('execute', { - exportedGetManifest, + exportedGetManifest: manifestGetterName, behaviors: Object.keys(manifestNS), }); const restoreRef = overrideRestoreRef || makeRestoreRef(vatAdminSvc, zoe); @@ -114,9 +113,9 @@ export const makeCoreProposalBehavior = ({ manifest, options: rawOptions, installations: rawInstallations, - } = await manifestNS[exportedGetManifest]( + } = await manifestNS[manifestGetterName]( harden({ restoreRef }), - ...manifestArgs, + ...manifestGetterArgs, ); // Await references in the options or installations. From 037f890cd5c09ab564457e472cb5c55a033b4586 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 13 Nov 2023 15:58:24 -0500 Subject: [PATCH 04/10] chore(deploy-script-support): Enforce bundleRef shape --- .../deploy-script-support/src/coreProposalBehavior.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/deploy-script-support/src/coreProposalBehavior.js b/packages/deploy-script-support/src/coreProposalBehavior.js index 302f6bf079e..9b0ac80212a 100644 --- a/packages/deploy-script-support/src/coreProposalBehavior.js +++ b/packages/deploy-script-support/src/coreProposalBehavior.js @@ -96,8 +96,16 @@ export const makeCoreProposalBehavior = ({ let bcapP; if ('bundleName' in manifestBundleRef) { bcapP = E(vatAdminSvc).getNamedBundleCap(manifestBundleRef.bundleName); - } else { + } else if ('bundleID' in manifestBundleRef) { bcapP = E(vatAdminSvc).getBundleCap(manifestBundleRef.bundleID); + } else { + const keys = Reflect.ownKeys(manifestBundleRef).map(key => + typeof key === 'string' ? JSON.stringify(key) : String(key), + ); + const keysStr = `[${keys.join(', ')}]`; + throw Error( + `bundleRef must have own bundleName or bundleID, missing in ${keysStr}`, + ); } const bundleCap = await bcapP; From e6903b5da911d99f4b374543fa5326c6cad4462e Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 13 Nov 2023 16:00:01 -0500 Subject: [PATCH 05/10] chore(deploy-script-support): Rename `manifestNS` to clarify its nature --- .../src/coreProposalBehavior.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/deploy-script-support/src/coreProposalBehavior.js b/packages/deploy-script-support/src/coreProposalBehavior.js index 9b0ac80212a..dcbaf28cd25 100644 --- a/packages/deploy-script-support/src/coreProposalBehavior.js +++ b/packages/deploy-script-support/src/coreProposalBehavior.js @@ -109,19 +109,19 @@ export const makeCoreProposalBehavior = ({ } const bundleCap = await bcapP; - const manifestNS = await evaluateBundleCap(bundleCap); + const installationNS = await evaluateBundleCap(bundleCap); // Get the manifest and its metadata. console.error('execute', { exportedGetManifest: manifestGetterName, - behaviors: Object.keys(manifestNS), + behaviors: Object.keys(installationNS), }); const restoreRef = overrideRestoreRef || makeRestoreRef(vatAdminSvc, zoe); const { manifest, options: rawOptions, installations: rawInstallations, - } = await manifestNS[manifestGetterName]( + } = await installationNS[manifestGetterName]( harden({ restoreRef }), ...manifestGetterArgs, ); @@ -131,7 +131,7 @@ export const makeCoreProposalBehavior = ({ [rawOptions, rawInstallations].map(shallowlyFulfilled), ); - // Publish the installations for behavior dependencies. + // Publish the installations for our dependencies. const installAdmin = E(agoricNamesAdmin).lookupAdmin('installation'); await Promise.all( entries(installations || {}).map(([key, value]) => { @@ -140,10 +140,10 @@ export const makeCoreProposalBehavior = ({ }), ); - // Evaluate the manifest for our behaviors. + // Evaluate the manifest. return runModuleBehaviors({ allPowers: powers, - behaviors: manifestNS, + behaviors: installationNS, manifest: overrideManifest || manifest, makeConfig: (name, _permit) => { log('coreProposal:', name); @@ -152,7 +152,6 @@ export const makeCoreProposalBehavior = ({ }); }; - // Make the behavior the completion value. return behavior; }; From f16e093c44a80485e0deeb5962a4ef737b29189a Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 13 Nov 2023 16:00:58 -0500 Subject: [PATCH 06/10] chore(deploy-script-support): Clarify `shallowlyFulfilled` --- .../src/coreProposalBehavior.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/deploy-script-support/src/coreProposalBehavior.js b/packages/deploy-script-support/src/coreProposalBehavior.js index dcbaf28cd25..75bf1ad10e0 100644 --- a/packages/deploy-script-support/src/coreProposalBehavior.js +++ b/packages/deploy-script-support/src/coreProposalBehavior.js @@ -43,18 +43,27 @@ export const makeCoreProposalBehavior = ({ }) => { const { entries, fromEntries } = Object; - // deeplyFulfilled is a bit overkill for what we need. + /** + * Given an object whose properties may be promise-valued, return a promise + * for an analogous object in which each such value has been replaced with its + * fulfillment. + * This is a non-recursive form of endo `deeplyFulfilled`. + * + * @template T + * @param {{[K in keyof T]: (T[K] | Promise)}} obj + * @returns {Promise} + */ const shallowlyFulfilled = async obj => { if (!obj) { return obj; } - const ents = await Promise.all( + const awaitedEntries = await Promise.all( entries(obj).map(async ([key, valueP]) => { const value = await valueP; return [key, value]; }), ); - return fromEntries(ents); + return fromEntries(awaitedEntries); }; const makeRestoreRef = (vatAdminSvc, zoe) => { @@ -126,7 +135,7 @@ export const makeCoreProposalBehavior = ({ ...manifestGetterArgs, ); - // Await references in the options or installations. + // Await promises in the returned options and installations records. const [options, installations] = await Promise.all( [rawOptions, rawInstallations].map(shallowlyFulfilled), ); From cbef1af178a8ff6e17098d2ca459a4f7814067cb Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Thu, 23 Nov 2023 11:07:50 -0500 Subject: [PATCH 07/10] chore(deploy-script-support): Improve comment --- packages/deploy-script-support/src/coreProposalBehavior.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/deploy-script-support/src/coreProposalBehavior.js b/packages/deploy-script-support/src/coreProposalBehavior.js index 75bf1ad10e0..d25e6c300d5 100644 --- a/packages/deploy-script-support/src/coreProposalBehavior.js +++ b/packages/deploy-script-support/src/coreProposalBehavior.js @@ -70,7 +70,7 @@ export const makeCoreProposalBehavior = ({ /** @type {(ref: import('./externalTypes.js').ManifestBundleRef) => Promise>} */ const defaultRestoreRef = async bundleRef => { // extract-proposal.js creates these records, and bundleName is - // the name under which the bundle was installed into + // the optional name under which the bundle was installed into // config.bundles const bundleIdP = 'bundleName' in bundleRef From f4abd3ad11397836b5752ce5a789b52e3d8b5fda Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Thu, 23 Nov 2023 11:10:46 -0500 Subject: [PATCH 08/10] chore(deploy-script-support): Clean up logging --- .../deploy-script-support/src/coreProposalBehavior.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/deploy-script-support/src/coreProposalBehavior.js b/packages/deploy-script-support/src/coreProposalBehavior.js index d25e6c300d5..65508419987 100644 --- a/packages/deploy-script-support/src/coreProposalBehavior.js +++ b/packages/deploy-script-support/src/coreProposalBehavior.js @@ -97,9 +97,9 @@ export const makeCoreProposalBehavior = ({ } = powers; // Get the on-chain installation containing the manifest and behaviors. - console.info('evaluateBundleCap', { + log('evaluateBundleCap', { manifestBundleRef, - exportedGetManifest: manifestGetterName, + manifestGetterName, vatAdminSvc, }); let bcapP; @@ -121,9 +121,9 @@ export const makeCoreProposalBehavior = ({ const installationNS = await evaluateBundleCap(bundleCap); // Get the manifest and its metadata. - console.error('execute', { - exportedGetManifest: manifestGetterName, - behaviors: Object.keys(installationNS), + log('execute', { + manifestGetterName, + bundleExports: Object.keys(installationNS), }); const restoreRef = overrideRestoreRef || makeRestoreRef(vatAdminSvc, zoe); const { From 6dc6f12dbfa444df49a55dd013a72caf1d629b8e Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Thu, 23 Nov 2023 11:28:11 -0500 Subject: [PATCH 09/10] chore(deploy-script-support): Comment on the scope of `powers` --- .../src/coreProposalBehavior.js | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/deploy-script-support/src/coreProposalBehavior.js b/packages/deploy-script-support/src/coreProposalBehavior.js index 65508419987..452c039e48a 100644 --- a/packages/deploy-script-support/src/coreProposalBehavior.js +++ b/packages/deploy-script-support/src/coreProposalBehavior.js @@ -8,8 +8,14 @@ const t = 'makeCoreProposalBehavior'; * @typedef {*} BootstrapPowers */ -// These permits limit the powers passed to the `behavior` function returned by -// `makeCoreProposalBehavior`. +/** + * These permits are expected to be the minimum powers required by the + * `behavior` function returned from `makeCoreProposalBehavior`. + * They are merged with all of the manifest getter's permits to produce the + * total permits needed by the resulting core proposal (such as might be---and + * generally are---written into a *-permit.json file). + * @see {@link ./writeCoreProposal.js} + */ export const permits = { consume: { agoricNamesAdmin: t, vatAdminSvc: t, zoe: t }, evaluateBundleCap: t, @@ -85,8 +91,13 @@ export const makeCoreProposalBehavior = ({ /** @param {ChainBootstrapSpace & BootstrapPowers & { evaluateBundleCap: any }} powers */ const behavior = async powers => { - // NOTE: If updating any of these names extracted from `powers`, you must - // change `permits` above to reflect their accessibility. + // NOTE: `powers` is expected to match or be a superset of the above `permits` export, + // which should therefore be kept in sync with this deconstruction code. + // HOWEVER, do note that this function is invoked with at least the *union* of powers + // required by individual moduleBehaviors declared by the manifest getter, which is + // necessary so it can use `runModuleBehaviors` to provide the appropriate subset to + // each one (see ./writeCoreProposal.js). + // Handle `powers` with the requisite care. const { consume: { vatAdminSvc, zoe, agoricNamesAdmin }, evaluateBundleCap, @@ -151,6 +162,7 @@ export const makeCoreProposalBehavior = ({ // Evaluate the manifest. return runModuleBehaviors({ + // Remember that `powers` may be arbitrarily broad. allPowers: powers, behaviors: installationNS, manifest: overrideManifest || manifest, From a3a54f97145bc1dbd7386dba9035461e6eca88c9 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 27 Nov 2023 15:20:22 -0500 Subject: [PATCH 10/10] chore(deploy-script-support): Rename variables for clarity Per @michaelfig review --- .../src/coreProposalBehavior.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/deploy-script-support/src/coreProposalBehavior.js b/packages/deploy-script-support/src/coreProposalBehavior.js index 452c039e48a..304e195b437 100644 --- a/packages/deploy-script-support/src/coreProposalBehavior.js +++ b/packages/deploy-script-support/src/coreProposalBehavior.js @@ -10,7 +10,7 @@ const t = 'makeCoreProposalBehavior'; /** * These permits are expected to be the minimum powers required by the - * `behavior` function returned from `makeCoreProposalBehavior`. + * `coreProposalBehavior` function returned from `makeCoreProposalBehavior`. * They are merged with all of the manifest getter's permits to produce the * total permits needed by the resulting core proposal (such as might be---and * generally are---written into a *-permit.json file). @@ -90,7 +90,7 @@ export const makeCoreProposalBehavior = ({ }; /** @param {ChainBootstrapSpace & BootstrapPowers & { evaluateBundleCap: any }} powers */ - const behavior = async powers => { + const coreProposalBehavior = async powers => { // NOTE: `powers` is expected to match or be a superset of the above `permits` export, // which should therefore be kept in sync with this deconstruction code. // HOWEVER, do note that this function is invoked with at least the *union* of powers @@ -129,19 +129,19 @@ export const makeCoreProposalBehavior = ({ } const bundleCap = await bcapP; - const installationNS = await evaluateBundleCap(bundleCap); + const proposalNS = await evaluateBundleCap(bundleCap); // Get the manifest and its metadata. log('execute', { manifestGetterName, - bundleExports: Object.keys(installationNS), + bundleExports: Object.keys(proposalNS), }); const restoreRef = overrideRestoreRef || makeRestoreRef(vatAdminSvc, zoe); const { manifest, options: rawOptions, installations: rawInstallations, - } = await installationNS[manifestGetterName]( + } = await proposalNS[manifestGetterName]( harden({ restoreRef }), ...manifestGetterArgs, ); @@ -164,7 +164,7 @@ export const makeCoreProposalBehavior = ({ return runModuleBehaviors({ // Remember that `powers` may be arbitrarily broad. allPowers: powers, - behaviors: installationNS, + behaviors: proposalNS, manifest: overrideManifest || manifest, makeConfig: (name, _permit) => { log('coreProposal:', name); @@ -173,7 +173,7 @@ export const makeCoreProposalBehavior = ({ }); }; - return behavior; + return coreProposalBehavior; }; export const makeEnactCoreProposalsFromBundleRef = @@ -181,13 +181,13 @@ export const makeEnactCoreProposalsFromBundleRef = async powers => { await Promise.all( makeCoreProposalArgs.map(async ({ ref, call, overrideManifest }) => { - const subBehavior = makeCoreProposalBehavior({ + const coreProposalBehavior = makeCoreProposalBehavior({ manifestBundleRef: ref, getManifestCall: call, overrideManifest, E, }); - return subBehavior(powers); + return coreProposalBehavior(powers); }), ); };