Skip to content

Commit

Permalink
feat(extract-proposal): named proposals with expressed needs
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Sep 21, 2023
1 parent e6eb616 commit 7b0d456
Showing 1 changed file with 55 additions and 30 deletions.
85 changes: 55 additions & 30 deletions packages/deploy-script-support/src/extract-proposal.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import fs from 'fs';
import { createRequire } from 'module';
import path from 'path';

import { solveDependencies } from '@agoric/internal/src/dep-solver.js';
import { defangAndTrim, stringify } from './code-gen.js';
import {
makeCoreProposalBehavior,
makeEnactCoreProposalsFromBundleRef,
} from './coreProposalBehavior.js';

/**
* @typedef {string | { module: string, entrypoint: string, args?: Array<unknown> }} ConfigProposal
* @typedef {string | {
* module: string, entrypoint: string, args?: Array<unknown>, needs?: unknown
* }} ConfigProposal
*/

const { details: X, Fail } = assert;
Expand Down Expand Up @@ -43,16 +46,22 @@ const findModule = (initDir, srcSpec) =>
/**
* @param {{ bundleID?: string, bundleName?: string }} handle - mutated then hardened
* @param {string} sourceSpec - the specifier of a module to load
* @param {number} sequence - the sequence number of the proposal
* @param {PropertyKey} key - the key of the proposal
* @param {string} piece - the piece of the proposal
* @returns {Promise<[string, any]>}
*/
const namedHandleToBundleSpec = async (handle, sourceSpec, sequence, piece) => {
handle.bundleName = `coreProposal${sequence}_${piece}`;
const namedHandleToBundleSpec = async (handle, sourceSpec, key, piece) => {
handle.bundleName = `coreProposal${String(key)}_${piece}`;
harden(handle);
return harden([handle.bundleName, { sourceSpec }]);
};

/**
* @param {unknown[] | Record<PropertyKey, unknown>} obj
*/
const getKeys = obj =>
Reflect.ownKeys(obj).filter(key => key !== 'length' || !Array.isArray(obj));

/**
* Format core proposals to be run at bootstrap:
* SwingSet `bundles` configuration
Expand All @@ -64,12 +73,12 @@ const namedHandleToBundleSpec = async (handle, sourceSpec, sequence, piece) => {
* but for sim-chain and such, they can be declared statically in
* the chain configuration, in which case they are run at bootstrap.
*
* @param {ConfigProposal[]} coreProposals - governance
* @param {ConfigProposal[] | Record<PropertyKey, ConfigProposal>} coreProposals - governance
* proposals to run at chain bootstrap for scenarios such as sim-chain.
* @param {FilePath} [dirname]
* @param {object} [opts]
* @param {typeof makeEnactCoreProposalsFromBundleRef} [opts.makeEnactCoreProposals]
* @param {(i: number) => number} [opts.getSequenceForProposal]
* @param {(key: PropertyKey) => PropertyKey} [opts.getSequenceForProposal]
* @param {typeof namedHandleToBundleSpec} [opts.handleToBundleSpec]
*/
export const extractCoreProposalBundles = async (
Expand All @@ -79,7 +88,7 @@ export const extractCoreProposalBundles = async (
) => {
const {
makeEnactCoreProposals = makeEnactCoreProposalsFromBundleRef,
getSequenceForProposal = i => i,
getSequenceForProposal = key => key,
handleToBundleSpec = namedHandleToBundleSpec,
} = opts || {};

Expand All @@ -92,8 +101,9 @@ export const extractCoreProposalBundles = async (
const bundleHandleToAbsolutePaths = new Map();

const bundleToSource = new Map();
const extracted = await Promise.all(
coreProposals.map(async (coreProposal, i) => {
const extractedEntries = await Promise.all(
getKeys(coreProposals).map(async key => {
const coreProposal = coreProposals[key];
// console.debug(`Parsing core proposal:`, coreProposal);

/** @type {string} */
Expand All @@ -102,12 +112,15 @@ export const extractCoreProposalBundles = async (
let args;
/** @type {string} */
let module;
/** @type {unknown} */
let needs;
if (typeof coreProposal === 'string') {
module = coreProposal;
entrypoint = 'defaultProposalBuilder';
args = [];
needs = null;
} else {
({ module, entrypoint, args = [] } = coreProposal);
({ module, entrypoint, args = [], needs } = coreProposal);
}

typeof module === 'string' ||
Expand All @@ -118,7 +131,7 @@ export const extractCoreProposalBundles = async (

const thisProposalBundleHandles = new Set();
assert(getSequenceForProposal);
const thisProposalSequence = getSequenceForProposal(i);
const thisProposalSequence = getSequenceForProposal(key);
const initPath = findModule(dirname, module);
const initDir = path.dirname(initPath);
/** @type {Record<string, import('./externalTypes.js').ProposalBuilder>} */
Expand Down Expand Up @@ -224,31 +237,41 @@ export const extractCoreProposalBundles = async (
}),
);

return harden({
ref: behaviorBundleHandle,
call: getManifestCall,
overrideManifest,
bundleSpecs: bundleSpecEntries,
});
return /** @type {const} */ ([
key,
{
ref: behaviorBundleHandle,
call: getManifestCall,
overrideManifest,
bundleSpecs: bundleSpecEntries,
needs,
},
]);
}),
);

// Extract all the bundle specs in already-sorted order.
const bundles = Object.fromEntries(
extracted.flatMap(({ bundleSpecs }) => bundleSpecs),
extractedEntries.flatMap(([_key, { bundleSpecs }]) => bundleSpecs),
);
harden(bundles);

// Extract the manifest references and calls.
const makeCPArgs = extracted.map(({ ref, call, overrideManifest }) => ({
ref,
call,
overrideManifest,
}));
harden(makeCPArgs);
// Use `extracted[k].needs` to create a dependency graph, then divide it into
// steps, each of which contains core proposals that are executed in parallel.
const extracted = {};
for (const [key, value] of extractedEntries) {
extracted[key] = value;
}
const codeSteps = solveDependencies(extracted).map(extractedStep => {
// Extract the manifest references and calls.
const makeCPArgs = getKeys(extractedStep).map(key => {
const { ref, call, overrideManifest } = extractedStep[key];
return { ref, call, overrideManifest };
});
harden(makeCPArgs);

const code = `\
// This is generated by @agoric/cosmic-swingset/src/extract-proposal.js - DO NOT EDIT
const code = `\
// This is generated by @agoric/deploy-script-support/src/extract-proposal.js - DO NOT EDIT
/* eslint-disable */
const makeCoreProposalArgs = harden(${stringify(makeCPArgs, true)});
Expand All @@ -257,11 +280,13 @@ const makeCoreProposalBehavior = ${makeCoreProposalBehavior};
(${makeEnactCoreProposals})({ makeCoreProposalArgs, E });
`;
return defangAndTrim(code);
});

// console.debug('created bundles from proposals:', coreProposals, bundles);
return {
return harden({
bundles,
code: defangAndTrim(code),
codeSteps,
bundleHandleToAbsolutePaths,
};
});
};

0 comments on commit 7b0d456

Please sign in to comment.