Skip to content

Commit

Permalink
Merge pull request #8712 from Agoric/gibson-2024-01-cleanup-corepropo…
Browse files Browse the repository at this point in the history
…salbehavior

chore(deploy-script-support): Sync code patterns across files
  • Loading branch information
mergify[bot] authored and mhofman committed Jan 13, 2024
2 parents 325e87b + 94b9f84 commit 2dd32a2
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 62 deletions.
65 changes: 42 additions & 23 deletions packages/deploy-script-support/src/coreProposalBehavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ const t = 'makeCoreProposalBehavior';
* @typedef {*} BootstrapPowers
*/

/**
* @typedef {import('./externalTypes.js').ManifestBundleRef} ManifestBundleRef
* @typedef {[methodName: string, ...args: unknown[]]} FlatMethargs
* @typedef {Record<string, Record<string, unknown>>} Manifest
*/

/**
* These permits are expected to be the minimum powers required by the
* `coreProposalBehavior` function returned from `makeCoreProposalBehavior`.
Expand All @@ -30,22 +36,22 @@ export const permits = {
* for catching bugs. Thus, this maker must not reference any other modules or
* definitions.
*
* @param {object} opts
* @param {import('./externalTypes.js').ManifestBundleRef} opts.manifestBundleRef
* @param {[methodName: string, ...args: unknown[]]} opts.getManifestCall
* @param {Record<string, Record<string, unknown>>} [opts.overrideManifest]
* @param {typeof import('@endo/far').E} opts.E
* @param {(...args: unknown[]) => void} [opts.log]
* @param {(ref: import('./externalTypes.js').ManifestBundleRef) => Promise<import('@agoric/zoe/src/zoeService/utils.js').Installation<unknown>>} [opts.restoreRef]
* @param {object} inputs
* @param {ManifestBundleRef} inputs.manifestBundleRef
* @param {FlatMethargs} inputs.getManifestCall
* @param {Manifest} [inputs.customManifest]
* @param {typeof import('@endo/far').E} inputs.E
* @param {(...args: unknown[]) => void} [inputs.log]
* @param {(ref: import('./externalTypes.js').ManifestBundleRef) => Promise<import('@agoric/zoe/src/zoeService/utils.js').Installation<unknown>>} [inputs.customRestoreRef]
* @returns {(vatPowers: unknown) => Promise<unknown>}
*/
export const makeCoreProposalBehavior = ({
manifestBundleRef,
getManifestCall: [manifestGetterName, ...manifestGetterArgs],
overrideManifest,
customManifest,
E,
log = console.info,
restoreRef: overrideRestoreRef,
customRestoreRef,
}) => {
const { entries, fromEntries } = Object;

Expand Down Expand Up @@ -136,7 +142,7 @@ export const makeCoreProposalBehavior = ({
manifestGetterName,
bundleExports: Object.keys(proposalNS),
});
const restoreRef = overrideRestoreRef || makeRestoreRef(vatAdminSvc, zoe);
const restoreRef = customRestoreRef || makeRestoreRef(vatAdminSvc, zoe);
const {
manifest,
options: rawOptions,
Expand All @@ -152,20 +158,23 @@ export const makeCoreProposalBehavior = ({
);

// Publish the installations for our dependencies.
const installAdmin = E(agoricNamesAdmin).lookupAdmin('installation');
await Promise.all(
entries(installations || {}).map(([key, value]) => {
produceInstallations[key].resolve(value);
return E(installAdmin).update(key, value);
}),
);
const installationEntries = entries(installations || {});
if (installationEntries.length > 0) {
const installAdmin = E(agoricNamesAdmin).lookupAdmin('installation');
await Promise.all(
installationEntries.map(([key, value]) => {
produceInstallations[key].resolve(value);
return E(installAdmin).update(key, value);
}),
);
}

// Evaluate the manifest.
return runModuleBehaviors({
// Remember that `powers` may be arbitrarily broad.
allPowers: powers,
behaviors: proposalNS,
manifest: overrideManifest || manifest,
manifest: customManifest || manifest,
makeConfig: (name, _permit) => {
log('coreProposal:', name);
return { options };
Expand All @@ -176,18 +185,28 @@ export const makeCoreProposalBehavior = ({
return coreProposalBehavior;
};

export const makeEnactCoreProposalsFromBundleRef =
({ makeCoreProposalArgs, E }) =>
async powers => {
/**
* @param {object} inputs
* @param {Array<{ ref: ManifestBundleRef, call: FlatMethargs, customManifest?: Manifest }>} inputs.metadataRecords
* @param {typeof import('@endo/far').E} inputs.E
*/
export const makeEnactCoreProposalsFromBundleRef = ({ metadataRecords, E }) => {
/**
* @param {ChainBootstrapSpace & BootstrapPowers & { evaluateBundleCap: any }} powers
* @returns {Promise<void>}
*/
const enactCoreProposals = async powers => {
await Promise.all(
makeCoreProposalArgs.map(async ({ ref, call, overrideManifest }) => {
metadataRecords.map(async ({ ref, call, customManifest }) => {
const coreProposalBehavior = makeCoreProposalBehavior({
manifestBundleRef: ref,
getManifestCall: call,
overrideManifest,
customManifest,
E,
});
return coreProposalBehavior(powers);
}),
);
};
return enactCoreProposals;
};
59 changes: 31 additions & 28 deletions packages/deploy-script-support/src/extract-proposal.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
* @typedef {string | { module: string, entrypoint: string, args?: Array<unknown> }} ConfigProposal
*/

const { details: X, Fail } = assert;
const { Fail } = assert;

const req = createRequire(import.meta.url);

Expand All @@ -24,8 +24,8 @@ const req = createRequire(import.meta.url);
* @typedef {string} FilePath
*/
const pathResolve = (...paths) => {
const fileName = paths.pop();
assert(fileName, '>=1 paths required');
const fileName = /** @type {string} */ (paths.pop());
fileName || Fail`base name required`;
try {
return req.resolve(fileName, {
paths,
Expand Down Expand Up @@ -132,11 +132,8 @@ export const extractCoreProposalBundles = async (
absolutePaths.bundle = absoluteBundle;
const oldSource = bundleToSource.get(absoluteBundle);
if (oldSource) {
assert.equal(
oldSource,
absoluteSrc,
X`${bundlePath} already installed from ${oldSource}, now ${absoluteSrc}`,
);
oldSource === absoluteSrc ||
Fail`${bundlePath} already installed from ${oldSource}, now ${absoluteSrc}`;
} else {
bundleToSource.set(absoluteBundle, absoluteSrc);
}
Expand Down Expand Up @@ -197,21 +194,20 @@ export const extractCoreProposalBundles = async (
harden(proposal),
);

const behaviorSource = pathResolve(initDir, sourceSpec);
const behaviors = await import(behaviorSource);
const [exportedGetManifest, ...manifestArgs] = getManifestCall;
assert(
exportedGetManifest in behaviors,
`behavior ${behaviorSource} missing ${exportedGetManifest}`,
const proposalSource = pathResolve(initDir, sourceSpec);
const proposalNS = await import(proposalSource);
const [manifestGetterName, ...manifestGetterArgs] = getManifestCall;
manifestGetterName in proposalNS ||
Fail`proposal ${proposalSource} missing export ${manifestGetterName}`;
const { manifest: customManifest } = await proposalNS[manifestGetterName](
harden({ restoreRef: () => null }),
...manifestGetterArgs,
);
const { manifest: overrideManifest } = await behaviors[
exportedGetManifest
](harden({ restoreRef: () => null }), ...manifestArgs);

const behaviorBundleHandle = {};
const specEntry = await handleToBundleSpec(
behaviorBundleHandle,
behaviorSource,
proposalSource,
thisProposalSequence,
'behaviors',
);
Expand All @@ -220,14 +216,14 @@ export const extractCoreProposalBundles = async (
bundleHandleToAbsolutePaths.set(
behaviorBundleHandle,
harden({
source: behaviorSource,
source: proposalSource,
}),
);

return harden({
ref: behaviorBundleHandle,
call: getManifestCall,
overrideManifest,
customManifest,
bundleSpecs: bundleSpecEntries,
});
}),
Expand All @@ -240,22 +236,29 @@ export const extractCoreProposalBundles = async (
harden(bundles);

// Extract the manifest references and calls.
const makeCPArgs = extracted.map(({ ref, call, overrideManifest }) => ({
const metadataRecords = extracted.map(({ ref, call, customManifest }) => ({
ref,
call,
overrideManifest,
customManifest,
}));
harden(makeCPArgs);
harden(metadataRecords);

const code = `\
// This is generated by @agoric/cosmic-swingset/src/extract-proposal.js - DO NOT EDIT
// This is generated by @agoric/deploy-script-support/src/extract-proposal.js - DO NOT EDIT
/* eslint-disable */
const makeCoreProposalArgs = harden(${stringify(makeCPArgs, true)});
const makeCoreProposalBehavior = ${makeCoreProposalBehavior};
const metadataRecords = harden(${stringify(metadataRecords, true)});
(${makeEnactCoreProposals})({ makeCoreProposalArgs, E });
// Make an enactCoreProposals function and "export" it by way of script completion value.
// It is constructed by an IIFE to ensure the absence of global bindings for
// makeCoreProposalBehavior and makeEnactCoreProposals (the latter referencing the former),
// which may not be necessary but preserves behavior pre-dating
// https://github.com/Agoric/agoric-sdk/pull/8712 .
const enactCoreProposals = ((
makeCoreProposalBehavior = ${makeCoreProposalBehavior},
makeEnactCoreProposals = ${makeEnactCoreProposals},
) => makeEnactCoreProposals({ metadataRecords, E }))();
enactCoreProposals;
`;

// console.debug('created bundles from proposals:', coreProposals, bundles);
Expand Down
26 changes: 15 additions & 11 deletions packages/deploy-script-support/src/writeCoreProposal.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ export const makeWriteCoreProposal = (
const mergeProposalPermit = async (proposal, additionalPermits) => {
const {
sourceSpec,
getManifestCall: [exportedGetManifest, ...manifestArgs],
getManifestCall: [manifestGetterName, ...manifestGetterArgs],
} = proposal;

const manifestNs = await import(pathResolve(sourceSpec));
const proposalNS = await import(pathResolve(sourceSpec));

// We only care about the manifest, not any restoreRef calls.
const { manifest } = await manifestNs[exportedGetManifest](
{ restoreRef: x => `restoreRef:${x}` },
...manifestArgs,
const { manifest } = await proposalNS[manifestGetterName](
harden({ restoreRef: x => `restoreRef:${x}` }),
...manifestGetterArgs,
);

const mergedPermits = mergePermits(manifest);
Expand Down Expand Up @@ -98,7 +98,7 @@ export const makeWriteCoreProposal = (
*
* @param {string} entrypoint
* @param {string} [bundlePath]
* @param [opts]
* @param {unknown} [opts]
* @returns {Promise<import('./externalTypes.js').ManifestBundleRef>}
*/
const install = async (entrypoint, bundlePath, opts) => {
Expand Down Expand Up @@ -137,7 +137,7 @@ export const makeWriteCoreProposal = (
// console.log('created', { filePrefix, sourceSpec, getManifestCall });

// Extract the top-level permit.
const { permits: proposalPermit, manifest: overrideManifest } =
const { permits: proposalPermit, manifest: customManifest } =
await mergeProposalPermit(proposal, permits);

// Get an install
Expand All @@ -150,10 +150,14 @@ export const makeWriteCoreProposal = (
const manifestBundleRef = ${stringify(manifestBundleRef)};
const getManifestCall = harden(${stringify(getManifestCall, true)});
const overrideManifest = ${stringify(overrideManifest, true)};
// Make the behavior the completion value.
(${makeCoreProposalBehavior})({ manifestBundleRef, getManifestCall, overrideManifest, E });
const customManifest = ${stringify(customManifest, true)};
// Make a behavior function and "export" it by way of script completion value.
// It is constructed by an anonymous invocation to ensure the absence of a global binding
// for makeCoreProposalBehavior, which may not be necessary but preserves behavior pre-dating
// https://github.com/Agoric/agoric-sdk/pull/8712 .
const behavior = (${makeCoreProposalBehavior})({ manifestBundleRef, getManifestCall, customManifest, E });
behavior;
`;

const trimmed = defangAndTrim(code);
Expand Down

0 comments on commit 2dd32a2

Please sign in to comment.