From e3ba536c569796533ba91eecc203095b9493e251 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 23 Feb 2023 17:14:21 -0600 Subject: [PATCH 01/38] test(vats): factor out t.context.loadBundle() - confine ambient authority to test set-up region - fix some static typing --- packages/vats/test/test-boot.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/vats/test/test-boot.js b/packages/vats/test/test-boot.js index eb6d3ef7124..2005fb24196 100644 --- a/packages/vats/test/test-boot.js +++ b/packages/vats/test/test-boot.js @@ -2,7 +2,7 @@ // eslint-disable-next-line import/no-extraneous-dependencies import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; import { makeFakeVatAdmin } from '@agoric/zoe/tools/fakeVatAdmin.js'; -import bundleSource from '@endo/bundle-source'; +import bundleSourceAmbient from '@endo/bundle-source'; import { E, passStyleOf } from '@endo/far'; import { eventLoopIteration } from '@agoric/zoe/tools/eventLoopIteration.js'; @@ -56,15 +56,17 @@ testRole('chain', true); testRole('sim-chain', false); testRole('sim-chain', true); -test('evaluateBundleCap is available to core eval', async t => { +test('evaluateBundleCap is available to core eval', async (/** @type {ECtx} */ t) => { + const { loadBundle } = t.context; + /** @type {undefined | import('../src/types.js').BridgeHandler} */ let handler; - const modulePath = new URL('../src/core/utils.js', import.meta.url).pathname; const { produce, consume } = makePromiseSpace(t.log); const { admin, vatAdminState } = makeFakeVatAdmin(); const vatPowers = vatAdminState.getVatPowers(); const prepare = async () => { - const bundle = await bundleSource(modulePath); + const bundle = await loadBundle('../src/core/utils.js'); + if (bundle.moduleFormat !== 'endoZipBase64') throw t.fail(); const bundleID = bundle.endoZipBase64Sha512; vatAdminState.installBundle(bundleID, bundle); const bridgeManager = { @@ -81,7 +83,7 @@ test('evaluateBundleCap is available to core eval', async t => { // @ts-expect-error await bridgeCoreEval({ vatPowers, produce, consume }); - t.truthy(handler); + if (!handler) throw t.fail(); const produceThing = async ({ consume: { vatAdminSvc }, @@ -105,7 +107,6 @@ test('evaluateBundleCap is available to core eval', async t => { }; t.log({ bridgeMessage }); - // @ts-expect-error await E(handler).fromBridge(bridgeMessage); const actual = await consume.thing; From 4812005b47d6b95aa5ac2169a3dce20cc7b1e5df Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 24 Feb 2023 16:24:42 -0600 Subject: [PATCH 02/38] test(solo): confine ambient authority to setup --- packages/solo/test/test-home.js | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/packages/solo/test/test-home.js b/packages/solo/test/test-home.js index 35ad5f7b693..4a93cfc8578 100644 --- a/packages/solo/test/test-home.js +++ b/packages/solo/test/test-home.js @@ -2,7 +2,7 @@ import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; -import bundleSource from '@endo/bundle-source'; +import bundleSourceAmbient from '@endo/bundle-source'; import { AmountMath } from '@agoric/ertp'; import { Stable } from '@agoric/vats/src/tokens.js'; import { Far } from '@endo/marshal'; @@ -12,20 +12,29 @@ import { makeFixture, E } from './captp-fixture.js'; const SOLO_PORT = 7999; -// This runs before all the tests. -let home; -let teardown; +// #region setup (ambient authority is confined to this region) test.before('setup', async t => { + const loadBundle = async specifier => { + const contractUrl = await importMetaResolve(specifier, import.meta.url); + const contractRoot = new URL(contractUrl).pathname; + t.log({ contractRoot }); + const bundle = await bundleSourceAmbient(contractRoot); + return bundle; + }; const { homeP, kill } = await makeFixture(SOLO_PORT, process.env.NOISY); - teardown = kill; - home = await homeP; + const home = await homeP; + + t.context = { home, teardown: kill, loadBundle }; + t.truthy('ready'); }); +// #endregion // Now come the tests that use `home`... // ========================================= test.serial('home.board', async t => { + const { home } = t.context; const { board } = E.get(home); await t.throwsAsync( () => E(board).getValue('board0120'), @@ -50,6 +59,7 @@ test.serial('home.board', async t => { }); test.serial('home.wallet - transfer funds to the feePurse', async t => { + const { home } = t.context; const { wallet, faucet } = E.get(home); const feePurse = E(faucet).getFeePurse(); const feeBrand = await E(feePurse).getAllegedBrand(); @@ -62,16 +72,13 @@ test.serial('home.wallet - transfer funds to the feePurse', async t => { }); test.serial('home.wallet - receive zoe invite', async t => { + const { home, loadBundle } = t.context; const { wallet, zoe, board } = E.get(home); // Setup contract in order to get an invite to use in tests - const contractUrl = await importMetaResolve( + const bundle = await loadBundle( '@agoric/zoe/src/contracts/automaticRefund.js', - import.meta.url, ); - const contractRoot = new URL(contractUrl).pathname; - t.log({ contractRoot }); - const bundle = await bundleSource(contractRoot); const installationHandle = await E(zoe).install(bundle); const { creatorInvitation: invite } = await E(zoe).startInstance( installationHandle, @@ -113,6 +120,7 @@ test.serial('home.wallet - receive zoe invite', async t => { }); test.serial('home.wallet - central issuer setup', async t => { + const { home } = t.context; const { wallet } = E.get(home); // Check that the wallet knows about the central issuer. @@ -127,6 +135,7 @@ test.serial('home.wallet - central issuer setup', async t => { }); test.serial('home.localTimerService makeNotifier', async t => { + const { home } = t.context; const { localTimerService } = E.get(home); const notifier = E(localTimerService).makeNotifier(1n, 1n); const update1 = await E(notifier).getUpdateSince(); @@ -158,6 +167,7 @@ function makeHandler() { } test.serial('home.localTimerService makeRepeater', async t => { + const { home } = t.context; const { localTimerService } = E.get(home); const timestamp = await E(localTimerService).getCurrentTimestamp(); const repeater = E(localTimerService).makeRepeater(1n, 1n); @@ -173,6 +183,7 @@ test.serial('home.localTimerService makeRepeater', async t => { // ========================================= // This runs after all the tests. test.after.always('teardown', async t => { + const { teardown } = t.context; await teardown(); t.truthy('shutdown'); }); From e2906f2daaff997628027185fdfc27a90243946a Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 25 Feb 2023 10:30:27 -0600 Subject: [PATCH 03/38] test(vats): stub test for bootstrap upgrade --- .../vats/test/upgrading/test-upgrade-vats.js | 97 +++++++++++-------- 1 file changed, 59 insertions(+), 38 deletions(-) diff --git a/packages/vats/test/upgrading/test-upgrade-vats.js b/packages/vats/test/upgrading/test-upgrade-vats.js index ee6fb9ec8fa..77c5a905313 100644 --- a/packages/vats/test/upgrading/test-upgrade-vats.js +++ b/packages/vats/test/upgrading/test-upgrade-vats.js @@ -2,14 +2,24 @@ import { test as anyTest } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; import { buildVatController } from '@agoric/swingset-vat'; -import { kunser } from '@agoric/swingset-vat/src/lib/kmarshal.js'; +import { makeRunUtils } from '../bootstrapTests/supports.js'; + +const resolveAssetModule = specifier => + new URL(specifier, import.meta.url).pathname; +const bundleSpecs = { + relay: { + // XXX cross-package asset module + sourceSpec: resolveAssetModule('../../../SwingSet/test/bootstrap-relay.js'), + }, + board: { sourceSpec: resolveAssetModule('../../src/vat-board.js') }, + chain: { sourceSpec: resolveAssetModule('../../src/core/boot-chain.js') }, +}; /** @type {import('ava').TestFn>>} */ const test = anyTest; -const makeTestContext = async metaUrl => { - const bfile = name => new URL(name, metaUrl).pathname; - return { bfile }; +const makeTestContext = async () => { + return {}; }; /** @@ -20,64 +30,75 @@ test.before(async t => { t.context = await makeTestContext(import.meta.url); }); -test('upgrade vat-board', async t => { - const { bfile } = t.context; - +const makeScenario = async (t, bundles) => { /** @type {SwingSetConfig} */ const config = { includeDevDependencies: true, // for vat-data - defaultManagerType: 'xs-worker', + defaultManagerType: 'local', // better debugging bootstrap: 'bootstrap', defaultReapInterval: 'never', vats: { - bootstrap: { - sourceSpec: bfile('../../../SwingSet/test/bootstrap-relay.js'), - }, - }, - bundles: { - board: { sourceSpec: bfile('../../src/vat-board.js') }, + bootstrap: bundleSpecs.relay, }, + bundles, }; const c = await buildVatController(config); t.teardown(c.shutdown); c.pinVatRoot('bootstrap'); - await c.run(); + const runUtils = makeRunUtils(c, t.log); - const run = async (method, args = []) => { - assert(Array.isArray(args)); - const kpid = c.queueToVatRoot('bootstrap', method, args); - await c.run(); - const status = c.kpStatus(kpid); - if (status === 'fulfilled') { - const result = c.kpResolution(kpid); - return kunser(result); - } - assert(status === 'rejected'); - const err = c.kpResolution(kpid); - throw kunser(err); + return runUtils; +}; + +test('upgrade vat-board', async t => { + const bundles = { + board: bundleSpecs.board, }; - const messageVat = (name, methodName, args) => - run('messageVat', [{ name, methodName, args }]); - const messageObject = (presence, methodName, args) => - run('messageVatObject', [{ presence, methodName, args }]); + const { EV } = await makeScenario(t, bundles); t.log('create initial version'); const boardVatConfig = { name: 'board', bundleCapName: 'board', }; - await run('createVat', [boardVatConfig]); - const board = await messageVat('board', 'getBoard', []); - const thing = await run('makeSimpleRemotable', ['Thing', {}]); - const thingId = await messageObject(board, 'getId', [thing]); + await EV.vat('bootstrap').createVat(boardVatConfig); + const board = await EV.vat('board').getBoard(); + const thing = await EV.vat('bootstrap').makeSimpleRemotable('Thing', {}); + const thingId = await EV(board).getId(thing); t.regex(thingId, /^board0[0-9]+$/); t.log('now perform the null upgrade'); - const { incarnationNumber } = await run('upgradeVat', [boardVatConfig]); + const { incarnationNumber } = await EV.vat('bootstrap').upgradeVat( + boardVatConfig, + ); t.is(incarnationNumber, 2, 'Board vat must be upgraded'); - const board2 = await messageVat('board', 'getBoard', []); + const board2 = await EV.vat('board').getBoard(); t.is(board2, board, 'must get the same board reference'); - const actualThing = await messageObject(board2, 'getValue', [thingId]); + const actualThing = await EV(board2).getValue(thingId); t.is(actualThing, thing, 'must get original value back'); }); + +test.skip('upgrade bootstrap vat', async t => { + const bundles = { + chain: bundleSpecs.chain, + }; + const { EV } = await makeScenario(t, bundles); + + t.log('create initial version'); + const chainVatConfig = { + name: 'chain', + bundleCapName: 'chain', + }; + await EV.vat('bootstrap').createVat(chainVatConfig); + await EV.vat('chain') + .bootstrap({}, {}) + .catch(problem => t.log('TODO: address problem:', problem)); + + t.log('now perform the null upgrade'); + + const { incarnationNumber } = await EV.vat('bootstrap').upgradeVat( + chainVatConfig, + ); + t.is(incarnationNumber, 2, 'vat must be upgraded'); +}); From ae56f4e7c4ba11c4e2b1d4ee373ee46586b7cc58 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Tue, 21 Feb 2023 17:00:16 -0600 Subject: [PATCH 04/38] refactor(vats): factor out lib-boot.js --- packages/vats/src/core/boot.js | 154 ++---------------- packages/vats/src/core/lib-boot.js | 142 ++++++++++++++++ packages/vats/test/bootstrapTests/supports.js | 2 +- 3 files changed, 158 insertions(+), 140 deletions(-) create mode 100644 packages/vats/src/core/lib-boot.js diff --git a/packages/vats/src/core/boot.js b/packages/vats/src/core/boot.js index 72622efdb78..7890873db6a 100644 --- a/packages/vats/src/core/boot.js +++ b/packages/vats/src/core/boot.js @@ -1,13 +1,5 @@ // @ts-check -import { E, Far } from '@endo/far'; - import * as simBehaviors from '@agoric/inter-protocol/src/proposals/sim-behaviors.js'; -import { makePassableEncoding } from '@agoric/swingset-vat/tools/passableEncoding.js'; -import { - makeAgoricNamesAccess, - makePromiseSpace, - runModuleBehaviors, -} from './utils.js'; import { CLIENT_BOOTSTRAP_MANIFEST, CHAIN_BOOTSTRAP_MANIFEST, @@ -17,8 +9,9 @@ import { import * as behaviors from './behaviors.js'; import * as clientBehaviors from './client-behaviors.js'; import * as utils from './utils.js'; +import { makeBootstrap } from './lib-boot.js'; -const { Fail, quote: q } = assert; +const { Fail } = assert; // Choose a manifest based on runtime configured argv.ROLE. const roleToManifest = harden({ @@ -45,13 +38,7 @@ const roleToBehaviors = harden({ * coreProposalCode?: string, * }} vatParameters */ -const buildRootObject = (vatPowers, vatParameters) => { - const log = vatPowers.logger || console.info; - const { produce, consume } = makePromiseSpace(log); - const { agoricNames, agoricNamesAdmin, spaces } = makeAgoricNamesAccess(log); - produce.agoricNames.resolve(agoricNames); - produce.agoricNamesAdmin.resolve(agoricNamesAdmin); - +export const buildRootObject = (vatPowers, vatParameters) => { const { // XXX not for production ?! argv: { ROLE = 'chain' }, @@ -65,131 +52,20 @@ const buildRootObject = (vatPowers, vatParameters) => { bootManifest || Fail`no configured bootstrapManifest for role ${ROLE}`; bootBehaviors || Fail`no configured bootstrapBehaviors for role ${ROLE}`; - /** - * Bootstrap vats and devices. - * - * @param {SwingsetVats} vats - * @param {SoloDevices | ChainDevices} devices - */ - const rawBootstrap = async (vats, devices) => { - // Complete SwingSet wiring. - const { D } = vatPowers; - if (devices.mailbox) { - D(devices.mailbox).registerInboundHandler(vats.vattp); - // eslint-disable-next-line @jessie.js/no-nested-await -- XXX - await E(vats.vattp).registerMailboxDevice(devices.mailbox); - } else { - console.warn('No mailbox device. Not registering with vattp'); - } - - const runBehaviors = manifest => { - return runModuleBehaviors({ - // eslint-disable-next-line no-use-before-define - allPowers, - behaviors: bootBehaviors, - manifest, - makeConfig: (name, permit) => { - log(`bootstrap: ${name}(${q(permit)}`); - return vatParameters[name]; - }, - }); - }; - - // TODO: Aspires to be BootstrapPowers, but it's too specific. - const allPowers = harden({ - vatPowers, - vatParameters, - vats, - devices, - produce, - consume, - ...spaces, - runBehaviors, - // These module namespaces might be useful for core eval governance. - modules: { - clientBehaviors: { ...clientBehaviors }, - simBehaviors: { ...simBehaviors }, - behaviors: { ...behaviors }, - utils: { ...utils }, - }, - }); - - await runBehaviors(bootManifest); - - const { coreProposalCode } = vatParameters; - if (!coreProposalCode) { - return; - } - - // Start the governance from the core proposals. - const coreEvalMessage = { - type: 'CORE_EVAL', - evals: [ - { - json_permits: 'true', - js_code: coreProposalCode, - }, - ], - }; - /** @type {any} */ - const { coreEvalBridgeHandler } = consume; - await E(coreEvalBridgeHandler).fromBridge(coreEvalMessage); + const modules = { + clientBehaviors: { ...clientBehaviors }, + simBehaviors: { ...simBehaviors }, + behaviors: { ...behaviors }, + utils: { ...utils }, }; - // For testing supports - const vatData = new Map(); - const { encodePassable, decodePassable } = makePassableEncoding(); - - return Far('bootstrap', { - bootstrap: (vats, devices) => { - for (const [name, root] of Object.entries(vats)) { - if (name !== 'vatAdmin') { - vatData.set(name, { root }); - } - } - rawBootstrap(vats, devices).catch(e => { - console.error('BOOTSTRAP FAILED:', e); - throw e; - }); - }, - consumeItem: name => { - assert.typeof(name, 'string'); - return consume[name]; - }, - produceItem: (name, resolution) => { - assert.typeof(name, 'string'); - produce[name].resolve(resolution); - }, - resetItem: name => { - assert.typeof(name, 'string'); - produce[name].reset(); - }, - - // #region testing supports - messageVat: async ({ name, methodName, args = [] }) => { - const vat = vatData.get(name) || Fail`unknown vat name: ${q(name)}`; - const { root } = vat; - const decodedArgs = args.map(decodePassable); - const result = await E(root)[methodName](...decodedArgs); - return encodePassable(result); - }, - messageVatObject: async ({ presence, methodName, args = [] }) => { - const object = decodePassable(presence); - const decodedArgs = args.map(decodePassable); - const result = await E(object)[methodName](...decodedArgs); - return encodePassable(result); - }, - awaitVatObject: async ({ presence, path = [] }) => { - let value = await decodePassable(presence); - for (const key of path) { - // eslint-disable-next-line no-await-in-loop - value = await value[key]; - } - return encodePassable(value); - }, - // #endregion - }); + return makeBootstrap( + vatPowers, + vatParameters, + bootManifest, + behaviors, + modules, + ); }; harden({ buildRootObject }); -export { buildRootObject }; diff --git a/packages/vats/src/core/lib-boot.js b/packages/vats/src/core/lib-boot.js new file mode 100644 index 00000000000..5e5b865e1c9 --- /dev/null +++ b/packages/vats/src/core/lib-boot.js @@ -0,0 +1,142 @@ +import { E, Far } from '@endo/far'; +import { makePassableEncoding } from '@agoric/swingset-vat/tools/passableEncoding.js'; +import { + makeAgoricNamesAccess, + makePromiseSpace, + runModuleBehaviors, +} from './utils.js'; + +const { Fail, quote: q } = assert; + +export const makeBootstrap = ( + vatPowers, + vatParameters, + bootManifest, + behaviors, + modules, +) => { + const log = vatPowers.logger || console.info; + const { produce, consume } = makePromiseSpace(log); + const { agoricNames, agoricNamesAdmin, spaces } = makeAgoricNamesAccess(log); + produce.agoricNames.resolve(agoricNames); + produce.agoricNamesAdmin.resolve(agoricNamesAdmin); + + /** + * Bootstrap vats and devices. + * + * @param {SwingsetVats} vats + * @param {SoloDevices | ChainDevices} devices + */ + const rawBootstrap = async (vats, devices) => { + // Complete SwingSet wiring. + const { D } = vatPowers; + if (!devices.mailbox) { + console.warn('No mailbox device. Not registering with vattp'); + } + await (devices.mailbox && + (D(devices.mailbox).registerInboundHandler(vats.vattp), + E(vats.vattp).registerMailboxDevice(devices.mailbox))); + + const runBehaviors = manifest => { + return runModuleBehaviors({ + // eslint-disable-next-line no-use-before-define + allPowers, + behaviors, + manifest, + makeConfig: (name, permit) => { + log(`bootstrap: ${name}(${q(permit)}`); + return vatParameters[name]; + }, + }); + }; + + // TODO: Aspires to be BootstrapPowers, but it's too specific. + const allPowers = harden({ + vatPowers, + vatParameters, + vats, + devices, + produce, + consume, + ...spaces, + runBehaviors, + // These module namespaces might be useful for core eval governance. + modules, + }); + + await runBehaviors(bootManifest); + + const { coreProposalCode } = vatParameters; + if (!coreProposalCode) { + return; + } + + // Start the governance from the core proposals. + const coreEvalMessage = { + type: 'CORE_EVAL', + evals: [ + { + json_permits: 'true', + js_code: coreProposalCode, + }, + ], + }; + /** @type {any} */ + const { coreEvalBridgeHandler } = consume; + await E(coreEvalBridgeHandler).fromBridge(coreEvalMessage); + }; + + // For testing supports + const vatData = new Map(); + const { encodePassable, decodePassable } = makePassableEncoding(); + + return Far('bootstrap', { + bootstrap: (vats, devices) => { + for (const [name, root] of Object.entries(vats)) { + if (name !== 'vatAdmin') { + vatData.set(name, { root }); + } + } + rawBootstrap(vats, devices).catch(e => { + console.error('BOOTSTRAP FAILED:', e); + throw e; + }); + }, + consumeItem: name => { + assert.typeof(name, 'string'); + return consume[name]; + }, + produceItem: (name, resolution) => { + assert.typeof(name, 'string'); + produce[name].resolve(resolution); + }, + resetItem: name => { + assert.typeof(name, 'string'); + produce[name].reset(); + }, + + // #region testing supports + messageVat: async ({ name, methodName, args = [] }) => { + const vat = vatData.get(name) || Fail`unknown vat name: ${q(name)}`; + const { root } = vat; + const decodedArgs = args.map(decodePassable); + const result = await E(root)[methodName](...decodedArgs); + return encodePassable(result); + }, + messageVatObject: async ({ presence, methodName, args = [] }) => { + const object = decodePassable(presence); + const decodedArgs = args.map(decodePassable); + const result = await E(object)[methodName](...decodedArgs); + return encodePassable(result); + }, + awaitVatObject: async ({ presence, path = [] }) => { + let value = await decodePassable(presence); + for (const key of path) { + // eslint-disable-next-line no-await-in-loop + value = await value[key]; + } + return encodePassable(value); + }, + // #endregion + }); +}; diff --git a/packages/vats/test/bootstrapTests/supports.js b/packages/vats/test/bootstrapTests/supports.js index 96666f0f53d..ecc48327d3a 100644 --- a/packages/vats/test/bootstrapTests/supports.js +++ b/packages/vats/test/bootstrapTests/supports.js @@ -11,7 +11,7 @@ import { promises as fs } from 'fs'; import { resolve as importMetaResolve } from 'import-meta-resolve'; import { boardSlottingMarshaller } from '../../tools/board-utils.js'; -/** @typedef {ReturnType} BootstrapRootObject */ +/** @typedef {ReturnType} BootstrapRootObject */ /** @type {Record} */ export const bootstrapMethods = { From 23999a534251984b4d6545c0dec71f01113930c0 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Tue, 21 Feb 2023 17:02:01 -0600 Subject: [PATCH 05/38] refactor(vats): copy boot.js for chain, sim, solo --- packages/vats/decentral-devnet-config.json | 2 +- .../vats/src/core/{boot.js => boot-chain.js} | 0 packages/vats/src/core/boot-sim.js | 69 +++++++++++++++++++ packages/vats/src/core/boot-solo.js | 69 +++++++++++++++++++ 4 files changed, 139 insertions(+), 1 deletion(-) rename packages/vats/src/core/{boot.js => boot-chain.js} (100%) create mode 100644 packages/vats/src/core/boot-sim.js create mode 100644 packages/vats/src/core/boot-solo.js diff --git a/packages/vats/decentral-devnet-config.json b/packages/vats/decentral-devnet-config.json index fe001159c19..332784bbbe3 100644 --- a/packages/vats/decentral-devnet-config.json +++ b/packages/vats/decentral-devnet-config.json @@ -106,7 +106,7 @@ ], "vats": { "bootstrap": { - "sourceSpec": "@agoric/vats/src/core/boot.js", + "sourceSpec": "@agoric/vats/src/core/boot-chain.js", "creationOptions": { "critical": true } diff --git a/packages/vats/src/core/boot.js b/packages/vats/src/core/boot-chain.js similarity index 100% rename from packages/vats/src/core/boot.js rename to packages/vats/src/core/boot-chain.js diff --git a/packages/vats/src/core/boot-sim.js b/packages/vats/src/core/boot-sim.js new file mode 100644 index 00000000000..fbaed1ff644 --- /dev/null +++ b/packages/vats/src/core/boot-sim.js @@ -0,0 +1,69 @@ +// @ts-check +import * as simBehaviors from '@agoric/inter-protocol/src/proposals/sim-behaviors.js'; +import { + CLIENT_BOOTSTRAP_MANIFEST, + CHAIN_BOOTSTRAP_MANIFEST, + SIM_CHAIN_BOOTSTRAP_MANIFEST, +} from './manifest.js'; + +import * as behaviors from './behaviors.js'; +import * as clientBehaviors from './client-behaviors.js'; +import * as utils from './utils.js'; +import { makeBootstrap } from './lib-boot.js'; + +const { Fail } = assert; + +// Choose a manifest based on runtime configured argv.ROLE. +const roleToManifest = harden({ + chain: CHAIN_BOOTSTRAP_MANIFEST, + 'sim-chain': SIM_CHAIN_BOOTSTRAP_MANIFEST, + client: CLIENT_BOOTSTRAP_MANIFEST, +}); +const roleToBehaviors = harden({ + 'sim-chain': { ...behaviors, ...simBehaviors }, + // copy to avoid trying to harden a module namespace + client: { ...clientBehaviors }, +}); + +/** + * Build root object of the bootstrap vat. + * + * @param {{ + * D: DProxy, + * logger: (msg) => void, + * }} vatPowers + * @param {{ + * argv: { ROLE: string }, + * bootstrapManifest?: Record>, + * coreProposalCode?: string, + * }} vatParameters + */ +export const buildRootObject = (vatPowers, vatParameters) => { + const { + argv: { ROLE }, + bootstrapManifest, + } = vatParameters; + console.debug(`${ROLE} bootstrap starting`); + + const bootManifest = bootstrapManifest || roleToManifest[ROLE]; + const bootBehaviors = roleToBehaviors[ROLE] || behaviors; + bootManifest || Fail`no configured bootstrapManifest for role ${ROLE}`; + bootBehaviors || Fail`no configured bootstrapBehaviors for role ${ROLE}`; + + const modules = { + clientBehaviors: { ...clientBehaviors }, + simBehaviors: { ...simBehaviors }, + behaviors: { ...behaviors }, + utils: { ...utils }, + }; + + return makeBootstrap( + vatPowers, + vatParameters, + bootManifest, + behaviors, + modules, + ); +}; + +harden({ buildRootObject }); diff --git a/packages/vats/src/core/boot-solo.js b/packages/vats/src/core/boot-solo.js new file mode 100644 index 00000000000..fbaed1ff644 --- /dev/null +++ b/packages/vats/src/core/boot-solo.js @@ -0,0 +1,69 @@ +// @ts-check +import * as simBehaviors from '@agoric/inter-protocol/src/proposals/sim-behaviors.js'; +import { + CLIENT_BOOTSTRAP_MANIFEST, + CHAIN_BOOTSTRAP_MANIFEST, + SIM_CHAIN_BOOTSTRAP_MANIFEST, +} from './manifest.js'; + +import * as behaviors from './behaviors.js'; +import * as clientBehaviors from './client-behaviors.js'; +import * as utils from './utils.js'; +import { makeBootstrap } from './lib-boot.js'; + +const { Fail } = assert; + +// Choose a manifest based on runtime configured argv.ROLE. +const roleToManifest = harden({ + chain: CHAIN_BOOTSTRAP_MANIFEST, + 'sim-chain': SIM_CHAIN_BOOTSTRAP_MANIFEST, + client: CLIENT_BOOTSTRAP_MANIFEST, +}); +const roleToBehaviors = harden({ + 'sim-chain': { ...behaviors, ...simBehaviors }, + // copy to avoid trying to harden a module namespace + client: { ...clientBehaviors }, +}); + +/** + * Build root object of the bootstrap vat. + * + * @param {{ + * D: DProxy, + * logger: (msg) => void, + * }} vatPowers + * @param {{ + * argv: { ROLE: string }, + * bootstrapManifest?: Record>, + * coreProposalCode?: string, + * }} vatParameters + */ +export const buildRootObject = (vatPowers, vatParameters) => { + const { + argv: { ROLE }, + bootstrapManifest, + } = vatParameters; + console.debug(`${ROLE} bootstrap starting`); + + const bootManifest = bootstrapManifest || roleToManifest[ROLE]; + const bootBehaviors = roleToBehaviors[ROLE] || behaviors; + bootManifest || Fail`no configured bootstrapManifest for role ${ROLE}`; + bootBehaviors || Fail`no configured bootstrapBehaviors for role ${ROLE}`; + + const modules = { + clientBehaviors: { ...clientBehaviors }, + simBehaviors: { ...simBehaviors }, + behaviors: { ...behaviors }, + utils: { ...utils }, + }; + + return makeBootstrap( + vatPowers, + vatParameters, + bootManifest, + behaviors, + modules, + ); +}; + +harden({ buildRootObject }); From 00b385b166240fd9aa5918f8d098885cb2e6e244 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 24 Feb 2023 19:54:55 -0600 Subject: [PATCH 06/38] chore(vats): separate sim, client, chain boot behaviors - update boot-psm.js now that manifest.js is gone - move BootstrapManifest type to lib-boot.js chore(vats): reorg boot-chain, chain-behaviors - restore test-boot.js tests - static types for test-boot.js and boot-*.js - prune argvByRole - no more export * - lib-boot: early check for missing behavior - basic-behaviors.js: - organize imports a bit - all behaviors return Promise use await rather than return - export BASIC_BOOTSTRAP_PERMITS - boot-chain.js: - destructure non-behaviors out of import * - hoist modules - chain-behaviors: factor BASIC_BOOTSTRAP_PERMITS out of SHARED_CHAIN_BOOTSTRAP_MANIFEST --- packages/vats/decentral-core-config.json | 2 +- .../vats/decentral-test-vaults-config.json | 2 +- packages/vats/index.js | 1 - packages/vats/src/core/basic-behaviors.js | 133 ++++++- packages/vats/src/core/behaviors.js | 4 - packages/vats/src/core/boot-chain.js | 75 ++-- packages/vats/src/core/boot-psm.js | 2 +- packages/vats/src/core/boot-sim.js | 73 ++-- packages/vats/src/core/boot-solo.js | 76 ++-- packages/vats/src/core/chain-behaviors.js | 96 ++++- packages/vats/src/core/client-behaviors.js | 39 ++- packages/vats/src/core/lib-boot.js | 43 +++ packages/vats/src/core/manifest.js | 328 ------------------ packages/vats/test/test-boot.js | 92 ++--- 14 files changed, 439 insertions(+), 527 deletions(-) delete mode 100644 packages/vats/src/core/behaviors.js delete mode 100644 packages/vats/src/core/manifest.js diff --git a/packages/vats/decentral-core-config.json b/packages/vats/decentral-core-config.json index f106850083a..3560c10fc93 100644 --- a/packages/vats/decentral-core-config.json +++ b/packages/vats/decentral-core-config.json @@ -3,7 +3,7 @@ "defaultReapInterval": 1000, "vats": { "bootstrap": { - "sourceSpec": "@agoric/vats/src/core/boot.js", + "sourceSpec": "@agoric/vats/src/core/boot-chain.js", "creationOptions": { "critical": true } diff --git a/packages/vats/decentral-test-vaults-config.json b/packages/vats/decentral-test-vaults-config.json index 186a66518ac..0f497fe61f2 100644 --- a/packages/vats/decentral-test-vaults-config.json +++ b/packages/vats/decentral-test-vaults-config.json @@ -149,7 +149,7 @@ ], "vats": { "bootstrap": { - "sourceSpec": "@agoric/vats/src/core/boot.js", + "sourceSpec": "@agoric/vats/src/core/boot-chain.js", "creationOptions": { "critical": true } diff --git a/packages/vats/index.js b/packages/vats/index.js index d6eaf085e1a..c6a8bb5d12b 100644 --- a/packages/vats/index.js +++ b/packages/vats/index.js @@ -2,7 +2,6 @@ // Ambient types import './src/core/types.js'; -export * from './src/core/boot.js'; // eslint-disable-next-line import/export -- no named exports export * from './src/types.js'; export * from './src/nameHub.js'; diff --git a/packages/vats/src/core/basic-behaviors.js b/packages/vats/src/core/basic-behaviors.js index f4b2ddc3d0c..7fc1ed25968 100644 --- a/packages/vats/src/core/basic-behaviors.js +++ b/packages/vats/src/core/basic-behaviors.js @@ -1,10 +1,10 @@ // @ts-check -import { AssetKind, makeIssuerKit } from '@agoric/ertp'; import { Nat } from '@endo/nat'; +import { E, Far } from '@endo/far'; +import { AssetKind, makeIssuerKit } from '@agoric/ertp'; import { makeScalarMapStore } from '@agoric/store'; import { provideLazy } from '@agoric/store/src/stores/store-utils.js'; -import { E, Far } from '@endo/far'; import { BridgeId, VBankAccount, WalletName } from '@agoric/internal'; import { makeNameHubKit } from '../nameHub.js'; import { feeIssuerConfig } from './utils.js'; @@ -124,9 +124,7 @@ export const buildZoe = async ({ invitationBrand.resolve(brand); feeMintAccess.resolve(fma); - return Promise.all([ - E(client).assignBundle([_addr => ({ zoe: zoeService })]), - ]); + await Promise.all([E(client).assignBundle([_addr => ({ zoe: zoeService })])]); }; harden(buildZoe); @@ -422,7 +420,7 @@ export const addBankAssets = async ({ produceIssuer.IST.resolve(runKit.issuer); produceBrand.BLD.resolve(bldKit.brand); produceBrand.IST.resolve(runKit.brand); - return Promise.all([ + await Promise.all([ E(bankMgr).addAsset( Stake.denom, Stake.symbol, @@ -438,3 +436,126 @@ export const addBankAssets = async ({ ]); }; harden(addBankAssets); + +/** @type {import('./lib-boot').BootstrapManifest} */ +export const BASIC_BOOTSTRAP_PERMITS = harden({ + /** @type {import('./lib-boot').BootstrapManifestPermit} */ + bridgeCoreEval: true, // Needs all the powers. + [makeOracleBrands.name]: { + oracleBrand: { + produce: { + USD: true, + }, + }, + }, + [startPriceAuthority.name]: { + consume: { loadCriticalVat: true, client: true }, + produce: { + priceAuthorityVat: 'priceAuthority', + priceAuthority: 'priceAuthority', + priceAuthorityAdmin: 'priceAuthority', + }, + }, + [makeVatsFromBundles.name]: { + vats: { + vatAdmin: 'vatAdmin', + }, + devices: { + vatAdmin: true, + }, + produce: { + vatAdminSvc: 'vatAdmin', + loadVat: true, + loadCriticalVat: true, + vatStore: true, + }, + }, + [buildZoe.name]: { + consume: { + vatAdminSvc: true, + loadCriticalVat: true, + client: true, + }, + produce: { + zoe: 'zoe', + feeMintAccess: 'zoe', + }, + issuer: { produce: { Invitation: 'zoe' } }, + brand: { produce: { Invitation: 'zoe' } }, + }, + [makeBoard.name]: { + consume: { + loadCriticalVat: true, + client: true, + }, + produce: { + board: 'board', + }, + }, + + [makeAddressNameHubs.name]: { + consume: { + agoricNames: true, + client: true, + }, + produce: { + namesByAddress: true, + namesByAddressAdmin: true, + }, + home: { + produce: { myAddressNameAdmin: true }, + }, + }, + [makeClientBanks.name]: { + consume: { + namesByAddressAdmin: true, + bankManager: 'bank', + client: true, + walletFactoryStartResult: 'walletFactory', + }, + home: { produce: { bank: 'bank' } }, + }, + [installBootContracts.name]: { + consume: { zoe: 'zoe', vatAdminSvc: true }, + installation: { + produce: { + centralSupply: 'zoe', + mintHolder: 'zoe', + }, + }, + }, + [mintInitialSupply.name]: { + vatParameters: { + argv: { bootMsg: true }, + }, + consume: { + feeMintAccess: true, + zoe: true, + }, + produce: { + initialSupply: true, + }, + installation: { + consume: { centralSupply: 'zoe' }, + }, + }, + [addBankAssets.name]: { + consume: { + agoricNamesAdmin: true, + initialSupply: true, + bridgeManager: true, + // TODO: re-org loadCriticalVat to be subject to permits + loadCriticalVat: true, + zoe: true, + }, + produce: { + bankManager: 'bank', + bldIssuerKit: true, + }, + installation: { + consume: { centralSupply: 'zoe', mintHolder: 'zoe' }, + }, + issuer: { produce: { BLD: 'BLD', IST: 'zoe' } }, + brand: { produce: { BLD: 'BLD', IST: 'zoe' } }, + }, +}); diff --git a/packages/vats/src/core/behaviors.js b/packages/vats/src/core/behaviors.js deleted file mode 100644 index ed8f3f01a32..00000000000 --- a/packages/vats/src/core/behaviors.js +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-check -export * from './basic-behaviors.js'; -export * from './chain-behaviors.js'; -// We exclude sim-behaviors.js from this list because it should not be used in production. diff --git a/packages/vats/src/core/boot-chain.js b/packages/vats/src/core/boot-chain.js index 7890873db6a..635aab47634 100644 --- a/packages/vats/src/core/boot-chain.js +++ b/packages/vats/src/core/boot-chain.js @@ -1,29 +1,30 @@ // @ts-check -import * as simBehaviors from '@agoric/inter-protocol/src/proposals/sim-behaviors.js'; -import { - CLIENT_BOOTSTRAP_MANIFEST, - CHAIN_BOOTSTRAP_MANIFEST, - SIM_CHAIN_BOOTSTRAP_MANIFEST, -} from './manifest.js'; - -import * as behaviors from './behaviors.js'; -import * as clientBehaviors from './client-behaviors.js'; -import * as utils from './utils.js'; import { makeBootstrap } from './lib-boot.js'; -const { Fail } = assert; +import * as basicBehaviorsPlus from './basic-behaviors.js'; +import { CHAIN_BOOTSTRAP_MANIFEST } from './chain-behaviors.js'; +import * as chainBehaviorsPlus from './chain-behaviors.js'; +import * as utils from './utils.js'; -// Choose a manifest based on runtime configured argv.ROLE. -const roleToManifest = harden({ - chain: CHAIN_BOOTSTRAP_MANIFEST, - 'sim-chain': SIM_CHAIN_BOOTSTRAP_MANIFEST, - client: CLIENT_BOOTSTRAP_MANIFEST, -}); -const roleToBehaviors = harden({ - 'sim-chain': { ...behaviors, ...simBehaviors }, - // copy to avoid trying to harden a module namespace - client: { ...clientBehaviors }, -}); +export const MANIFEST = CHAIN_BOOTSTRAP_MANIFEST; + +const { + BASIC_BOOTSTRAP_PERMITS: _b, + PowerFlags: _p, + makeMyAddressNameAdminKit: _m, + ...basicBehaviors +} = basicBehaviorsPlus; +const { + CHAIN_BOOTSTRAP_MANIFEST: _c, + SHARED_CHAIN_BOOTSTRAP_MANIFEST: _s, + ...chainBehaviors +} = chainBehaviorsPlus; +const behaviors = { ...basicBehaviors, ...chainBehaviors }; + +const modules = { + behaviors: { ...behaviors }, + utils: { ...utils }, +}; /** * Build root object of the bootstrap vat. @@ -33,39 +34,13 @@ const roleToBehaviors = harden({ * logger: (msg) => void, * }} vatPowers * @param {{ - * argv: { ROLE: string }, - * bootstrapManifest?: Record>, * coreProposalCode?: string, * }} vatParameters */ export const buildRootObject = (vatPowers, vatParameters) => { - const { - // XXX not for production ?! - argv: { ROLE = 'chain' }, - bootstrapManifest, - } = vatParameters; - // ROLE || Fail`boot requires ROLE in argv`; - console.debug(`${ROLE} bootstrap starting`); - - const bootManifest = bootstrapManifest || roleToManifest[ROLE]; - const bootBehaviors = roleToBehaviors[ROLE] || behaviors; - bootManifest || Fail`no configured bootstrapManifest for role ${ROLE}`; - bootBehaviors || Fail`no configured bootstrapBehaviors for role ${ROLE}`; - - const modules = { - clientBehaviors: { ...clientBehaviors }, - simBehaviors: { ...simBehaviors }, - behaviors: { ...behaviors }, - utils: { ...utils }, - }; + console.debug(`chain bootstrap starting`); - return makeBootstrap( - vatPowers, - vatParameters, - bootManifest, - behaviors, - modules, - ); + return makeBootstrap(vatPowers, vatParameters, MANIFEST, behaviors, modules); }; harden({ buildRootObject }); diff --git a/packages/vats/src/core/boot-psm.js b/packages/vats/src/core/boot-psm.js index 07b22226ef1..07e53c9f3c1 100644 --- a/packages/vats/src/core/boot-psm.js +++ b/packages/vats/src/core/boot-psm.js @@ -40,8 +40,8 @@ import { noProvisioner, publishAgoricNames, startTimerService, + CHAIN_BOOTSTRAP_MANIFEST, } from './chain-behaviors.js'; -import { CHAIN_BOOTSTRAP_MANIFEST } from './manifest.js'; import { startWalletFactory, WALLET_FACTORY_MANIFEST, diff --git a/packages/vats/src/core/boot-sim.js b/packages/vats/src/core/boot-sim.js index fbaed1ff644..8c6f2b01bc6 100644 --- a/packages/vats/src/core/boot-sim.js +++ b/packages/vats/src/core/boot-sim.js @@ -1,69 +1,46 @@ // @ts-check -import * as simBehaviors from '@agoric/inter-protocol/src/proposals/sim-behaviors.js'; -import { - CLIENT_BOOTSTRAP_MANIFEST, - CHAIN_BOOTSTRAP_MANIFEST, - SIM_CHAIN_BOOTSTRAP_MANIFEST, -} from './manifest.js'; +import { SIM_CHAIN_BOOTSTRAP_PERMITS } from '@agoric/inter-protocol/src/proposals/sim-behaviors.js'; +import * as simBehaviorsPlus from '@agoric/inter-protocol/src/proposals/sim-behaviors.js'; +import * as basicBehaviorsPlus from './basic-behaviors.js'; +import { SHARED_CHAIN_BOOTSTRAP_MANIFEST } from './chain-behaviors.js'; +import * as chainBehaviorsPlus from './chain-behaviors.js'; -import * as behaviors from './behaviors.js'; -import * as clientBehaviors from './client-behaviors.js'; -import * as utils from './utils.js'; import { makeBootstrap } from './lib-boot.js'; -const { Fail } = assert; +export const MANIFEST = { + ...SHARED_CHAIN_BOOTSTRAP_MANIFEST, + ...SIM_CHAIN_BOOTSTRAP_PERMITS, +}; -// Choose a manifest based on runtime configured argv.ROLE. -const roleToManifest = harden({ - chain: CHAIN_BOOTSTRAP_MANIFEST, - 'sim-chain': SIM_CHAIN_BOOTSTRAP_MANIFEST, - client: CLIENT_BOOTSTRAP_MANIFEST, -}); -const roleToBehaviors = harden({ - 'sim-chain': { ...behaviors, ...simBehaviors }, - // copy to avoid trying to harden a module namespace - client: { ...clientBehaviors }, -}); +const { + BASIC_BOOTSTRAP_PERMITS: _b, + PowerFlags: _p, + makeMyAddressNameAdminKit: _m, + ...basicBehaviors +} = basicBehaviorsPlus; +const { + CHAIN_BOOTSTRAP_MANIFEST: _c, + SHARED_CHAIN_BOOTSTRAP_MANIFEST: _s, + ...chainBehaviors +} = chainBehaviorsPlus; +const { SIM_CHAIN_BOOTSTRAP_PERMITS: _sc, ...simBehaviors } = simBehaviorsPlus; +const behaviors = { ...basicBehaviors, ...chainBehaviors, ...simBehaviors }; /** - * Build root object of the bootstrap vat. + * Build root object of the bootstrap vat for the simulated chain. * * @param {{ * D: DProxy, * logger: (msg) => void, * }} vatPowers * @param {{ - * argv: { ROLE: string }, - * bootstrapManifest?: Record>, * coreProposalCode?: string, * }} vatParameters */ export const buildRootObject = (vatPowers, vatParameters) => { - const { - argv: { ROLE }, - bootstrapManifest, - } = vatParameters; - console.debug(`${ROLE} bootstrap starting`); - - const bootManifest = bootstrapManifest || roleToManifest[ROLE]; - const bootBehaviors = roleToBehaviors[ROLE] || behaviors; - bootManifest || Fail`no configured bootstrapManifest for role ${ROLE}`; - bootBehaviors || Fail`no configured bootstrapBehaviors for role ${ROLE}`; - - const modules = { - clientBehaviors: { ...clientBehaviors }, - simBehaviors: { ...simBehaviors }, - behaviors: { ...behaviors }, - utils: { ...utils }, - }; + console.debug(`sim bootstrap starting`); - return makeBootstrap( - vatPowers, - vatParameters, - bootManifest, - behaviors, - modules, - ); + return makeBootstrap(vatPowers, vatParameters, MANIFEST, behaviors, {}); }; harden({ buildRootObject }); diff --git a/packages/vats/src/core/boot-solo.js b/packages/vats/src/core/boot-solo.js index fbaed1ff644..c99b19c5243 100644 --- a/packages/vats/src/core/boot-solo.js +++ b/packages/vats/src/core/boot-solo.js @@ -1,28 +1,38 @@ // @ts-check -import * as simBehaviors from '@agoric/inter-protocol/src/proposals/sim-behaviors.js'; -import { - CLIENT_BOOTSTRAP_MANIFEST, - CHAIN_BOOTSTRAP_MANIFEST, - SIM_CHAIN_BOOTSTRAP_MANIFEST, -} from './manifest.js'; - -import * as behaviors from './behaviors.js'; -import * as clientBehaviors from './client-behaviors.js'; -import * as utils from './utils.js'; import { makeBootstrap } from './lib-boot.js'; -const { Fail } = assert; +import * as basicBehaviorsPlus from './basic-behaviors.js'; +import * as chainBehaviorsPlus from './chain-behaviors.js'; +import { CLIENT_BOOTSTRAP_MANIFEST } from './client-behaviors.js'; +import * as clientBehaviorsPlus from './client-behaviors.js'; +import * as utils from './utils.js'; -// Choose a manifest based on runtime configured argv.ROLE. -const roleToManifest = harden({ - chain: CHAIN_BOOTSTRAP_MANIFEST, - 'sim-chain': SIM_CHAIN_BOOTSTRAP_MANIFEST, - client: CLIENT_BOOTSTRAP_MANIFEST, +export const MANIFEST = CLIENT_BOOTSTRAP_MANIFEST; + +// XXX export basicBehaviors record from basic-behaviors.js? +const { + BASIC_BOOTSTRAP_PERMITS: _b, + PowerFlags: _p, + makeMyAddressNameAdminKit: _m, + ...basicBehaviors +} = basicBehaviorsPlus; +const { + CHAIN_BOOTSTRAP_MANIFEST: _c, + SHARED_CHAIN_BOOTSTRAP_MANIFEST: _s, + ...chainBehaviors +} = chainBehaviorsPlus; +const { CLIENT_BOOTSTRAP_MANIFEST: _cb, ...clientBehaviors } = + clientBehaviorsPlus; +const behaviors = harden({ + ...basicBehaviors, + ...chainBehaviors, + ...clientBehaviors, }); -const roleToBehaviors = harden({ - 'sim-chain': { ...behaviors, ...simBehaviors }, - // copy to avoid trying to harden a module namespace - client: { ...clientBehaviors }, + +const modules = harden({ + clientBehaviors: { ...clientBehaviors }, + behaviors: { ...behaviors }, + utils: { ...utils }, }); /** @@ -39,31 +49,9 @@ const roleToBehaviors = harden({ * }} vatParameters */ export const buildRootObject = (vatPowers, vatParameters) => { - const { - argv: { ROLE }, - bootstrapManifest, - } = vatParameters; - console.debug(`${ROLE} bootstrap starting`); - - const bootManifest = bootstrapManifest || roleToManifest[ROLE]; - const bootBehaviors = roleToBehaviors[ROLE] || behaviors; - bootManifest || Fail`no configured bootstrapManifest for role ${ROLE}`; - bootBehaviors || Fail`no configured bootstrapBehaviors for role ${ROLE}`; - - const modules = { - clientBehaviors: { ...clientBehaviors }, - simBehaviors: { ...simBehaviors }, - behaviors: { ...behaviors }, - utils: { ...utils }, - }; + console.debug(`solo client bootstrap starting`); - return makeBootstrap( - vatPowers, - vatParameters, - bootManifest, - behaviors, - modules, - ); + return makeBootstrap(vatPowers, vatParameters, MANIFEST, behaviors, modules); }; harden({ buildRootObject }); diff --git a/packages/vats/src/core/chain-behaviors.js b/packages/vats/src/core/chain-behaviors.js index cf9977943d3..9e0a6a2e32c 100644 --- a/packages/vats/src/core/chain-behaviors.js +++ b/packages/vats/src/core/chain-behaviors.js @@ -19,7 +19,7 @@ import { allValues, BridgeId as BRIDGE_ID } from '@agoric/internal'; import * as STORAGE_PATH from '@agoric/internal/src/chain-storage-paths.js'; import { agoricNamesReserved, callProperties, extractPowers } from './utils.js'; -import { PowerFlags } from './basic-behaviors.js'; +import { PowerFlags, BASIC_BOOTSTRAP_PERMITS } from './basic-behaviors.js'; const { Fail } = assert; const { keys } = Object; @@ -544,3 +544,97 @@ export const setupNetworkProtocols = async ({ await registerNetworkProtocols(vats, dibcBridgeManager); return E(client).assignBundle([_a => ({ ibcport: makePorts() })]); }; + +/** @type {import('./lib-boot').BootstrapManifest} */ +export const SHARED_CHAIN_BOOTSTRAP_MANIFEST = { + ...BASIC_BOOTSTRAP_PERMITS, + + [bridgeCoreEval.name]: true, // Needs all the powers. + [makeBridgeManager.name]: { + consume: { loadCriticalVat: true }, + devices: { bridge: 'kernel' }, + produce: { + bridgeManager: true, + provisionBridgeManager: true, + provisionWalletBridgeManager: true, + walletBridgeManager: true, + }, + }, + [startTimerService.name]: { + devices: { + timer: true, + }, + vats: { + timer: 'timer', + }, + consume: { client: true }, + produce: { + chainTimerService: 'timer', + }, + home: { produce: { chainTimerService: 'timer' } }, + }, + [makeChainStorage.name]: { + consume: { loadCriticalVat: true, bridgeManager: true }, + produce: { + chainStorage: 'chainStorage', + }, + }, + [publishAgoricNames.name]: { + consume: { + agoricNamesAdmin: true, + board: 'board', + chainStorage: 'chainStorage', + }, + }, + [makeProvisioner.name]: { + consume: { + loadCriticalVat: true, + clientCreator: true, + }, + produce: { + provisioning: 'provisioning', + }, + vats: { + comms: true, + vattp: true, + }, + }, + [bridgeProvisioner.name]: { + consume: { + provisioning: true, + bridgeManager: true, + provisionBridgeManager: true, + provisionWalletBridgeManager: true, + }, + }, + [setupClientManager.name]: { + produce: { + client: true, + clientCreator: true, + }, + }, + [setupNetworkProtocols.name]: { + consume: { + client: true, + loadCriticalVat: true, + bridgeManager: true, + zoe: true, + provisioning: true, + }, + produce: { + networkVat: true, + }, + }, +}; +harden(SHARED_CHAIN_BOOTSTRAP_MANIFEST); + +/** @type {import('./lib-boot.js').BootstrapManifest} */ +export const CHAIN_BOOTSTRAP_MANIFEST = harden({ + ...SHARED_CHAIN_BOOTSTRAP_MANIFEST, + [connectChainFaucet.name]: { + consume: { + client: true, + }, + home: { produce: { faucet: true } }, + }, +}); diff --git a/packages/vats/src/core/client-behaviors.js b/packages/vats/src/core/client-behaviors.js index dfd62fafd54..59b5c0f4820 100644 --- a/packages/vats/src/core/client-behaviors.js +++ b/packages/vats/src/core/client-behaviors.js @@ -4,8 +4,7 @@ import { makePluginManager } from '@agoric/swingset-vat/src/vats/plugin-manager. import { deeplyFulfilled } from '@endo/marshal'; import { observeNotifier } from '@agoric/notifier'; import { registerNetworkProtocols } from './chain-behaviors.js'; - -export { makeVatsFromBundles } from './basic-behaviors.js'; +import { makeVatsFromBundles } from './basic-behaviors.js'; const { Fail } = assert; @@ -164,3 +163,39 @@ export const startClient = async ({ await Promise.all([addLocalPresences(), addChainPresences()]); }; harden(startClient); + +/** @type {import('./lib-boot.js').BootstrapManifest} */ +export const CLIENT_BOOTSTRAP_MANIFEST = harden({ + /** @type {import('./lib-boot.js').BootstrapManifestPermit} */ + [makeVatsFromBundles.name]: { + vats: { + vatAdmin: 'vatAdmin', + }, + devices: { + vatAdmin: true, + }, + produce: { + vatAdminSvc: 'vatAdmin', + loadVat: true, + loadCriticalVat: true, + vatStore: true, + }, + }, + [startClient.name]: { + vatParameters: { + argv: { FIXME_GCI: true }, + }, + devices: { command: true, plugin: true, timer: true }, + vats: { + comms: true, + http: true, + network: true, + spawner: true, + timer: true, + uploads: true, + vattp: true, + }, + vatPowers: true, + consume: { vatAdminSvc: true }, + }, +}); diff --git a/packages/vats/src/core/lib-boot.js b/packages/vats/src/core/lib-boot.js index 5e5b865e1c9..726e7d721bd 100644 --- a/packages/vats/src/core/lib-boot.js +++ b/packages/vats/src/core/lib-boot.js @@ -1,3 +1,4 @@ +// @ts-check import { E, Far } from '@endo/far'; import { makePassableEncoding } from '@agoric/swingset-vat/tools/passableEncoding.js'; import { @@ -8,6 +9,44 @@ import { const { Fail, quote: q } = assert; +/** + * @typedef {true | string | { [key: string]: BootstrapManifestPermit }} BootstrapManifestPermit + */ + +/** + * A manifest is an object in which each key is the name of a function to run + * at bootstrap and the corresponding value is a "permit" describing an + * attenuation of allPowers that should be provided as its first argument + * (cf. packages/vats/src/core/boot.js). + * + * A permit is either + * - `true` or a string (both meaning no attenuation, with a string serving + * as a grouping label for convenience and diagram generation), or + * - an object whose keys identify properties to preserve and whose values + * are themselves (recursive) permits. + * + * @typedef {Record} BootstrapManifest + * + */ + +/** + * @typedef {(powers: *, config?: *) => Promise} BootBehavior + * @typedef {Record} ModuleNamespace + */ + +/** @type {(a: X[], b: X[]) => X[]} */ +const setDiff = (a, b) => a.filter(x => !b.includes(x)); + +/** + * @param {{ + * D: DProxy, + * logger: (msg) => void, + * }} vatPowers + * @param {Record} vatParameters + * @param {BootstrapManifest} bootManifest + * @param {Record} behaviors + * @param {Record} modules + */ export const makeBootstrap = ( vatPowers, vatParameters, @@ -15,6 +54,10 @@ export const makeBootstrap = ( behaviors, modules, ) => { + const { keys } = Object; + const extra = setDiff(keys(bootManifest), keys(behaviors)); + extra.length === 0 || Fail`missing behavior for manifest keys: ${extra}`; + const log = vatPowers.logger || console.info; const { produce, consume } = makePromiseSpace(log); const { agoricNames, agoricNamesAdmin, spaces } = makeAgoricNamesAccess(log); diff --git a/packages/vats/src/core/manifest.js b/packages/vats/src/core/manifest.js deleted file mode 100644 index ebd0ac94717..00000000000 --- a/packages/vats/src/core/manifest.js +++ /dev/null @@ -1,328 +0,0 @@ -// @ts-check - -import { - connectFaucet, - grantRunBehaviors, - installSimEgress, -} from '@agoric/inter-protocol/src/proposals/sim-behaviors.js'; -import { makeBoard } from '../lib-board.js'; -import { - addBankAssets, - buildZoe, - installBootContracts, - makeAddressNameHubs, - makeClientBanks, - makeOracleBrands, - makeVatsFromBundles, - mintInitialSupply, - startPriceAuthority, -} from './basic-behaviors.js'; -import { - bridgeProvisioner, - connectChainFaucet, - makeBridgeManager, - makeChainStorage, - makeProvisioner, - publishAgoricNames, - setupClientManager, - setupNetworkProtocols, - startTimerService, -} from './chain-behaviors.js'; -import { startClient } from './client-behaviors.js'; - -/** - * @typedef {true | string | { [key: string]: BootstrapManifestPermit }} BootstrapManifestPermit - */ - -/** - * A manifest is an object in which each key is the name of a function to run - * at bootstrap and the corresponding value is a "permit" describing an - * attenuation of allPowers that should be provided as its first argument - * (cf. packages/vats/src/core/boot.js). - * - * A permit is either - * - `true` or a string (both meaning no attenuation, with a string serving - * as a grouping label for convenience and diagram generation), or - * - an object whose keys identify properties to preserve and whose values - * are themselves (recursive) permits. - * - * @typedef {Record} BootstrapManifest - */ - -/** @type {BootstrapManifest} */ -const SHARED_CHAIN_BOOTSTRAP_MANIFEST = harden({ - /** @type {BootstrapManifestPermit} */ - bridgeCoreEval: true, // Needs all the powers. - [makeOracleBrands.name]: { - oracleBrand: { - produce: { - USD: true, - }, - }, - }, - [startPriceAuthority.name]: { - consume: { loadCriticalVat: true, client: true }, - produce: { - priceAuthorityVat: 'priceAuthority', - priceAuthority: 'priceAuthority', - priceAuthorityAdmin: 'priceAuthority', - }, - }, - [makeVatsFromBundles.name]: { - vats: { - vatAdmin: 'vatAdmin', - }, - devices: { - vatAdmin: true, - }, - produce: { - vatAdminSvc: 'vatAdmin', - loadVat: true, - loadCriticalVat: true, - vatStore: true, - }, - }, - [buildZoe.name]: { - consume: { - vatAdminSvc: true, - loadCriticalVat: true, - client: true, - }, - produce: { - zoe: 'zoe', - feeMintAccess: 'zoe', - }, - issuer: { produce: { Invitation: 'zoe' } }, - brand: { produce: { Invitation: 'zoe' } }, - }, - [makeBoard.name]: { - consume: { - loadCriticalVat: true, - client: true, - }, - produce: { - board: 'board', - }, - }, - [makeBridgeManager.name]: { - consume: { loadCriticalVat: true }, - devices: { bridge: 'kernel' }, - produce: { - bridgeManager: true, - provisionBridgeManager: true, - provisionWalletBridgeManager: true, - walletBridgeManager: true, - }, - }, - [makeAddressNameHubs.name]: { - consume: { - agoricNames: true, - client: true, - }, - produce: { - namesByAddress: true, - namesByAddressAdmin: true, - }, - home: { - produce: { myAddressNameAdmin: true }, - }, - }, - [startTimerService.name]: { - devices: { - timer: true, - }, - vats: { - timer: 'timer', - }, - consume: { client: true }, - produce: { - chainTimerService: 'timer', - }, - home: { produce: { chainTimerService: 'timer' } }, - }, - [makeChainStorage.name]: { - consume: { loadCriticalVat: true, bridgeManager: true }, - produce: { - chainStorage: 'chainStorage', - }, - }, - [publishAgoricNames.name]: { - consume: { - agoricNamesAdmin: true, - board: 'board', - chainStorage: 'chainStorage', - }, - }, - [makeClientBanks.name]: { - consume: { - namesByAddressAdmin: true, - bankManager: 'bank', - client: true, - walletFactoryStartResult: 'walletFactory', - }, - home: { produce: { bank: 'bank' } }, - }, - [installBootContracts.name]: { - consume: { zoe: 'zoe', vatAdminSvc: true }, - installation: { - produce: { - centralSupply: 'zoe', - mintHolder: 'zoe', - }, - }, - }, - [mintInitialSupply.name]: { - vatParameters: { - argv: { bootMsg: true }, - }, - consume: { - feeMintAccess: true, - zoe: true, - }, - produce: { - initialSupply: true, - }, - installation: { - consume: { centralSupply: 'zoe' }, - }, - }, - [addBankAssets.name]: { - consume: { - agoricNamesAdmin: true, - initialSupply: true, - bridgeManager: true, - // TODO: re-org loadCriticalVat to be subject to permits - loadCriticalVat: true, - zoe: true, - }, - produce: { - bankManager: 'bank', - bldIssuerKit: true, - }, - installation: { - consume: { centralSupply: 'zoe', mintHolder: 'zoe' }, - }, - issuer: { produce: { BLD: 'BLD', IST: 'zoe' } }, - brand: { produce: { BLD: 'BLD', IST: 'zoe' } }, - }, - [makeProvisioner.name]: { - consume: { - loadCriticalVat: true, - clientCreator: true, - }, - produce: { - provisioning: 'provisioning', - }, - vats: { - comms: true, - vattp: true, - }, - }, - [bridgeProvisioner.name]: { - consume: { - provisioning: true, - bridgeManager: true, - provisionBridgeManager: true, - provisionWalletBridgeManager: true, - }, - }, - [setupClientManager.name]: { - produce: { - client: true, - clientCreator: true, - }, - }, - [setupNetworkProtocols.name]: { - consume: { - client: true, - loadCriticalVat: true, - bridgeManager: true, - zoe: true, - provisioning: true, - }, - produce: { - networkVat: true, - }, - }, -}); - -/** @type {BootstrapManifest} */ -export const CHAIN_BOOTSTRAP_MANIFEST = harden({ - ...SHARED_CHAIN_BOOTSTRAP_MANIFEST, - [connectChainFaucet.name]: { - consume: { - client: true, - }, - home: { produce: { faucet: true } }, - }, -}); - -/** @type {BootstrapManifest} */ -export const CLIENT_BOOTSTRAP_MANIFEST = harden({ - /** @type {BootstrapManifestPermit} */ - [makeVatsFromBundles.name]: { - vats: { - vatAdmin: 'vatAdmin', - }, - devices: { - vatAdmin: true, - }, - produce: { - vatAdminSvc: 'vatAdmin', - loadVat: true, - loadCriticalVat: true, - vatStore: true, - }, - }, - [startClient.name]: { - vatParameters: { - argv: { FIXME_GCI: true }, - }, - devices: { command: true, plugin: true, timer: true }, - vats: { - comms: true, - http: true, - network: true, - spawner: true, - timer: true, - uploads: true, - vattp: true, - }, - vatPowers: true, - consume: { vatAdminSvc: true }, - }, -}); - -/** @type {BootstrapManifest} */ -export const SIM_CHAIN_BOOTSTRAP_MANIFEST = harden({ - ...SHARED_CHAIN_BOOTSTRAP_MANIFEST, - /** @type {BootstrapManifestPermit} */ - [installSimEgress.name]: { - vatParameters: { argv: { hardcodedClientAddresses: true } }, - vats: { - vattp: true, - comms: true, - }, - consume: { clientCreator: true }, - }, - [connectFaucet.name]: { - consume: { - bankManager: true, - bldIssuerKit: true, - client: true, - feeMintAccess: true, - loadVat: true, - zoe: true, - }, - installation: { - consume: { centralSupply: 'zoe' }, - }, - produce: { mints: true }, - home: { produce: { faucet: true } }, - }, - [grantRunBehaviors.name]: { - runBehaviors: true, - consume: { client: true }, - home: { produce: { runBehaviors: true, governanceActions: true } }, - }, -}); diff --git a/packages/vats/test/test-boot.js b/packages/vats/test/test-boot.js index 2005fb24196..88f2ee3dd5c 100644 --- a/packages/vats/test/test-boot.js +++ b/packages/vats/test/test-boot.js @@ -7,7 +7,9 @@ import { E, passStyleOf } from '@endo/far'; import { eventLoopIteration } from '@agoric/zoe/tools/eventLoopIteration.js'; import { buildRootObject as buildPSMRootObject } from '../src/core/boot-psm.js'; -import { buildRootObject } from '../src/core/boot.js'; +import { buildRootObject } from '../src/core/boot-chain.js'; +import { buildRootObject as buildSimRootObject } from '../src/core/boot-sim.js'; +import { buildRootObject as buildSoloRootObject } from '../src/core/boot-solo.js'; import { bridgeCoreEval } from '../src/core/chain-behaviors.js'; import { makePromiseSpace } from '../src/core/utils.js'; @@ -18,43 +20,60 @@ import { mockSwingsetVats, } from '../tools/boot-test-utils.js'; -const argvByRole = { - chain: { - ROLE: 'chain', - }, - 'sim-chain': { - ROLE: 'sim-chain', - FIXME_GCI: 'fake GCI', - hardcodedClientAddresses: ['a1'], - }, - client: { - ROLE: 'client', - FIXME_GCI: 'fake GCI', - hardcodedClientAddresses: ['a1'], - }, +// #region ambient authority limited to test set-up +/** @typedef {import('ava').ExecutionContext>} ECtx */ + +const makeTestContext = () => { + const bundleSource = bundleSourceAmbient; + const loadBundle = async specifier => { + const modulePath = new URL(specifier, import.meta.url).pathname; + /** @type {import('@agoric/swingset-vat').Bundle} */ + const bundle = await bundleSource(modulePath); + return bundle; + }; + + return { loadBundle }; }; -const testRole = (ROLE, governanceActions) => { - test(`test manifest permits: ${ROLE} gov: ${governanceActions}`, async t => { +test.before(t => { + t.context = makeTestContext(); +}); +// #endregion + +/** + * @callback BuildRootObject + * @param {{}} vatPowers + * @param {{}} vatParameters + * @param {import('@agoric/vat-data').Baggage} [baggage] + */ + +/** + * + * @param {string} label + * @param {BuildRootObject} entryPoint + * @param {boolean} doCoreProposals + */ +const testBootstrap = (label, entryPoint, doCoreProposals) => { + const vatParameters = { + argv: { + FIXME_GCI: 'fake GCI', + hardcodedClientAddresses: ['a1'], + }, + }; + + test(`test manifest permits: ${label} gov: ${doCoreProposals}`, async t => { const mock = makeMock(t.log); - const root = buildRootObject( - { D: mockDProxy, logger: t.log }, - { - argv: argvByRole[ROLE], - // @ts-expect-error XXX - governanceActions, - }, - ); + const vatPowers = { D: mockDProxy, logger: t.log }; + const root = entryPoint(vatPowers, vatParameters); const vats = mockSwingsetVats(mock); - const actual = await E(root).bootstrap(vats, mock.devices); - t.deepEqual(actual, undefined); + await t.notThrowsAsync(E(root).bootstrap(vats, mock.devices)); }); }; -testRole('client', false); -testRole('chain', false); -testRole('chain', true); -testRole('sim-chain', false); -testRole('sim-chain', true); +testBootstrap('client', buildSoloRootObject, false); +testBootstrap('chain', buildRootObject, false); +testBootstrap('chain', buildRootObject, true); +testBootstrap('sim', buildSimRootObject, false); +testBootstrap('sim', buildSimRootObject, true); test('evaluateBundleCap is available to core eval', async (/** @type {ECtx} */ t) => { const { loadBundle } = t.context; @@ -115,14 +134,7 @@ test('evaluateBundleCap is available to core eval', async (/** @type {ECtx} */ t }); test('bootstrap provides a way to pass items to CORE_EVAL', async t => { - const root = buildRootObject( - { D: mockDProxy, logger: t.log }, - { - argv: argvByRole.chain, - // @ts-expect-error XXX - governanceActions: false, - }, - ); + const root = buildRootObject({ D: mockDProxy, logger: t.log }, {}); await E(root).produceItem('swissArmyKnife', [1, 2, 3]); t.deepEqual(await E(root).consumeItem('swissArmyKnife'), [1, 2, 3]); From ef89a19c4b3bb70312a0d07c1a5b8b797fa85130 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 24 Feb 2023 14:49:15 -0600 Subject: [PATCH 07/38] chore(vats): CORE_EVAL expects utils module With an empty `modules` bootstrap power, `Cannot read properties of undefined (reading 'runModuleBehaviors')` ... was thrown in the code generated by makeWriteCoreProposal() in code-gen.js The initial symptoms were pretty obscure: ``` KERNEL PANIC: kp40.policy panic: rejected {"body":"#{\"#error\":\"behavior: cannot coerce undefined to object\" ``` These debug settings gave us a useful stack trace: `packages/solo/test$ DEBUG=SwingSet:ls,SwingSet:vat,track-turns ./startsolo.sh` The offending line is referring to `runModuleBehaviors` as a module global. So `Cannot read properties of undefined` seems to be SES-shim-speak for "Reference Error". --- packages/vats/src/core/boot-sim.js | 4 +++- packages/vats/src/core/lib-boot.js | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/vats/src/core/boot-sim.js b/packages/vats/src/core/boot-sim.js index 8c6f2b01bc6..c40aa401732 100644 --- a/packages/vats/src/core/boot-sim.js +++ b/packages/vats/src/core/boot-sim.js @@ -4,6 +4,7 @@ import * as simBehaviorsPlus from '@agoric/inter-protocol/src/proposals/sim-beha import * as basicBehaviorsPlus from './basic-behaviors.js'; import { SHARED_CHAIN_BOOTSTRAP_MANIFEST } from './chain-behaviors.js'; import * as chainBehaviorsPlus from './chain-behaviors.js'; +import * as utils from './utils.js'; import { makeBootstrap } from './lib-boot.js'; @@ -40,7 +41,8 @@ const behaviors = { ...basicBehaviors, ...chainBehaviors, ...simBehaviors }; export const buildRootObject = (vatPowers, vatParameters) => { console.debug(`sim bootstrap starting`); - return makeBootstrap(vatPowers, vatParameters, MANIFEST, behaviors, {}); + const modules = harden({ utils: { ...utils } }); + return makeBootstrap(vatPowers, vatParameters, MANIFEST, behaviors, modules); }; harden({ buildRootObject }); diff --git a/packages/vats/src/core/lib-boot.js b/packages/vats/src/core/lib-boot.js index 726e7d721bd..b1e177b52c8 100644 --- a/packages/vats/src/core/lib-boot.js +++ b/packages/vats/src/core/lib-boot.js @@ -32,6 +32,7 @@ const { Fail, quote: q } = assert; /** * @typedef {(powers: *, config?: *) => Promise} BootBehavior * @typedef {Record} ModuleNamespace + * @typedef {{ utils: typeof import('./utils.js') } & Record>} BootModules */ /** @type {(a: X[], b: X[]) => X[]} */ @@ -45,7 +46,7 @@ const setDiff = (a, b) => a.filter(x => !b.includes(x)); * @param {Record} vatParameters * @param {BootstrapManifest} bootManifest * @param {Record} behaviors - * @param {Record} modules + * @param {BootModules} modules */ export const makeBootstrap = ( vatPowers, From 821d0a11612fc6d5ac0d1eeb57641b8abef8a36c Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 24 Feb 2023 15:00:43 -0600 Subject: [PATCH 08/38] chore: use decentral-demo-config for sim chain Patterned after devnet config, but uses boot-sim.js bootstrap vat. ```diff $ diff -wu ./decentral-devnet-config.json ./decentral-demo-config.json --- ./decentral-devnet-config.json 2023-02-24 14:02:56.015581229 -0600 +++ ./decentral-demo-config.json 2023-02-24 14:59:18.991084488 -0600 @@ -106,7 +106,7 @@ ], "vats": { "bootstrap": { - "sourceSpec": "@agoric/vats/src/core/boot-chain.js", + "sourceSpec": "@agoric/vats/src/core/boot-sim.js", "creationOptions": { "critical": true } ``` --- packages/cosmic-swingset/src/sim-params.js | 3 +- packages/vats/decentral-demo-config.json | 140 ++++++++++++++++----- 2 files changed, 113 insertions(+), 30 deletions(-) diff --git a/packages/cosmic-swingset/src/sim-params.js b/packages/cosmic-swingset/src/sim-params.js index e4aacf5fe2f..e1e4d0d7b9c 100644 --- a/packages/cosmic-swingset/src/sim-params.js +++ b/packages/cosmic-swingset/src/sim-params.js @@ -58,8 +58,7 @@ export const defaultBeansPerUnit = [ makeStringBeans(BeansPerXsnapComputron, defaultBeansPerXsnapComputron), ]; -export const defaultBootstrapVatConfig = - '@agoric/vats/decentral-devnet-config.json'; +const defaultBootstrapVatConfig = '@agoric/vats/decentral-demo-config.json'; export const defaultPowerFlagFees = [ makePowerFlagFee('SMART_WALLET', [makeCoin('ubld', 10_000_000n)]), diff --git a/packages/vats/decentral-demo-config.json b/packages/vats/decentral-demo-config.json index 42cd1cbe202..dd9fd0bcf37 100644 --- a/packages/vats/decentral-demo-config.json +++ b/packages/vats/decentral-demo-config.json @@ -1,39 +1,129 @@ { "bootstrap": "bootstrap", "defaultReapInterval": 1000, + "snapshotInterval": 1000, "coreProposals": [ - "@agoric/inter-protocol/scripts/init-core.js", - "@agoric/pegasus/scripts/init-core.js" + "@agoric/vats/scripts/init-core.js", + { + "module": "@agoric/inter-protocol/scripts/init-core.js", + "entrypoint": "committeeProposalBuilder", + "args": [ + { + "econCommitteeOptions": { + "committeeSize": 3 + } + } + ] + }, + { + "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", + "entrypoint": "psmGovernanceBuilder", + "args": [] + }, + { + "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", + "entrypoint": "psmProposalBuilder", + "args": [ + { + "anchorOptions": { + "denom": "ibc/toyusdc", + "decimalPlaces": 6, + "keyword": "USDC_axl", + "proposedName": "USD Coin" + } + } + ] + }, + { + "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", + "entrypoint": "psmProposalBuilder", + "args": [ + { + "anchorOptions": { + "denom": "ibc/usdc5678", + "decimalPlaces": 6, + "keyword": "USDC_grv", + "proposedName": "USC Coin" + } + } + ] + }, + { + "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", + "entrypoint": "psmProposalBuilder", + "args": [ + { + "anchorOptions": { + "denom": "ibc/usdt1234", + "decimalPlaces": 6, + "keyword": "USDT_axl", + "proposedName": "Tether USD" + } + } + ] + }, + { + "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", + "entrypoint": "psmProposalBuilder", + "args": [ + { + "anchorOptions": { + "denom": "ibc/toyollie", + "decimalPlaces": 6, + "keyword": "USDT_grv", + "proposedName": "Tether USD" + } + } + ] + }, + { + "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", + "entrypoint": "psmProposalBuilder", + "args": [ + { + "anchorOptions": { + "denom": "ibc/toyellie", + "decimalPlaces": 6, + "keyword": "AUSD", + "proposedName": "Anchor USD" + } + } + ] + }, + { + "module": "@agoric/inter-protocol/scripts/invite-committee-core.js", + "entrypoint": "defaultProposalBuilder", + "args": [ + { + "voterAddresses": { + "gov1": "agoric1ldmtatp24qlllgxmrsjzcpe20fvlkp448zcuce", + "gov2": "agoric140dmkrz2e42ergjj7gyvejhzmjzurvqeq82ang", + "gov3": "agoric1w8wktaur4zf8qmmtn3n7x3r0jhsjkjntcm3u6h" + } + } + ] + } ], "vats": { "bootstrap": { - "sourceSpec": "@agoric/vats/src/core/boot.js", - "parameters": { - "governanceActions": true, - "economicCommitteeAddresses": { - "voter": "agoric1Ersatz" - } - }, + "sourceSpec": "@agoric/vats/src/core/boot-sim.js", "creationOptions": { "critical": true } } }, "bundles": { + "bank": { + "sourceSpec": "@agoric/vats/src/vat-bank.js" + }, "centralSupply": { "sourceSpec": "@agoric/vats/src/centralSupply.js" }, - "chainStorage": { - "sourceSpec": "@agoric/vats/src/vat-chainStorage.js" - }, "mintHolder": { "sourceSpec": "@agoric/vats/src/mintHolder.js" }, - "zcf": { - "sourceSpec": "@agoric/zoe/contractFacet.js" - }, - "bank": { - "sourceSpec": "@agoric/vats/src/vat-bank.js" + "mints": { + "sourceSpec": "@agoric/vats/src/vat-mints.js" }, "board": { "sourceSpec": "@agoric/vats/src/vat-board.js" @@ -41,9 +131,6 @@ "ibc": { "sourceSpec": "@agoric/vats/src/vat-ibc.js" }, - "mints": { - "sourceSpec": "@agoric/vats/src/vat-mints.js" - }, "network": { "sourceSpec": "@agoric/vats/src/vat-network.js" }, @@ -53,18 +140,15 @@ "provisioning": { "sourceSpec": "@agoric/vats/src/vat-provisioning.js" }, - "provisionPool": { - "sourceSpec": "@agoric/vats/src/provisionPool.js" - }, - "sharing": { - "sourceSpec": "@agoric/vats/src/vat-sharing.js" + "chainStorage": { + "sourceSpec": "@agoric/vats/src/vat-chainStorage.js" }, - "walletFactory": { - "sourceSpec": "@agoric/smart-wallet/src/walletFactory.js" + "zcf": { + "sourceSpec": "@agoric/zoe/contractFacet.js" }, "zoe": { "sourceSpec": "@agoric/vats/src/vat-zoe.js" } }, "defaultManagerType": "xs-worker" -} +} \ No newline at end of file From 5d676c4e6774dfaa612d31f61d9bd8f6b2e29ebe Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Tue, 21 Feb 2023 17:44:56 -0600 Subject: [PATCH 09/38] WIP(inter-protocol): sim proposal getManifestForInterProtocol - export manifest from sim-behaviors.js - core(inter-protocol): static types for sim-behaviors - return Promise --- .../src/proposals/core-proposal.js | 17 ++------ .../src/proposals/sim-behaviors.js | 39 ++++++++++++++++++- .../src/proposals/sim-proposal.js | 34 ++++++++++++++++ 3 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 packages/inter-protocol/src/proposals/sim-proposal.js diff --git a/packages/inter-protocol/src/proposals/core-proposal.js b/packages/inter-protocol/src/proposals/core-proposal.js index 842387ebd04..b35361bc413 100644 --- a/packages/inter-protocol/src/proposals/core-proposal.js +++ b/packages/inter-protocol/src/proposals/core-proposal.js @@ -9,9 +9,9 @@ export * from './sim-behaviors.js'; export * from './startPSM.js'; // eslint-disable-line import/export export * from './startEconCommittee.js'; // eslint-disable-line import/export -/** @type {import('@agoric/vats/src/core/manifest.js').BootstrapManifest} */ +/** @type {import('@agoric/vats/src/core/lib-boot.js').BootstrapManifest} */ const SHARED_MAIN_MANIFEST = harden({ - /** @type {import('@agoric/vats/src/core/manifest.js').BootstrapManifestPermit} */ + /** @type {import('@agoric/vats/src/core/lib-boot.js').BootstrapManifestPermit} */ [econBehaviors.startVaultFactory.name]: { consume: { board: 'board', @@ -200,19 +200,9 @@ export const getManifestForMain = ( }; }; -const roleToManifest = harden({ - chain: { - ...REWARD_MANIFEST, - ...STAKE_FACTORY_MANIFEST, - }, - 'sim-chain': SIM_CHAIN_MANIFEST, - client: {}, -}); - export const getManifestForInterProtocol = ( { restoreRef }, { - ROLE = 'chain', econCommitteeOptions, installKeys, vaultFactoryControllerAddress, @@ -237,7 +227,8 @@ export const getManifestForInterProtocol = ( manifest: { ...econCommitteeManifest.manifest, ...mainManifest.manifest, - ...roleToManifest[ROLE], + ...REWARD_MANIFEST, + ...STAKE_FACTORY_MANIFEST, }, installations: { ...econCommitteeManifest.installations, diff --git a/packages/inter-protocol/src/proposals/sim-behaviors.js b/packages/inter-protocol/src/proposals/sim-behaviors.js index 006d8ee0222..fde6c1997a9 100644 --- a/packages/inter-protocol/src/proposals/sim-behaviors.js +++ b/packages/inter-protocol/src/proposals/sim-behaviors.js @@ -1,7 +1,9 @@ import { E, Far } from '@endo/far'; import { addRemote } from '@agoric/vats/src/core/utils.js'; -export { connectFaucet } from './demoIssuers.js'; +import { connectFaucet } from './demoIssuers.js'; + +export { connectFaucet }; /** @param {BootstrapPowers} powers */ export const installSimEgress = async ({ @@ -11,7 +13,7 @@ export const installSimEgress = async ({ }) => { const PROVISIONER_INDEX = 1; - return Promise.all( + await Promise.all( argv.hardcodedClientAddresses.map(async (addr, i) => { const clientFacet = await E(clientCreator).createClientFacet( `solo${i}`, @@ -37,3 +39,36 @@ export const grantRunBehaviors = async ({ return E(client).assignBundle([_addr => bundle]); }; harden(grantRunBehaviors); + +/** @type {import('@agoric/vats').BootstrapManifest} */ +export const SIM_CHAIN_BOOTSTRAP_PERMITS = harden({ + /** @type {import('@agoric/vats').BootstrapManifestPermit} */ + [installSimEgress.name]: { + vatParameters: { argv: { hardcodedClientAddresses: true } }, + vats: { + vattp: true, + comms: true, + }, + consume: { clientCreator: true }, + }, + [connectFaucet.name]: { + consume: { + bankManager: true, + bldIssuerKit: true, + client: true, + feeMintAccess: true, + loadVat: true, + zoe: true, + }, + installation: { + consume: { centralSupply: 'zoe' }, + }, + produce: { mints: true }, + home: { produce: { faucet: true } }, + }, + [grantRunBehaviors.name]: { + runBehaviors: true, + consume: { client: true }, + home: { produce: { runBehaviors: true, governanceActions: true } }, + }, +}); diff --git a/packages/inter-protocol/src/proposals/sim-proposal.js b/packages/inter-protocol/src/proposals/sim-proposal.js new file mode 100644 index 00000000000..f41ba3e8bfd --- /dev/null +++ b/packages/inter-protocol/src/proposals/sim-proposal.js @@ -0,0 +1,34 @@ +import { Stable } from '@agoric/vats/src/tokens.js'; +import { fundAMM } from './demoIssuers.js'; + +// XXX from core-proposal.js + +export const SIM_CHAIN_MANIFEST = harden({ + [fundAMM.name]: { + consume: { + centralSupplyBundle: true, + mintHolderBundle: true, + chainTimerService: 'timer', + bldIssuerKit: true, + feeMintAccess: true, + loadVat: true, + mints: 'mints', + priceAuthorityVat: 'priceAuthority', + priceAuthorityAdmin: 'priceAuthority', + vaultFactoryKit: 'VaultFactory', + zoe: true, + }, + installation: { + consume: { centralSupply: 'zoe' }, + }, + issuer: { + consume: { [Stable.symbol]: 'zoe' }, + }, + brand: { + consume: { [Stable.symbol]: 'zoe' }, + }, + instance: { + consume: { amm: 'amm' }, + }, + }, +}); From c762772e4ac1d0b292d45eda7ec90761165e947e Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 24 Feb 2023 20:45:54 -0600 Subject: [PATCH 10/38] refactor(inter-protocol): BootstrapManifest type moved --- .../inter-protocol/src/proposals/sim-behaviors.js | 4 ++-- packages/inter-protocol/src/proposals/startPSM.js | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/inter-protocol/src/proposals/sim-behaviors.js b/packages/inter-protocol/src/proposals/sim-behaviors.js index fde6c1997a9..26e456c3473 100644 --- a/packages/inter-protocol/src/proposals/sim-behaviors.js +++ b/packages/inter-protocol/src/proposals/sim-behaviors.js @@ -40,9 +40,9 @@ export const grantRunBehaviors = async ({ }; harden(grantRunBehaviors); -/** @type {import('@agoric/vats').BootstrapManifest} */ +/** @type {import('@agoric/vats/src/core/lib-boot').BootstrapManifest} */ export const SIM_CHAIN_BOOTSTRAP_PERMITS = harden({ - /** @type {import('@agoric/vats').BootstrapManifestPermit} */ + /** @type {import('@agoric/vats/src/core/lib-boot').BootstrapManifestPermit} */ [installSimEgress.name]: { vatParameters: { argv: { hardcodedClientAddresses: true } }, vats: { diff --git a/packages/inter-protocol/src/proposals/startPSM.js b/packages/inter-protocol/src/proposals/startPSM.js index 6d2f8628409..10e3be72de0 100644 --- a/packages/inter-protocol/src/proposals/startPSM.js +++ b/packages/inter-protocol/src/proposals/startPSM.js @@ -15,6 +15,8 @@ import { inviteToEconCharter, } from './committee-proposal.js'; +/** @typedef {import('@agoric/vats/src/core/lib-boot.js').BootstrapManifest} BootstrapManifest */ + const BASIS_POINTS = 10000n; const { details: X } = assert; @@ -314,7 +316,7 @@ export const installGovAndPSMContracts = async ({ * named swingset bundles only in * decentral-psm-config.json * - * @type {import('@agoric/vats/src/core/manifest.js').BootstrapManifest} + * @type {BootstrapManifest} */ export const PSM_GOV_MANIFEST = { [installGovAndPSMContracts.name]: { @@ -345,8 +347,7 @@ export const PSM_GOV_MANIFEST = { }; export const INVITE_PSM_COMMITTEE_MANIFEST = harden( - /** @type {import('@agoric/vats/src/core/manifest.js').BootstrapManifest} */ - ({ + /** @type {BootstrapManifest} */ ({ [inviteCommitteeMembers.name]: { consume: { namesByAddressAdmin: true, @@ -363,9 +364,8 @@ export const INVITE_PSM_COMMITTEE_MANIFEST = harden( }), ); -/** @type {import('@agoric/vats/src/core/manifest.js').BootstrapManifest} */ -export const PSM_MANIFEST = harden({ - /** @type {import('@agoric/vats/src/core/manifest.js').BootstrapManifestPermit} */ +/** @type {BootstrapManifest} */ +export const PSM_MANIFEST = { [makeAnchorAsset.name]: { consume: { agoricNamesAdmin: true, bankManager: 'bank', zoe: 'zoe' }, installation: { consume: { mintHolder: 'zoe' } }, @@ -395,7 +395,8 @@ export const PSM_MANIFEST = harden({ consume: { [Stable.symbol]: 'zoe' }, }, }, -}); +}; +harden(PSM_MANIFEST); export const getManifestForPsmGovernance = ( { restoreRef }, From 821776779a000a4814eb6143aab61b6b456be640 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 23 Feb 2023 17:12:23 -0600 Subject: [PATCH 11/38] fix(solo)!: separate boot-solo.js out of boot.js (CONT.) rather than ROLE --- packages/solo/solo-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solo/solo-config.json b/packages/solo/solo-config.json index 75e1e4845c0..d215366ff32 100644 --- a/packages/solo/solo-config.json +++ b/packages/solo/solo-config.json @@ -16,7 +16,7 @@ "sourceSpec": "./src/vat-uploads.js" }, "bootstrap": { - "sourceSpec": "@agoric/vats/src/core/boot.js" + "sourceSpec": "@agoric/vats/src/core/boot-solo.js" } } } From 3655afe9a4d5ed1fcdb551131ff5d82b88600f65 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 24 Feb 2023 17:01:10 -0600 Subject: [PATCH 12/38] chore(vats): move authorityViz.js to tools --- packages/vats/{src => tools}/authorityViz.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/vats/{src => tools}/authorityViz.js (100%) diff --git a/packages/vats/src/authorityViz.js b/packages/vats/tools/authorityViz.js similarity index 100% rename from packages/vats/src/authorityViz.js rename to packages/vats/tools/authorityViz.js From 89dd2602fd4bb911e0e5338074e3db379ae1f31c Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 24 Feb 2023 19:53:59 -0600 Subject: [PATCH 13/38] chore(vats): restore authorityViz.js to working order - misc static types - note TODO ideas - make executable --- packages/vats/tools/authorityViz.js | 221 ++++++++++++++++++---------- 1 file changed, 145 insertions(+), 76 deletions(-) mode change 100644 => 100755 packages/vats/tools/authorityViz.js diff --git a/packages/vats/tools/authorityViz.js b/packages/vats/tools/authorityViz.js old mode 100644 new mode 100755 index 07d4db488c8..fbebcca2ba1 --- a/packages/vats/tools/authorityViz.js +++ b/packages/vats/tools/authorityViz.js @@ -1,10 +1,14 @@ +#!/usr/bin/env node // @ts-check import '@endo/init'; import process from 'process'; -import * as manifests from './core/manifest.js'; +const { entries, keys, values } = Object; -const { entries } = Object; +const logged = label => x => { + console.error(label, x); + return x; +}; const styles = { vatPowers: 'shape=star, style=filled, fillcolor=aqua', @@ -62,17 +66,17 @@ function* fmtGraph(nodes, neighbors) { /** * * @param {Record} manifest - * @typedef {{ - * vatParameters?: Record, - * vatPowers?: Record - * vats?: Record - * devices?: Record + * @typedef { true | { + * vatParameters?: Record, + * vatPowers?: Record + * vats?: Record + * devices?: Record * home?: PowerSpace, * issuer?: PowerSpace, * brand?: PowerSpace, + * oracleBrand?: PowerSpace, * installation?: PowerSpace, * instance?: PowerSpace, - * runBehaviors: Function, * } & PowerSpace } Permit * @typedef {{produce?: Record, consume?: Record}} PowerSpace * @typedef { boolean | VatName } Status @@ -89,6 +93,7 @@ const manifest2graph = manifest => { * @param {string} [style] */ const addEdge = (src, dest, style = '') => { + logged('addEdge')({ src, dest }); if (!neighbors.has(src)) { neighbors.set(src, new Set()); } @@ -98,89 +103,143 @@ const manifest2graph = manifest => { /** * @param {string} src * @param {string} ty - * @param {Record | undefined} item + * @param {Permit} item * @param {boolean} [reverse=false] */ const level1 = (src, ty, item, reverse = false) => { - if (item) { - for (const [powerName, status] of entries(item)) { - // subsumed by permits for vat:, home:, ... - if ( - [ - 'loadVat', - 'loadCriticalVat', - 'client', - 'agoricNames', - 'nameHubs', - 'nameAdmins', - ].includes(powerName) && - reverse - ) - continue; - if (status) { - let cluster = {}; - if (typeof status !== 'boolean') { - cluster = { cluster: status }; - } - - nodes.add({ - id: `${ty}.${powerName}`, - label: powerName, - style: styles[ty], - ...cluster, - }); - addEdge(src, `${ty}.${powerName}`, reverse ? 'dir=back' : ''); - if (ty === 'home') { - nodes.add({ id: 'home', label: 'home', cluster: 'provisioning' }); - addEdge('home', `${ty}.${powerName}`); - } + if (!item) return; + for (const [powerName, status] of entries(item)) { + // subsumed by permits for vat:, home:, ... + if ( + [ + 'loadVat', + 'loadCriticalVat', + 'client', + 'agoricNames', + 'nameHubs', + 'nameAdmins', + ].includes(powerName) && + reverse + ) + continue; + if (status) { + let cluster = {}; + if (typeof status !== 'boolean') { + cluster = { cluster: status }; + } + + nodes.add({ + id: `${ty}.${powerName}`, + label: powerName, + style: styles[ty], + ...cluster, + }); + addEdge(src, `${ty}.${powerName}`, reverse ? 'dir=back' : ''); + if (ty === 'home') { + nodes.add({ id: 'home', label: 'home', cluster: 'provisioning' }); + addEdge('home', `${ty}.${powerName}`); } } } }; + /** @type {(xs: X[]) => X[]} */ + const uniq = xs => [...new Set(xs)]; + const spaces = uniq( + logged('vals')(values(manifest)).flatMap(permit => + logged('keys?')(keys(permit)).flatMap(name => { + logged('name?')(name); + + if (['produce', 'consume'].includes(name)) return []; + return [name]; + }), + ), + ); + console.error('@@@', { spaces }); + for (const [fnName, permit] of entries(manifest)) { - nodes.add({ id: fnName, label: fnName }); - - level1(fnName, 'vatPowers', permit.vatPowers, true); - level1(fnName, 'vats', permit.vats, true); - level1(fnName, 'devices', permit.devices, true); - level1(fnName, 'space', permit.produce); - level1(fnName, 'space', permit.consume, true); - level1(fnName, 'home', (permit.home || {}).produce); - level1(fnName, 'issuer', (permit.issuer || {}).produce); - level1(fnName, 'issuer', (permit.issuer || {}).consume, true); - level1(fnName, 'brand', (permit.brand || {}).produce); - level1(fnName, 'brand', (permit.brand || {}).consume, true); - level1(fnName, 'installation', (permit.installation || {}).produce); - level1(fnName, 'installation', (permit.installation || {}).consume, true); - level1(fnName, 'instance', (permit.instance || {}).produce); - level1(fnName, 'instance', (permit.instance || {}).consume, true); - if (permit.runBehaviors) { - nodes.add({ - id: `runBehaviors`, - label: `runBehaviors`, - style: '', - }); - addEdge(fnName, `runBehaviors`); + if (permit === true) { + console.error('skipping wildcard permit:', fnName); + continue; + } + nodes.add({ id: logged('fn')(fnName), label: fnName }); + + permit.vatPowers && level1(fnName, 'vatPowers', permit.vatPowers, true); + permit.vats && level1(fnName, 'vats', permit.vats, true); + permit.devices && level1(fnName, 'devices', permit.devices, true); + + const doPart = (name, part) => { + if (!part) return; + level1(fnName, name, part.produce || {}); + level1(fnName, name, part.consume || {}, true); + }; + doPart('space', permit); + spaces.forEach(s => doPart(s, permit[s])); + + if ('runBehaviors' in permit) { + throw Error('not impl'); + // nodes.add({ + // id: `runBehaviors`, + // label: `runBehaviors`, + // style: '', + // }); + // addEdge(fnName, `runBehaviors`); } } return { nodes, neighbors }; }; +const { Fail, quote: q } = assert; + +/** + * @param {string} specifier + * @param {object} io + * @param {Resolver} io.resolve + * @param {typeof import('fs/promises').readFile} io.readFile + */ +const loadConfig = async (specifier, { resolve, readFile }) => { + const fullPath = await resolve(specifier, import.meta.url).then( + u => new URL(u).pathname, + ); + typeof fullPath === 'string' || Fail`${q(specifier)}`; + const txt = await readFile(fullPath, 'utf-8'); + typeof txt === 'string' || Fail`readFile ${q(fullPath)}`; + return JSON.parse(txt); +}; + /** * @param {string[]} args * @param {object} io * @param {typeof import('process').stdout} io.stdout + * @param {typeof import('fs/promises')} io.fsp + * @param {{ + * resolve: Resolver, + * url: string, + * load: (specifier: string) => Promise>, + * }} io.meta + * + * @typedef {(specifier: string, parent: string) => Promise} Resolver */ -const main = async (args, { stdout }) => { - const [...opts] = args; - // if (!fn) throw Error('usage: authorityViz [--sim-chain]'); - const [sim, gov] = ['--sim-chain', '--gov'].map(opt => opts.includes(opt)); - const manifest = sim - ? manifests.SIM_CHAIN_BOOTSTRAP_MANIFEST - : manifests.CHAIN_BOOTSTRAP_MANIFEST; +const main = async (args, { stdout, fsp, meta }) => { + const [specifier, ...opts] = args; + specifier || Fail`Usage: $0 @agoric/vats/decentral-...json`; + + const config = await loadConfig(specifier, { + resolve: meta.resolve, + readFile: fsp.readFile, + }); + // console.log(config); + const { bootstrap } = config.vats; + + const { MANIFEST } = await meta + .resolve(bootstrap.sourceSpec, meta.url) + .then(p => meta.load(p)); + // console.log('manifest keys:', Object.keys(MANIFEST)); + + const [gov] = ['--gov'].map(opt => opts.includes(opt)); + if (gov) { + throw Error('not impl'); /* const postBoot = sim ? manifests.SIM_CHAIN_POST_BOOT_MANIFEST @@ -189,15 +248,25 @@ const main = async (args, { stdout }) => { */ } - // console.log(JSON.stringify(bootstrapManifest, null, 2)); - const g = manifest2graph(/** @type {any} */ (manifest)); + const g = manifest2graph(MANIFEST); for (const chunk of fmtGraph(g.nodes, g.neighbors)) { stdout.write(chunk); } }; (async () => { - return main(process.argv.slice(2), { - stdout: process.stdout, - }); + // eslint-disable-next-line import/no-extraneous-dependencies + Promise.all([import('fs/promises'), import('import-meta-resolve')]).then( + ([fsp, metaResolve]) => { + return main(process.argv.slice(2), { + stdout: process.stdout, + fsp, + meta: { + resolve: metaResolve.resolve, + url: import.meta.url, + load: specifier => import(specifier), + }, + }); + }, + ); })().catch(console.error); From 7831f9950669695c6c865c2c180e2f36385d49b6 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 25 Feb 2023 08:56:21 -0600 Subject: [PATCH 14/38] refactor(vats): factor out promise-space.js --- packages/smart-wallet/test/supports.js | 5 +- packages/vats/index.js | 1 + packages/vats/src/core/boot-psm.js | 3 +- packages/vats/src/core/lib-boot.js | 7 +- packages/vats/src/core/promise-space.js | 106 ++++++++++++++++++ packages/vats/src/core/utils.js | 106 +----------------- packages/vats/test/test-boot.js | 2 +- packages/vats/test/test-clientBundle.js | 3 +- packages/vats/test/test-name-hub-published.js | 3 +- packages/vats/test/test-promise-space.js | 2 +- packages/vats/test/test-vat-bank.js | 3 +- 11 files changed, 121 insertions(+), 120 deletions(-) create mode 100644 packages/vats/src/core/promise-space.js diff --git a/packages/smart-wallet/test/supports.js b/packages/smart-wallet/test/supports.js index 170318dfede..4a4487d43b7 100644 --- a/packages/smart-wallet/test/supports.js +++ b/packages/smart-wallet/test/supports.js @@ -8,10 +8,7 @@ import { } from '@agoric/vats/src/core/basic-behaviors.js'; import { setupClientManager } from '@agoric/vats/src/core/chain-behaviors.js'; import '@agoric/vats/src/core/types.js'; -import { - makeAgoricNamesAccess, - makePromiseSpace, -} from '@agoric/vats/src/core/utils.js'; +import { makeAgoricNamesAccess, makePromiseSpace } from '@agoric/vats'; import { buildRootObject as boardRoot } from '@agoric/vats/src/vat-board.js'; import { buildRootObject as mintsRoot } from '@agoric/vats/src/vat-mints.js'; import { makeMockChainStorageRoot } from '@agoric/internal/src/storage-test-utils.js'; diff --git a/packages/vats/index.js b/packages/vats/index.js index c6a8bb5d12b..29bca8966ee 100644 --- a/packages/vats/index.js +++ b/packages/vats/index.js @@ -6,3 +6,4 @@ import './src/core/types.js'; export * from './src/types.js'; export * from './src/nameHub.js'; export * from './src/bridge.js'; +export { makePromiseSpace } from './src/core/promise-space.js'; diff --git a/packages/vats/src/core/boot-psm.js b/packages/vats/src/core/boot-psm.js index 07e53c9f3c1..465f9c45ace 100644 --- a/packages/vats/src/core/boot-psm.js +++ b/packages/vats/src/core/boot-psm.js @@ -20,7 +20,8 @@ import { ECON_COMMITTEE_MANIFEST, startEconomicCommittee, } from '@agoric/inter-protocol/src/proposals/startEconCommittee.js'; -import { makeAgoricNamesAccess, makePromiseSpace } from './utils.js'; +import { makeAgoricNamesAccess } from './utils.js'; +import { makePromiseSpace } from './promise-space.js'; import { Stable, Stake } from '../tokens.js'; import { addBankAssets, diff --git a/packages/vats/src/core/lib-boot.js b/packages/vats/src/core/lib-boot.js index b1e177b52c8..61d2f7cab01 100644 --- a/packages/vats/src/core/lib-boot.js +++ b/packages/vats/src/core/lib-boot.js @@ -1,11 +1,8 @@ // @ts-check import { E, Far } from '@endo/far'; import { makePassableEncoding } from '@agoric/swingset-vat/tools/passableEncoding.js'; -import { - makeAgoricNamesAccess, - makePromiseSpace, - runModuleBehaviors, -} from './utils.js'; +import { makeAgoricNamesAccess, runModuleBehaviors } from './utils.js'; +import { makePromiseSpace } from './promise-space.js'; const { Fail, quote: q } = assert; diff --git a/packages/vats/src/core/promise-space.js b/packages/vats/src/core/promise-space.js new file mode 100644 index 00000000000..93e9fc3c023 --- /dev/null +++ b/packages/vats/src/core/promise-space.js @@ -0,0 +1,106 @@ +import { makePromiseKit } from '@endo/promise-kit'; + +/** + * Make { produce, consume } where for each name, `consume[name]` is a promise + * and `produce[name].resolve` resolves it. + * + * Note: repeated resolves() are noops. + * + * @param {typeof console.log} [log] + * @returns {PromiseSpace} + */ + +export const makePromiseSpace = (log = (..._args) => {}) => { + /** + * @typedef {PromiseRecord & { + * reset: (reason?: unknown) => void, + * isSettling: boolean, + * }} PromiseState + */ + /** @type {Map} */ + const nameToState = new Map(); + const remaining = new Set(); + + const findOrCreateState = name => { + /** @type {PromiseState} */ + let state; + const currentState = nameToState.get(name); + if (currentState) { + state = currentState; + } else { + log(`${name}: new Promise`); + const pk = makePromiseKit(); + + pk.promise + .finally(() => { + remaining.delete(name); + log(name, 'settled; remaining:', [...remaining.keys()].sort()); + }) + .catch(() => {}); + + const settling = () => { + assert(state); + state = harden({ ...state, isSettling: true }); + nameToState.set(name, state); + }; + + const resolve = value => { + settling(); + pk.resolve(value); + }; + const reject = reason => { + settling(); + pk.reject(reason); + }; + + const reset = (reason = undefined) => { + if (!state.isSettling) { + if (!reason) { + // Reuse the old promise; don't reject it. + return; + } + reject(reason); + } + // Now publish a new promise. + nameToState.delete(name); + remaining.delete(name); + }; + + state = harden({ + isSettling: false, + resolve, + reject, + reset, + promise: pk.promise, + }); + nameToState.set(name, state); + remaining.add(name); + } + return state; + }; + + const consume = new Proxy( + {}, + { + get: (_target, name) => { + assert.typeof(name, 'string'); + const kit = findOrCreateState(name); + return kit.promise; + }, + }, + ); + + const produce = new Proxy( + {}, + { + get: (_target, name) => { + assert.typeof(name, 'string'); + const { reject, resolve, reset } = findOrCreateState(name); + return harden({ reject, resolve, reset }); + }, + }, + ); + + return harden({ produce, consume }); +}; +harden(makePromiseSpace); diff --git a/packages/vats/src/core/utils.js b/packages/vats/src/core/utils.js index 19019da63e2..369c2e15a9c 100644 --- a/packages/vats/src/core/utils.js +++ b/packages/vats/src/core/utils.js @@ -1,9 +1,9 @@ // @ts-check import { E } from '@endo/far'; import { assertPassable } from '@endo/marshal'; -import { makePromiseKit } from '@endo/promise-kit'; import { makeNameHubKit } from '../nameHub.js'; import { Stable, Stake } from '../tokens.js'; +import { makePromiseSpace } from './promise-space.js'; const { entries, fromEntries, keys } = Object; const { Fail, quote: q } = assert; @@ -109,110 +109,6 @@ harden(addRemote); export const callProperties = (builders, ...args) => fromEntries(builders.map(fn => entries(fn(...args))).flat()); -/** - * Make { produce, consume } where for each name, `consume[name]` is a promise - * and `produce[name].resolve` resolves it. - * - * Note: repeated resolves() are noops. - * - * @param {typeof console.log} [log] - * @returns {PromiseSpace} - */ -export const makePromiseSpace = (log = (..._args) => {}) => { - /** - * @typedef {PromiseRecord & { - * reset: (reason?: unknown) => void, - * isSettling: boolean, - * }} PromiseState - */ - /** @type {Map} */ - const nameToState = new Map(); - const remaining = new Set(); - - const findOrCreateState = name => { - /** @type {PromiseState} */ - let state; - const currentState = nameToState.get(name); - if (currentState) { - state = currentState; - } else { - log(`${name}: new Promise`); - const pk = makePromiseKit(); - - pk.promise - .finally(() => { - remaining.delete(name); - log(name, 'settled; remaining:', [...remaining.keys()].sort()); - }) - .catch(() => {}); - - const settling = () => { - assert(state); - state = harden({ ...state, isSettling: true }); - nameToState.set(name, state); - }; - - const resolve = value => { - settling(); - pk.resolve(value); - }; - const reject = reason => { - settling(); - pk.reject(reason); - }; - - const reset = (reason = undefined) => { - if (!state.isSettling) { - if (!reason) { - // Reuse the old promise; don't reject it. - return; - } - reject(reason); - } - // Now publish a new promise. - nameToState.delete(name); - remaining.delete(name); - }; - - state = harden({ - isSettling: false, - resolve, - reject, - reset, - promise: pk.promise, - }); - nameToState.set(name, state); - remaining.add(name); - } - return state; - }; - - const consume = new Proxy( - {}, - { - get: (_target, name) => { - assert.typeof(name, 'string'); - const kit = findOrCreateState(name); - return kit.promise; - }, - }, - ); - - const produce = new Proxy( - {}, - { - get: (_target, name) => { - assert.typeof(name, 'string'); - const { reject, resolve, reset } = findOrCreateState(name); - return harden({ reject, resolve, reset }); - }, - }, - ); - - return harden({ produce, consume }); -}; -harden(makePromiseSpace); - /** * Attenuate `specimen` to only allow acccess to properties specified in `template` * diff --git a/packages/vats/test/test-boot.js b/packages/vats/test/test-boot.js index 88f2ee3dd5c..e155b0013ad 100644 --- a/packages/vats/test/test-boot.js +++ b/packages/vats/test/test-boot.js @@ -11,7 +11,7 @@ import { buildRootObject } from '../src/core/boot-chain.js'; import { buildRootObject as buildSimRootObject } from '../src/core/boot-sim.js'; import { buildRootObject as buildSoloRootObject } from '../src/core/boot-solo.js'; import { bridgeCoreEval } from '../src/core/chain-behaviors.js'; -import { makePromiseSpace } from '../src/core/utils.js'; +import { makePromiseSpace } from '../src/core/promise-space.js'; import { makeMock, diff --git a/packages/vats/test/test-clientBundle.js b/packages/vats/test/test-clientBundle.js index 5625e138fb9..fcb22755224 100644 --- a/packages/vats/test/test-clientBundle.js +++ b/packages/vats/test/test-clientBundle.js @@ -13,7 +13,8 @@ import { } from '@agoric/inter-protocol/src/proposals/demoIssuers.js'; import { makeScalarBigMapStore } from '@agoric/vat-data'; import { setupClientManager } from '../src/core/chain-behaviors.js'; -import { makeAgoricNamesAccess, makePromiseSpace } from '../src/core/utils.js'; +import { makeAgoricNamesAccess } from '../src/core/utils.js'; +import { makePromiseSpace } from '../src/core/promise-space.js'; import { buildRootObject as mintsRoot } from '../src/vat-mints.js'; import { buildRootObject as boardRoot } from '../src/vat-board.js'; import { diff --git a/packages/vats/test/test-name-hub-published.js b/packages/vats/test/test-name-hub-published.js index 32439cf8c3f..c0d3cd21cc8 100644 --- a/packages/vats/test/test-name-hub-published.js +++ b/packages/vats/test/test-name-hub-published.js @@ -4,7 +4,8 @@ import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; import { makeMockChainStorageRoot } from '@agoric/inter-protocol/test/supports.js'; import { makeHandle } from '@agoric/zoe/src/makeHandle.js'; import { eventLoopIteration } from '@agoric/zoe/tools/eventLoopIteration.js'; -import { makeAgoricNamesAccess, makePromiseSpace } from '../src/core/utils.js'; +import { makeAgoricNamesAccess } from '../src/core/utils.js'; +import { makePromiseSpace } from '../src/core/promise-space.js'; import { publishAgoricNames, setupClientManager, diff --git a/packages/vats/test/test-promise-space.js b/packages/vats/test/test-promise-space.js index 10a5baaf667..d671483715d 100644 --- a/packages/vats/test/test-promise-space.js +++ b/packages/vats/test/test-promise-space.js @@ -1,7 +1,7 @@ // @ts-check import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; -import { makePromiseSpace } from '../src/core/utils.js'; +import { makePromiseSpace } from '../src/core/promise-space.js'; test('makePromiseSpace', async t => { const { produce, consume } = makePromiseSpace(); diff --git a/packages/vats/test/test-vat-bank.js b/packages/vats/test/test-vat-bank.js index 738dbd3baa5..c60202eaada 100644 --- a/packages/vats/test/test-vat-bank.js +++ b/packages/vats/test/test-vat-bank.js @@ -13,7 +13,8 @@ import { addBankAssets, installBootContracts, } from '../src/core/basic-behaviors.js'; -import { makeAgoricNamesAccess, makePromiseSpace } from '../src/core/utils.js'; +import { makeAgoricNamesAccess } from '../src/core/utils.js'; +import { makePromiseSpace } from '../src/core/promise-space.js'; import { makePopulatedFakeVatAdmin } from '../tools/boot-test-utils.js'; test('communication', async t => { From 107bd1040575286d13de5da1adac3857b54c02f8 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 25 Feb 2023 09:01:27 -0600 Subject: [PATCH 15/38] test(inter-protocol): update makePromiseSpace import --- .../src/proposals/sim-proposal.js | 33 +------------------ packages/inter-protocol/test/psm/setupPsm.js | 5 +-- packages/inter-protocol/test/reserve/setup.js | 5 +-- .../test/stakeFactory/test-stakeFactory.js | 5 +-- packages/inter-protocol/test/supports.js | 5 +-- 5 files changed, 5 insertions(+), 48 deletions(-) diff --git a/packages/inter-protocol/src/proposals/sim-proposal.js b/packages/inter-protocol/src/proposals/sim-proposal.js index f41ba3e8bfd..01f440fe0cd 100644 --- a/packages/inter-protocol/src/proposals/sim-proposal.js +++ b/packages/inter-protocol/src/proposals/sim-proposal.js @@ -1,34 +1,3 @@ -import { Stable } from '@agoric/vats/src/tokens.js'; -import { fundAMM } from './demoIssuers.js'; - // XXX from core-proposal.js -export const SIM_CHAIN_MANIFEST = harden({ - [fundAMM.name]: { - consume: { - centralSupplyBundle: true, - mintHolderBundle: true, - chainTimerService: 'timer', - bldIssuerKit: true, - feeMintAccess: true, - loadVat: true, - mints: 'mints', - priceAuthorityVat: 'priceAuthority', - priceAuthorityAdmin: 'priceAuthority', - vaultFactoryKit: 'VaultFactory', - zoe: true, - }, - installation: { - consume: { centralSupply: 'zoe' }, - }, - issuer: { - consume: { [Stable.symbol]: 'zoe' }, - }, - brand: { - consume: { [Stable.symbol]: 'zoe' }, - }, - instance: { - consume: { amm: 'amm' }, - }, - }, -}); +export const SIM_CHAIN_MANIFEST = harden({}); diff --git a/packages/inter-protocol/test/psm/setupPsm.js b/packages/inter-protocol/test/psm/setupPsm.js index cd14ee081d7..8942b4e2b1f 100644 --- a/packages/inter-protocol/test/psm/setupPsm.js +++ b/packages/inter-protocol/test/psm/setupPsm.js @@ -1,10 +1,7 @@ import { Far, makeLoopback } from '@endo/captp'; import { E } from '@endo/eventual-send'; -import { - makeAgoricNamesAccess, - makePromiseSpace, -} from '@agoric/vats/src/core/utils.js'; +import { makeAgoricNamesAccess, makePromiseSpace } from '@agoric/vats'; import { makeBoard } from '@agoric/vats/src/lib-board.js'; import { Stable } from '@agoric/vats/src/tokens.js'; import { makeScalarMapStore } from '@agoric/vat-data'; diff --git a/packages/inter-protocol/test/reserve/setup.js b/packages/inter-protocol/test/reserve/setup.js index b90f0d36101..b6b5b941772 100644 --- a/packages/inter-protocol/test/reserve/setup.js +++ b/packages/inter-protocol/test/reserve/setup.js @@ -1,9 +1,6 @@ import buildManualTimer from '@agoric/zoe/tools/manualTimer.js'; import { E } from '@endo/eventual-send'; -import { - makeAgoricNamesAccess, - makePromiseSpace, -} from '@agoric/vats/src/core/utils.js'; +import { makeAgoricNamesAccess, makePromiseSpace } from '@agoric/vats'; import { makeBoard } from '@agoric/vats/src/lib-board.js'; import { setupReserve } from '../../src/proposals/econ-behaviors.js'; diff --git a/packages/inter-protocol/test/stakeFactory/test-stakeFactory.js b/packages/inter-protocol/test/stakeFactory/test-stakeFactory.js index 86431bb6e2d..dc66880b8d8 100644 --- a/packages/inter-protocol/test/stakeFactory/test-stakeFactory.js +++ b/packages/inter-protocol/test/stakeFactory/test-stakeFactory.js @@ -9,10 +9,7 @@ import { makeCopyBag } from '@agoric/store'; import { unsafeMakeBundleCache } from '@agoric/swingset-vat/tools/bundleTool.js'; import centralSupplyBundle from '@agoric/vats/bundles/bundle-centralSupply.js'; import mintHolderBundle from '@agoric/vats/bundles/bundle-mintHolder.js'; -import { - makeAgoricNamesAccess, - makePromiseSpace, -} from '@agoric/vats/src/core/utils.js'; +import { makeAgoricNamesAccess, makePromiseSpace } from '@agoric/vats'; import { makeBoard } from '@agoric/vats/src/lib-board.js'; import { Stable } from '@agoric/vats/src/tokens.js'; import { makeRatio } from '@agoric/zoe/src/contractSupport/index.js'; diff --git a/packages/inter-protocol/test/supports.js b/packages/inter-protocol/test/supports.js index b9ab325420a..e9d2479c851 100644 --- a/packages/inter-protocol/test/supports.js +++ b/packages/inter-protocol/test/supports.js @@ -4,10 +4,7 @@ import committeeBundle from '@agoric/governance/bundles/bundle-committee.js'; import contractGovernorBundle from '@agoric/governance/bundles/bundle-contractGovernor.js'; import puppetContractGovernorBundle from '@agoric/governance/bundles/bundle-puppetContractGovernor.js'; import * as utils from '@agoric/vats/src/core/utils.js'; -import { - makeAgoricNamesAccess, - makePromiseSpace, -} from '@agoric/vats/src/core/utils.js'; +import { makePromiseSpace, makeAgoricNamesAccess } from '@agoric/vats'; import { makeBoard } from '@agoric/vats/src/lib-board.js'; import { Stable } from '@agoric/vats/src/tokens.js'; import { makeMockChainStorageRoot } from '@agoric/internal/src/storage-test-utils.js'; From ef850ab9508cbad111acddeb8780ca0f08e92701 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 2 Mar 2023 17:16:23 -0600 Subject: [PATCH 16/38] test(vats): parameterize config in makeSwingsetTestKit() --- packages/vats/test/bootstrapTests/supports.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/vats/test/bootstrapTests/supports.js b/packages/vats/test/bootstrapTests/supports.js index ecc48327d3a..ffe24fc2130 100644 --- a/packages/vats/test/bootstrapTests/supports.js +++ b/packages/vats/test/bootstrapTests/supports.js @@ -186,11 +186,12 @@ export const makeWalletFactoryDriver = async ( }; }; -export const getNodeTestVaultsConfig = async () => { - const fullPath = await importMetaResolve( - '@agoric/vats/decentral-test-vaults-config.json', - import.meta.url, - ).then(u => new URL(u).pathname); +export const getNodeTestVaultsConfig = async ( + specifier = '@agoric/vats/decentral-test-vaults-config.json', +) => { + const fullPath = await importMetaResolve(specifier, import.meta.url).then( + u => new URL(u).pathname, + ); const config = await loadSwingsetConfigFile(fullPath); assert(config); @@ -217,10 +218,11 @@ export const getNodeTestVaultsConfig = async () => { * factory metrics using separate collateral managers. (Or use test.serial) * * @param {import('ava').ExecutionContext} t + * @param {string} [specifier] bootstrap config specifier */ -export const makeSwingsetTestKit = async t => { +export const makeSwingsetTestKit = async (t, specifier) => { console.time('makeSwingsetTestKit'); - const configPath = await getNodeTestVaultsConfig(); + const configPath = await getNodeTestVaultsConfig(specifier); const { kernelStorage } = initSwingStore(); const storage = makeFakeStorageKit('bootstrapTests'); From 8f1f657cd2a4b1f8c95fcb6610b6947b09c94b1e Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 2 Mar 2023 17:17:33 -0600 Subject: [PATCH 17/38] test(vats): bootstrap support for solo dev: home.myAddressNameAdmin --- .../vats/test/bootstrapTests/test-solo-dev.js | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 packages/vats/test/bootstrapTests/test-solo-dev.js diff --git a/packages/vats/test/bootstrapTests/test-solo-dev.js b/packages/vats/test/bootstrapTests/test-solo-dev.js new file mode 100644 index 00000000000..be332281efc --- /dev/null +++ b/packages/vats/test/bootstrapTests/test-solo-dev.js @@ -0,0 +1,57 @@ +// @ts-check +import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js'; +import { PowerFlags } from '../../src/core/basic-behaviors.js'; + +import { makeSwingsetTestKit } from './supports.js'; + +const { keys } = Object; +/** + * @type {import('ava').TestFn>>} + */ +const test = anyTest; + +const makeDefaultTestContext = async t => { + const swingsetTestKit = await makeSwingsetTestKit( + t, + '@agoric/vats/decentral-demo-config.json', + ); + return swingsetTestKit; +}; + +test.before(async t => (t.context = await makeDefaultTestContext(t))); + +// Goal: test that prod config does not expose mailbox access. +// But on the JS side, aside from vattp, prod config exposes mailbox access +// just as much as dev, so we can't test that here. + +test('sim/demo config provides home with .myAddressNameAdmin', async t => { + const devToolKeys = ['behaviors', 'chainTimerService', 'faucet']; + + // TODO: cross-check these with docs and/or deploy-script-support + const homeKeys = [ + 'agoricNames', + 'bank', + 'board', + 'ibcport', + 'myAddressNameAdmin', + 'namesByAddress', + 'priceAuthority', + 'zoe', + ...devToolKeys, + ].sort(); + + const { EV } = t.context.runUtils; + await t.notThrowsAsync(EV.vat('bootstrap').consumeItem('provisioning')); + t.log('bootstrap produced provisioning vat'); + const clientCreator = await EV.vat('bootstrap').consumeItem('clientCreator'); + const addr = 'agoric123'; + const clientFacet = await EV(clientCreator).createClientFacet( + 'user1', + addr, + PowerFlags.REMOTE_WALLET, + ); + const home = await EV(clientFacet).getChainBundle(); + const actual = await EV(home.myAddressNameAdmin).getMyAddress(); + t.is(actual, addr, 'my address'); + t.deepEqual(keys(home).sort(), homeKeys); +}); From 9ae7701bf9c110703c303eefae440f8209c50a63 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 2 Mar 2023 17:22:14 -0600 Subject: [PATCH 18/38] feat(vats): export makeAgoricNamesAccess at package level --- packages/vats/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vats/index.js b/packages/vats/index.js index 29bca8966ee..05aabbc4f3b 100644 --- a/packages/vats/index.js +++ b/packages/vats/index.js @@ -7,3 +7,4 @@ export * from './src/types.js'; export * from './src/nameHub.js'; export * from './src/bridge.js'; export { makePromiseSpace } from './src/core/promise-space.js'; +export { makeAgoricNamesAccess } from './src/core/utils.js'; From 7db2f17d0238fda236cbf72574c36078d617bd5b Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 3 Mar 2023 11:52:16 -0600 Subject: [PATCH 19/38] test(vats): no test-only code is in production configs - toward test for non-upgradeable vats --- .../src/proposals/demoIssuers.js | 3 + .../internal/src/magic-cookie-test-only.js | 9 ++ packages/vats/src/vat-mints.js | 8 +- packages/vats/test/test-boot-config.js | 99 ++++++++++++++++--- 4 files changed, 101 insertions(+), 18 deletions(-) create mode 100644 packages/internal/src/magic-cookie-test-only.js diff --git a/packages/inter-protocol/src/proposals/demoIssuers.js b/packages/inter-protocol/src/proposals/demoIssuers.js index c2b031dc25f..75cbd821ce2 100644 --- a/packages/inter-protocol/src/proposals/demoIssuers.js +++ b/packages/inter-protocol/src/proposals/demoIssuers.js @@ -8,6 +8,7 @@ import { import { E, Far } from '@endo/far'; import { Stake, Stable } from '@agoric/vats/src/tokens.js'; import { Nat } from '@endo/nat'; +import { notForProductionUse } from '@agoric/internal/src/magic-cookie-test-only.js'; const { Fail, quote: q } = assert; const { multiply, floorDivide } = natSafeMath; @@ -190,6 +191,7 @@ const mintRunPayment = async ( value, { centralSupplyInstall, feeMintAccess: feeMintAccessP, zoe }, ) => { + notForProductionUse(); const feeMintAccess = await feeMintAccessP; const { creatorFacet: ammSupplier } = await E(zoe).startInstance( @@ -297,6 +299,7 @@ export const connectFaucet = async ({ const { issuer, brand, mint } = await provideIssuerKit(issuerName); const unit = 10n ** BigInt(DecimalPlaces[issuerName]); const amount = AmountMath.make(brand, Nat(record.balance) * unit); + notForProductionUse(); const payment = await E(mint).mintPayment(amount); /** @type {UserPaymentRecord[]} */ diff --git a/packages/internal/src/magic-cookie-test-only.js b/packages/internal/src/magic-cookie-test-only.js new file mode 100644 index 00000000000..df4e788e8db --- /dev/null +++ b/packages/internal/src/magic-cookie-test-only.js @@ -0,0 +1,9 @@ +const cookie = harden({}); + +/** + * Facilitate static analysis to prevent + * demo/test facilities from being bundled in production. + */ +export const notForProductionUse = () => { + return cookie; +}; diff --git a/packages/vats/src/vat-mints.js b/packages/vats/src/vat-mints.js index 72034cda1e9..31dfa0d6c69 100644 --- a/packages/vats/src/vat-mints.js +++ b/packages/vats/src/vat-mints.js @@ -3,6 +3,7 @@ import { Far } from '@endo/far'; import { makeIssuerKit, AmountMath } from '@agoric/ertp'; import { makeScalarMapStore } from '@agoric/store'; +import { notForProductionUse } from '@agoric/internal/src/magic-cookie-test-only.js'; // This vat contains two starting mints for demos: moolaMint and // simoleanMint. @@ -21,13 +22,16 @@ export function buildRootObject() { getIssuers: issuerNames => issuerNames.map(api.getIssuer), /** - * NOTE: a mint is ability to mint new digital assets, + * WARNING: a mint is ability to mint new digital assets, * a very powerful authority that is usually closely held. * But this mint is for demo / faucet purposes. * * @param {string} name */ - getMint: name => mintsAndBrands.get(name).mint, + getMint: name => { + notForProductionUse(); + return mintsAndBrands.get(name).mint; + }, /** @param {string[]} issuerNames */ getMints: issuerNames => issuerNames.map(api.getMint), /** diff --git a/packages/vats/test/test-boot-config.js b/packages/vats/test/test-boot-config.js index ed89cad955f..011cb8e26f9 100644 --- a/packages/vats/test/test-boot-config.js +++ b/packages/vats/test/test-boot-config.js @@ -1,13 +1,17 @@ // @ts-check -import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; +import { test as anyTest } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; import { promises as fsPromises } from 'fs'; import path from 'path'; import { mustMatch } from '@agoric/store'; -import { shape as ssShape } from '@agoric/swingset-vat'; +import { loadSwingsetConfigFile, shape as ssShape } from '@agoric/swingset-vat'; +import { makeNodeBundleCache } from '@agoric/swingset-vat/tools/bundleTool.js'; import { ParametersShape as BootParametersShape } from '../src/core/boot-psm.js'; +/** @type {import('ava').TestFn>>} */ +const test = anyTest; + const CONFIG_FILES = [ 'decentral-core-config.json', 'decentral-demo-config.json', @@ -18,34 +22,97 @@ const CONFIG_FILES = [ 'decentral-test-vaults-config.json', ]; -/** - * @typedef {{ - * asset: (...ps: string[]) => Promise, - * }} Context - * @typedef {import('ava').ExecutionContext } TestCtx - */ +const PROD_CONFIG_FILES = [ + 'decentral-main-psm-config.json', + 'decentral-psm-config.json', + 'decentral-test-vaults-config.json', +]; + +const NON_UPGRADEABLE_VATS = [ + // TODO: move vat-network to a CoreEval proposal + // 'vat-network', + // 'vat-ibc', + // TODO: prune centralSupply from prod config + // 'centralSupply', + 'mints', + 'sharing', +]; -// NOTE: confine ambient authority to test.before -test.before(t => { +// #region NOTE: confine ambient authority to test.before +const makeTestContext = async () => { const pathname = new URL(import.meta.url).pathname; const dirname = path.dirname(pathname); - const asset = (...ps) => - fsPromises.readFile(path.join(dirname, ...ps), 'utf-8'); - t.context = { asset }; + const resolve = (...ps) => path.join(dirname, ...ps); + const asset = (...ps) => fsPromises.readFile(resolve(...ps), 'utf-8'); + + const cacheDir = resolve('..', 'bundles'); + const bundleCache = await makeNodeBundleCache(cacheDir, {}, s => import(s)); + + return { asset, bundleCache, cacheDir, resolve, basename: path.basename }; +}; + +test.before(async t => { + t.context = await makeTestContext(); }); +// #endregion -test('Bootstrap SwingSet config file syntax', /** @param {TestCtx} t */ async t => { +test('Bootstrap SwingSet config file syntax', async t => { const { asset } = t.context; await Promise.all( CONFIG_FILES.map(async f => { const txt = await asset('..', f); const config = harden(JSON.parse(txt)); - await t.notThrows(() => mustMatch(config, ssShape.SwingSetConfig), f); + t.notThrows(() => mustMatch(config, ssShape.SwingSetConfig), f); const parameters = config?.vats?.bootstrap?.parameters; t.log('syntax check:', f, parameters ? 'and parameters' : ''); - (await parameters) && + parameters && t.notThrows(() => mustMatch(parameters, BootParametersShape), f); }), ); }); + +test('no test-only code is in production configs', async t => { + const { basename, bundleCache, resolve } = t.context; + const { entries } = Object; + + const seen = new Set(); + + const noLog = () => {}; + + for await (const configSpec of PROD_CONFIG_FILES) { + t.log('checking config', configSpec); + const fullPath = resolve('..', configSpec); + const config = await loadSwingsetConfigFile(fullPath); + if (!config) throw t.truthy(config, configSpec); // if/throw refines type + const { bundles } = config; + if (!bundles) throw t.truthy(bundles, configSpec); + + for await (const [name, spec] of entries(bundles)) { + if (!('sourceSpec' in spec)) throw t.fail(); + + // t.log('checking bundle path', name, spec.sourceSpec); + for (const vatName of NON_UPGRADEABLE_VATS) { + if (spec.sourceSpec.includes(vatName)) { + t.fail(`${configSpec} bundle ${spec.sourceSpec} not upgradeable`); + } + } + + await bundleCache.load(spec.sourceSpec, undefined, noLog); + const targetName = basename(spec.sourceSpec, '.js'); + + if (!seen.has(targetName)) { + seen.add(targetName); + t.log('checking bundle', targetName); + const meta = await bundleCache.validate(targetName); + t.truthy(meta, name); + + for (const item of meta.contents) { + if (item.relativePath.includes('magic-cookie-test-only')) { + t.fail(`${configSpec} bundle ${name}: ${item.relativePath}`); + } + } + } + } + } +}); From 74d5f33afbf81c4f0383632269e606d31003b7f5 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Fri, 3 Mar 2023 13:54:08 -0600 Subject: [PATCH 20/38] fix(vats): prune mints/faucet from prod-like vats config --- packages/vats/decentral-test-vaults-config.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/vats/decentral-test-vaults-config.json b/packages/vats/decentral-test-vaults-config.json index 0f497fe61f2..edf1210ff86 100644 --- a/packages/vats/decentral-test-vaults-config.json +++ b/packages/vats/decentral-test-vaults-config.json @@ -177,9 +177,6 @@ "ibc": { "sourceSpec": "@agoric/vats/src/vat-ibc.js" }, - "mints": { - "sourceSpec": "@agoric/vats/src/vat-mints.js" - }, "network": { "sourceSpec": "@agoric/vats/src/vat-network.js" }, From 46d1ed21089701ec56dbb5f90603ffa69d5c8612 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Mon, 6 Mar 2023 13:28:11 -0600 Subject: [PATCH 21/38] chore(vats): prune sharing vat from test-vaults-config --- packages/vats/decentral-test-vaults-config.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/vats/decentral-test-vaults-config.json b/packages/vats/decentral-test-vaults-config.json index edf1210ff86..09a03a3ed8c 100644 --- a/packages/vats/decentral-test-vaults-config.json +++ b/packages/vats/decentral-test-vaults-config.json @@ -189,9 +189,6 @@ "provisioning": { "sourceSpec": "@agoric/vats/src/vat-provisioning.js" }, - "sharing": { - "sourceSpec": "@agoric/vats/src/vat-sharing.js" - }, "walletFactory": { "sourceSpec": "@agoric/smart-wallet/src/walletFactory.js" }, From 394b1541e106fd998085a32b14b2c4b3ea60c9ba Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 2 Mar 2023 21:25:20 -0600 Subject: [PATCH 22/38] chore: move sim stuff out of inter-protocol --- .../inter-protocol/src/proposals/core-proposal.js | 1 - packages/inter-protocol/src/proposals/sim-proposal.js | 3 --- packages/vats/src/core/boot-sim.js | 11 ++++++----- .../src/proposals => vats/src/core}/demoIssuers.js | 4 ++-- .../src/proposals => vats/src/core}/sim-behaviors.js | 3 +-- packages/vats/test/test-clientBundle.js | 7 ++----- .../{inter-protocol => vats}/test/test-demoAMM.js | 6 ++++-- 7 files changed, 15 insertions(+), 20 deletions(-) delete mode 100644 packages/inter-protocol/src/proposals/sim-proposal.js rename packages/{inter-protocol/src/proposals => vats/src/core}/demoIssuers.js (98%) rename packages/{inter-protocol/src/proposals => vats/src/core}/sim-behaviors.js (96%) rename packages/{inter-protocol => vats}/test/test-demoAMM.js (93%) diff --git a/packages/inter-protocol/src/proposals/core-proposal.js b/packages/inter-protocol/src/proposals/core-proposal.js index b35361bc413..79a3729c552 100644 --- a/packages/inter-protocol/src/proposals/core-proposal.js +++ b/packages/inter-protocol/src/proposals/core-proposal.js @@ -3,7 +3,6 @@ import * as econBehaviors from './econ-behaviors.js'; import { ECON_COMMITTEE_MANIFEST } from './startEconCommittee.js'; export * from './econ-behaviors.js'; -export * from './sim-behaviors.js'; // @ts-expect-error Module './econ-behaviors.js' has already exported a member // named 'EconomyBootstrapPowers'. export * from './startPSM.js'; // eslint-disable-line import/export diff --git a/packages/inter-protocol/src/proposals/sim-proposal.js b/packages/inter-protocol/src/proposals/sim-proposal.js deleted file mode 100644 index 01f440fe0cd..00000000000 --- a/packages/inter-protocol/src/proposals/sim-proposal.js +++ /dev/null @@ -1,3 +0,0 @@ -// XXX from core-proposal.js - -export const SIM_CHAIN_MANIFEST = harden({}); diff --git a/packages/vats/src/core/boot-sim.js b/packages/vats/src/core/boot-sim.js index c40aa401732..d7bf5d06ce4 100644 --- a/packages/vats/src/core/boot-sim.js +++ b/packages/vats/src/core/boot-sim.js @@ -1,13 +1,13 @@ // @ts-check -import { SIM_CHAIN_BOOTSTRAP_PERMITS } from '@agoric/inter-protocol/src/proposals/sim-behaviors.js'; -import * as simBehaviorsPlus from '@agoric/inter-protocol/src/proposals/sim-behaviors.js'; +import { makeBootstrap } from './lib-boot.js'; + import * as basicBehaviorsPlus from './basic-behaviors.js'; import { SHARED_CHAIN_BOOTSTRAP_MANIFEST } from './chain-behaviors.js'; +import { SIM_CHAIN_BOOTSTRAP_PERMITS } from './sim-behaviors.js'; import * as chainBehaviorsPlus from './chain-behaviors.js'; +import * as simBehaviorsPlus from './sim-behaviors.js'; import * as utils from './utils.js'; -import { makeBootstrap } from './lib-boot.js'; - export const MANIFEST = { ...SHARED_CHAIN_BOOTSTRAP_MANIFEST, ...SIM_CHAIN_BOOTSTRAP_PERMITS, @@ -27,6 +27,8 @@ const { const { SIM_CHAIN_BOOTSTRAP_PERMITS: _sc, ...simBehaviors } = simBehaviorsPlus; const behaviors = { ...basicBehaviors, ...chainBehaviors, ...simBehaviors }; +const modules = harden({ behaviors: { ...behaviors }, utils: { ...utils } }); + /** * Build root object of the bootstrap vat for the simulated chain. * @@ -41,7 +43,6 @@ const behaviors = { ...basicBehaviors, ...chainBehaviors, ...simBehaviors }; export const buildRootObject = (vatPowers, vatParameters) => { console.debug(`sim bootstrap starting`); - const modules = harden({ utils: { ...utils } }); return makeBootstrap(vatPowers, vatParameters, MANIFEST, behaviors, modules); }; diff --git a/packages/inter-protocol/src/proposals/demoIssuers.js b/packages/vats/src/core/demoIssuers.js similarity index 98% rename from packages/inter-protocol/src/proposals/demoIssuers.js rename to packages/vats/src/core/demoIssuers.js index 75cbd821ce2..82fc0dac7cf 100644 --- a/packages/inter-protocol/src/proposals/demoIssuers.js +++ b/packages/vats/src/core/demoIssuers.js @@ -6,9 +6,9 @@ import { natSafeMath, } from '@agoric/zoe/src/contractSupport/index.js'; import { E, Far } from '@endo/far'; -import { Stake, Stable } from '@agoric/vats/src/tokens.js'; import { Nat } from '@endo/nat'; import { notForProductionUse } from '@agoric/internal/src/magic-cookie-test-only.js'; +import { Stake, Stable } from '../tokens.js'; const { Fail, quote: q } = assert; const { multiply, floorDivide } = natSafeMath; @@ -460,7 +460,7 @@ export const poolRates = (issuerName, record, kits, central) => { }; /** - * @param { import('./econ-behaviors.js').EconomyBootstrapPowers & { + * @param { import('@agoric/inter-protocol/src/proposals/econ-behaviors.js').EconomyBootstrapPowers & { * consume: { mints } * }} powers */ diff --git a/packages/inter-protocol/src/proposals/sim-behaviors.js b/packages/vats/src/core/sim-behaviors.js similarity index 96% rename from packages/inter-protocol/src/proposals/sim-behaviors.js rename to packages/vats/src/core/sim-behaviors.js index 26e456c3473..10ea676ea4a 100644 --- a/packages/inter-protocol/src/proposals/sim-behaviors.js +++ b/packages/vats/src/core/sim-behaviors.js @@ -1,7 +1,6 @@ import { E, Far } from '@endo/far'; -import { addRemote } from '@agoric/vats/src/core/utils.js'; - import { connectFaucet } from './demoIssuers.js'; +import { addRemote } from './utils.js'; export { connectFaucet }; diff --git a/packages/vats/test/test-clientBundle.js b/packages/vats/test/test-clientBundle.js index fcb22755224..bf7b74feb39 100644 --- a/packages/vats/test/test-clientBundle.js +++ b/packages/vats/test/test-clientBundle.js @@ -7,11 +7,8 @@ import { E, Far } from '@endo/far'; import { makeZoeKit } from '@agoric/zoe'; import { makeIssuerKit } from '@agoric/ertp'; -import { - connectFaucet, - showAmount, -} from '@agoric/inter-protocol/src/proposals/demoIssuers.js'; import { makeScalarBigMapStore } from '@agoric/vat-data'; +import { connectFaucet, showAmount } from '../src/core/demoIssuers.js'; import { setupClientManager } from '../src/core/chain-behaviors.js'; import { makeAgoricNamesAccess } from '../src/core/utils.js'; import { makePromiseSpace } from '../src/core/promise-space.js'; @@ -146,7 +143,7 @@ test('connectFaucet produces payments', async t => { // t.deepEqual(Object.keys(userBundle), '@@todo'); - /** @type { import('@agoric/inter-protocol/src/proposals/demoIssuers.js').UserPaymentRecord[] } */ + /** @type { import('../src/core/demoIssuers.js').UserPaymentRecord[] } */ const pmts = await E(userBundle.faucet).tapFaucet(); const detail = await Promise.all( diff --git a/packages/inter-protocol/test/test-demoAMM.js b/packages/vats/test/test-demoAMM.js similarity index 93% rename from packages/inter-protocol/test/test-demoAMM.js rename to packages/vats/test/test-demoAMM.js index 1f9c35346e5..f2b6f5c7d26 100644 --- a/packages/inter-protocol/test/test-demoAMM.js +++ b/packages/vats/test/test-demoAMM.js @@ -1,7 +1,7 @@ // eslint-disable-next-line import/no-extraneous-dependencies import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; import { AmountMath, makeIssuerKit } from '@agoric/ertp'; -import { Stable } from '@agoric/vats/src/tokens.js'; +import { Stable } from '../src/tokens.js'; import { AMMDemoState, @@ -12,17 +12,19 @@ import { showAmount, showBrand, splitAllCentralPayments, -} from '../src/proposals/demoIssuers.js'; +} from '../src/core/demoIssuers.js'; /** @param { bigint } n */ const showIST = n => `${decimal(n, 6)} IST`; +// TODO: prune showIST formatting utility test('uist -> IST formatting test utility', t => { t.is(showIST(123456789n), '123.456789 IST', 'IST decimal point'); t.is(showIST(1234567890n), '1_234.56789 IST', 'thousands separators'); t.is(showIST(3286010000000000n), '3_286_010_000 IST', 'regression 1'); }); +// TODO: prune splitAllCentralPayments AMM utility? test('splitAllCentralPayments: count entries, spot check', async t => { const central = makeIssuerKit( Stable.symbol, From d1e8740b9d32cc8b0425d342b1f820d9501219c7 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Mon, 6 Mar 2023 16:05:13 -0600 Subject: [PATCH 23/38] chore(vats): clarify which vat bootstrap items go --- packages/vats/src/core/basic-behaviors.js | 4 ++-- packages/vats/src/core/chain-behaviors.js | 28 +++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/vats/src/core/basic-behaviors.js b/packages/vats/src/core/basic-behaviors.js index 7fc1ed25968..b035dd7d9d6 100644 --- a/packages/vats/src/core/basic-behaviors.js +++ b/packages/vats/src/core/basic-behaviors.js @@ -461,7 +461,7 @@ export const BASIC_BOOTSTRAP_PERMITS = harden({ vatAdmin: 'vatAdmin', }, devices: { - vatAdmin: true, + vatAdmin: 'kernel', }, produce: { vatAdminSvc: 'vatAdmin', @@ -543,7 +543,7 @@ export const BASIC_BOOTSTRAP_PERMITS = harden({ consume: { agoricNamesAdmin: true, initialSupply: true, - bridgeManager: true, + bridgeManager: 'chainStorage', // TODO: re-org loadCriticalVat to be subject to permits loadCriticalVat: true, zoe: true, diff --git a/packages/vats/src/core/chain-behaviors.js b/packages/vats/src/core/chain-behaviors.js index 9e0a6a2e32c..a5b07735bf6 100644 --- a/packages/vats/src/core/chain-behaviors.js +++ b/packages/vats/src/core/chain-behaviors.js @@ -554,15 +554,15 @@ export const SHARED_CHAIN_BOOTSTRAP_MANIFEST = { consume: { loadCriticalVat: true }, devices: { bridge: 'kernel' }, produce: { - bridgeManager: true, - provisionBridgeManager: true, - provisionWalletBridgeManager: true, - walletBridgeManager: true, + bridgeManager: 'chainStorage', + provisionBridgeManager: 'chainStorage', + provisionWalletBridgeManager: 'chainStorage', + walletBridgeManager: 'chainStorage', }, }, [startTimerService.name]: { devices: { - timer: true, + timer: 'kernel', }, vats: { timer: 'timer', @@ -595,16 +595,16 @@ export const SHARED_CHAIN_BOOTSTRAP_MANIFEST = { provisioning: 'provisioning', }, vats: { - comms: true, - vattp: true, + comms: 'comms', + vattp: 'vattp', }, }, [bridgeProvisioner.name]: { consume: { provisioning: true, - bridgeManager: true, - provisionBridgeManager: true, - provisionWalletBridgeManager: true, + bridgeManager: 'chainStorage', + provisionBridgeManager: 'chainStorage', + provisionWalletBridgeManager: 'chainStorage', }, }, [setupClientManager.name]: { @@ -617,12 +617,12 @@ export const SHARED_CHAIN_BOOTSTRAP_MANIFEST = { consume: { client: true, loadCriticalVat: true, - bridgeManager: true, - zoe: true, - provisioning: true, + bridgeManager: 'chainStorage', + zoe: 'zoe', + provisioning: 'provisioning', }, produce: { - networkVat: true, + networkVat: 'network', }, }, }; From b2f49e385f0fea2b5e4a444b0fd51a26e761ca0b Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Mon, 6 Mar 2023 17:11:03 -0600 Subject: [PATCH 24/38] test(vats): bootstrap visualization snapshot --- .../test/snapshots/test-boot-config.js.md | 279 ++++++++++++++++++ .../test/snapshots/test-boot-config.js.snap | Bin 0 -> 1833 bytes packages/vats/test/test-boot-config.js | 50 +++- 3 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 packages/vats/test/snapshots/test-boot-config.js.md create mode 100644 packages/vats/test/snapshots/test-boot-config.js.snap diff --git a/packages/vats/test/snapshots/test-boot-config.js.md b/packages/vats/test/snapshots/test-boot-config.js.md new file mode 100644 index 00000000000..7c9cb37e562 --- /dev/null +++ b/packages/vats/test/snapshots/test-boot-config.js.md @@ -0,0 +1,279 @@ +# Snapshot report for `test/test-boot-config.js` + +The actual snapshot is saved in `test-boot-config.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## bootstrap permit visualization snapshot + +> Snapshot 1 + + `digraph G {␊ + rankdir = LR;␊ + subgraph cluster_priceAuthority {␊ + label = "priceAuthority"␊ + "space_priceAuthorityVat" [label="priceAuthorityVat", shape=house, style=filled, fillcolor=khaki];␊ + "space_priceAuthority" [label="priceAuthority", shape=house, style=filled, fillcolor=khaki];␊ + "space_priceAuthorityAdmin" [label="priceAuthorityAdmin", shape=house, style=filled, fillcolor=khaki];␊ + }␊ + subgraph cluster_vatAdmin {␊ + label = "vatAdmin"␊ + "vats_vatAdmin" [label="vatAdmin", shape=doubleoctagon, style=filled, fillcolor=tomato];␊ + "space_vatAdminSvc" [label="vatAdminSvc", shape=house, style=filled, fillcolor=khaki];␊ + }␊ + subgraph cluster_kernel {␊ + label = "kernel"␊ + "devices_vatAdmin" [label="vatAdmin", shape=box, style=filled, fillcolor=gold];␊ + "devices_bridge" [label="bridge", shape=box, style=filled, fillcolor=gold];␊ + "devices_timer" [label="timer", shape=box, style=filled, fillcolor=gold];␊ + }␊ + subgraph cluster_zoe {␊ + label = "zoe"␊ + "space_zoe" [label="zoe", shape=house, style=filled, fillcolor=khaki];␊ + "space_feeMintAccess" [label="feeMintAccess", shape=house, style=filled, fillcolor=khaki];␊ + "issuer_Invitation" [label="Invitation", shape=trapezium, style=filled, fillcolor=chocolate];␊ + "brand_Invitation" [label="Invitation", shape=Mcircle, style=filled, fillcolor=chocolate2];␊ + "space_zoe" [label="zoe", shape=house, style=filled, fillcolor=khaki];␊ + "installation_centralSupply" [label="centralSupply", shape=cylinder];␊ + "installation_mintHolder" [label="mintHolder", shape=cylinder];␊ + "installation_centralSupply" [label="centralSupply", shape=cylinder];␊ + "issuer_IST" [label="IST", shape=trapezium, style=filled, fillcolor=chocolate];␊ + "brand_IST" [label="IST", shape=Mcircle, style=filled, fillcolor=chocolate2];␊ + "installation_centralSupply" [label="centralSupply", shape=cylinder];␊ + "installation_mintHolder" [label="mintHolder", shape=cylinder];␊ + "space_zoe" [label="zoe", shape=house, style=filled, fillcolor=khaki];␊ + }␊ + subgraph cluster_board {␊ + label = "board"␊ + "space_board" [label="board", shape=house, style=filled, fillcolor=khaki];␊ + "space_board" [label="board", shape=house, style=filled, fillcolor=khaki];␊ + }␊ + subgraph cluster_provisioning {␊ + label = "provisioning"␊ + "home" [label="home"];␊ + "home" [label="home"];␊ + "home" [label="home"];␊ + "space_provisioning" [label="provisioning", shape=house, style=filled, fillcolor=khaki];␊ + "space_provisioning" [label="provisioning", shape=house, style=filled, fillcolor=khaki];␊ + "home" [label="home"];␊ + }␊ + subgraph cluster_bank {␊ + label = "bank"␊ + "space_bankManager" [label="bankManager", shape=house, style=filled, fillcolor=khaki];␊ + "home_bank" [label="bank", shape=folder];␊ + "space_bankManager" [label="bankManager", shape=house, style=filled, fillcolor=khaki];␊ + }␊ + subgraph cluster_walletFactory {␊ + label = "walletFactory"␊ + "space_walletFactoryStartResult" [label="walletFactoryStartResult", shape=house, style=filled, fillcolor=khaki];␊ + }␊ + subgraph cluster_chainStorage {␊ + label = "chainStorage"␊ + "space_bridgeManager" [label="bridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_bridgeManager" [label="bridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_provisionBridgeManager" [label="provisionBridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_provisionWalletBridgeManager" [label="provisionWalletBridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_walletBridgeManager" [label="walletBridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_chainStorage" [label="chainStorage", shape=house, style=filled, fillcolor=khaki];␊ + "space_chainStorage" [label="chainStorage", shape=house, style=filled, fillcolor=khaki];␊ + "space_bridgeManager" [label="bridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_provisionBridgeManager" [label="provisionBridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_provisionWalletBridgeManager" [label="provisionWalletBridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_bridgeManager" [label="bridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + }␊ + subgraph cluster_BLD {␊ + label = "BLD"␊ + "issuer_BLD" [label="BLD", shape=trapezium, style=filled, fillcolor=chocolate];␊ + "brand_BLD" [label="BLD", shape=Mcircle, style=filled, fillcolor=chocolate2];␊ + }␊ + subgraph cluster_timer {␊ + label = "timer"␊ + "vats_timer" [label="timer", shape=doubleoctagon, style=filled, fillcolor=tomato];␊ + "space_chainTimerService" [label="chainTimerService", shape=house, style=filled, fillcolor=khaki];␊ + "home_chainTimerService" [label="chainTimerService", shape=folder];␊ + }␊ + subgraph cluster_comms {␊ + label = "comms"␊ + "vats_comms" [label="comms", shape=doubleoctagon, style=filled, fillcolor=tomato];␊ + }␊ + subgraph cluster_vattp {␊ + label = "vattp"␊ + "vats_vattp" [label="vattp", shape=doubleoctagon, style=filled, fillcolor=tomato];␊ + }␊ + subgraph cluster_network {␊ + label = "network"␊ + "space_networkVat" [label="networkVat", shape=house, style=filled, fillcolor=khaki];␊ + }␊ + "makeOracleBrands" [label="makeOracleBrands"];␊ + "oracleBrand_USD" [label="USD"];␊ + "startPriceAuthority" [label="startPriceAuthority"];␊ + "space_priceAuthorityVat" [label="priceAuthorityVat", shape=house, style=filled, fillcolor=khaki];␊ + "space_priceAuthority" [label="priceAuthority", shape=house, style=filled, fillcolor=khaki];␊ + "space_priceAuthorityAdmin" [label="priceAuthorityAdmin", shape=house, style=filled, fillcolor=khaki];␊ + "makeVatsFromBundles" [label="makeVatsFromBundles"];␊ + "vats_vatAdmin" [label="vatAdmin", shape=doubleoctagon, style=filled, fillcolor=tomato];␊ + "devices_vatAdmin" [label="vatAdmin", shape=box, style=filled, fillcolor=gold];␊ + "space_vatAdminSvc" [label="vatAdminSvc", shape=house, style=filled, fillcolor=khaki];␊ + "space_loadVat" [label="loadVat", shape=house, style=filled, fillcolor=khaki];␊ + "space_loadCriticalVat" [label="loadCriticalVat", shape=house, style=filled, fillcolor=khaki];␊ + "space_vatStore" [label="vatStore", shape=house, style=filled, fillcolor=khaki];␊ + "buildZoe" [label="buildZoe"];␊ + "space_zoe" [label="zoe", shape=house, style=filled, fillcolor=khaki];␊ + "space_feeMintAccess" [label="feeMintAccess", shape=house, style=filled, fillcolor=khaki];␊ + "space_vatAdminSvc" [label="vatAdminSvc", shape=house, style=filled, fillcolor=khaki];␊ + "issuer_Invitation" [label="Invitation", shape=trapezium, style=filled, fillcolor=chocolate];␊ + "brand_Invitation" [label="Invitation", shape=Mcircle, style=filled, fillcolor=chocolate2];␊ + "makeBoard" [label="makeBoard"];␊ + "space_board" [label="board", shape=house, style=filled, fillcolor=khaki];␊ + "makeAddressNameHubs" [label="makeAddressNameHubs"];␊ + "space_namesByAddress" [label="namesByAddress", shape=house, style=filled, fillcolor=khaki];␊ + "space_namesByAddressAdmin" [label="namesByAddressAdmin", shape=house, style=filled, fillcolor=khaki];␊ + "home_myAddressNameAdmin" [label="myAddressNameAdmin", shape=folder];␊ + "home" [label="home"];␊ + "makeClientBanks" [label="makeClientBanks"];␊ + "space_namesByAddressAdmin" [label="namesByAddressAdmin", shape=house, style=filled, fillcolor=khaki];␊ + "space_bankManager" [label="bankManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_walletFactoryStartResult" [label="walletFactoryStartResult", shape=house, style=filled, fillcolor=khaki];␊ + "home_bank" [label="bank", shape=folder];␊ + "home" [label="home"];␊ + "installBootContracts" [label="installBootContracts"];␊ + "space_zoe" [label="zoe", shape=house, style=filled, fillcolor=khaki];␊ + "space_vatAdminSvc" [label="vatAdminSvc", shape=house, style=filled, fillcolor=khaki];␊ + "installation_centralSupply" [label="centralSupply", shape=cylinder];␊ + "installation_mintHolder" [label="mintHolder", shape=cylinder];␊ + "mintInitialSupply" [label="mintInitialSupply"];␊ + "space_initialSupply" [label="initialSupply", shape=house, style=filled, fillcolor=khaki];␊ + "space_feeMintAccess" [label="feeMintAccess", shape=house, style=filled, fillcolor=khaki];␊ + "space_zoe" [label="zoe", shape=house, style=filled, fillcolor=khaki];␊ + "installation_centralSupply" [label="centralSupply", shape=cylinder];␊ + "addBankAssets" [label="addBankAssets"];␊ + "space_bankManager" [label="bankManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_bldIssuerKit" [label="bldIssuerKit", shape=house, style=filled, fillcolor=khaki];␊ + "space_agoricNamesAdmin" [label="agoricNamesAdmin", shape=house, style=filled, fillcolor=khaki];␊ + "space_initialSupply" [label="initialSupply", shape=house, style=filled, fillcolor=khaki];␊ + "space_bridgeManager" [label="bridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_zoe" [label="zoe", shape=house, style=filled, fillcolor=khaki];␊ + "issuer_BLD" [label="BLD", shape=trapezium, style=filled, fillcolor=chocolate];␊ + "issuer_IST" [label="IST", shape=trapezium, style=filled, fillcolor=chocolate];␊ + "brand_BLD" [label="BLD", shape=Mcircle, style=filled, fillcolor=chocolate2];␊ + "brand_IST" [label="IST", shape=Mcircle, style=filled, fillcolor=chocolate2];␊ + "installation_centralSupply" [label="centralSupply", shape=cylinder];␊ + "installation_mintHolder" [label="mintHolder", shape=cylinder];␊ + "makeBridgeManager" [label="makeBridgeManager"];␊ + "devices_bridge" [label="bridge", shape=box, style=filled, fillcolor=gold];␊ + "space_bridgeManager" [label="bridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_provisionBridgeManager" [label="provisionBridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_provisionWalletBridgeManager" [label="provisionWalletBridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_walletBridgeManager" [label="walletBridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "startTimerService" [label="startTimerService"];␊ + "vats_timer" [label="timer", shape=doubleoctagon, style=filled, fillcolor=tomato];␊ + "devices_timer" [label="timer", shape=box, style=filled, fillcolor=gold];␊ + "space_chainTimerService" [label="chainTimerService", shape=house, style=filled, fillcolor=khaki];␊ + "home_chainTimerService" [label="chainTimerService", shape=folder];␊ + "home" [label="home"];␊ + "makeChainStorage" [label="makeChainStorage"];␊ + "space_chainStorage" [label="chainStorage", shape=house, style=filled, fillcolor=khaki];␊ + "space_bridgeManager" [label="bridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "publishAgoricNames" [label="publishAgoricNames"];␊ + "space_agoricNamesAdmin" [label="agoricNamesAdmin", shape=house, style=filled, fillcolor=khaki];␊ + "space_board" [label="board", shape=house, style=filled, fillcolor=khaki];␊ + "space_chainStorage" [label="chainStorage", shape=house, style=filled, fillcolor=khaki];␊ + "makeProvisioner" [label="makeProvisioner"];␊ + "vats_comms" [label="comms", shape=doubleoctagon, style=filled, fillcolor=tomato];␊ + "vats_vattp" [label="vattp", shape=doubleoctagon, style=filled, fillcolor=tomato];␊ + "space_provisioning" [label="provisioning", shape=house, style=filled, fillcolor=khaki];␊ + "space_clientCreator" [label="clientCreator", shape=house, style=filled, fillcolor=khaki];␊ + "bridgeProvisioner" [label="bridgeProvisioner"];␊ + "space_provisioning" [label="provisioning", shape=house, style=filled, fillcolor=khaki];␊ + "space_bridgeManager" [label="bridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_provisionBridgeManager" [label="provisionBridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_provisionWalletBridgeManager" [label="provisionWalletBridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "setupClientManager" [label="setupClientManager"];␊ + "space_client" [label="client", shape=house, style=filled, fillcolor=khaki];␊ + "space_clientCreator" [label="clientCreator", shape=house, style=filled, fillcolor=khaki];␊ + "setupNetworkProtocols" [label="setupNetworkProtocols"];␊ + "space_networkVat" [label="networkVat", shape=house, style=filled, fillcolor=khaki];␊ + "space_bridgeManager" [label="bridgeManager", shape=house, style=filled, fillcolor=khaki];␊ + "space_zoe" [label="zoe", shape=house, style=filled, fillcolor=khaki];␊ + "space_provisioning" [label="provisioning", shape=house, style=filled, fillcolor=khaki];␊ + "connectChainFaucet" [label="connectChainFaucet"];␊ + "home_faucet" [label="faucet", shape=folder];␊ + "home" [label="home"];␊ + "makeOracleBrands" -> "oracleBrand_USD" []␊ + "startPriceAuthority" -> "space_priceAuthorityVat" []␊ + "startPriceAuthority" -> "space_priceAuthority" []␊ + "startPriceAuthority" -> "space_priceAuthorityAdmin" []␊ + "makeVatsFromBundles" -> "vats_vatAdmin" [dir=back]␊ + "makeVatsFromBundles" -> "devices_vatAdmin" [dir=back]␊ + "makeVatsFromBundles" -> "space_vatAdminSvc" []␊ + "makeVatsFromBundles" -> "space_loadVat" []␊ + "makeVatsFromBundles" -> "space_loadCriticalVat" []␊ + "makeVatsFromBundles" -> "space_vatStore" []␊ + "buildZoe" -> "space_zoe" []␊ + "buildZoe" -> "space_feeMintAccess" []␊ + "buildZoe" -> "space_vatAdminSvc" [dir=back]␊ + "buildZoe" -> "issuer_Invitation" []␊ + "buildZoe" -> "brand_Invitation" []␊ + "makeBoard" -> "space_board" []␊ + "makeAddressNameHubs" -> "space_namesByAddress" []␊ + "makeAddressNameHubs" -> "space_namesByAddressAdmin" []␊ + "makeAddressNameHubs" -> "home_myAddressNameAdmin" []␊ + "home" -> "home_myAddressNameAdmin" []␊ + "home" -> "home_bank" []␊ + "home" -> "home_chainTimerService" []␊ + "home" -> "home_faucet" []␊ + "makeClientBanks" -> "space_namesByAddressAdmin" [dir=back]␊ + "makeClientBanks" -> "space_bankManager" [dir=back]␊ + "makeClientBanks" -> "space_walletFactoryStartResult" [dir=back]␊ + "makeClientBanks" -> "home_bank" []␊ + "installBootContracts" -> "space_zoe" [dir=back]␊ + "installBootContracts" -> "space_vatAdminSvc" [dir=back]␊ + "installBootContracts" -> "installation_centralSupply" []␊ + "installBootContracts" -> "installation_mintHolder" []␊ + "mintInitialSupply" -> "space_initialSupply" []␊ + "mintInitialSupply" -> "space_feeMintAccess" [dir=back]␊ + "mintInitialSupply" -> "space_zoe" [dir=back]␊ + "mintInitialSupply" -> "installation_centralSupply" [dir=back]␊ + "addBankAssets" -> "space_bankManager" []␊ + "addBankAssets" -> "space_bldIssuerKit" []␊ + "addBankAssets" -> "space_agoricNamesAdmin" [dir=back]␊ + "addBankAssets" -> "space_initialSupply" [dir=back]␊ + "addBankAssets" -> "space_bridgeManager" [dir=back]␊ + "addBankAssets" -> "space_zoe" [dir=back]␊ + "addBankAssets" -> "issuer_BLD" []␊ + "addBankAssets" -> "issuer_IST" []␊ + "addBankAssets" -> "brand_BLD" []␊ + "addBankAssets" -> "brand_IST" []␊ + "addBankAssets" -> "installation_centralSupply" [dir=back]␊ + "addBankAssets" -> "installation_mintHolder" [dir=back]␊ + "makeBridgeManager" -> "devices_bridge" [dir=back]␊ + "makeBridgeManager" -> "space_bridgeManager" []␊ + "makeBridgeManager" -> "space_provisionBridgeManager" []␊ + "makeBridgeManager" -> "space_provisionWalletBridgeManager" []␊ + "makeBridgeManager" -> "space_walletBridgeManager" []␊ + "startTimerService" -> "vats_timer" [dir=back]␊ + "startTimerService" -> "devices_timer" [dir=back]␊ + "startTimerService" -> "space_chainTimerService" []␊ + "startTimerService" -> "home_chainTimerService" []␊ + "makeChainStorage" -> "space_chainStorage" []␊ + "makeChainStorage" -> "space_bridgeManager" [dir=back]␊ + "publishAgoricNames" -> "space_agoricNamesAdmin" [dir=back]␊ + "publishAgoricNames" -> "space_board" [dir=back]␊ + "publishAgoricNames" -> "space_chainStorage" [dir=back]␊ + "makeProvisioner" -> "vats_comms" [dir=back]␊ + "makeProvisioner" -> "vats_vattp" [dir=back]␊ + "makeProvisioner" -> "space_provisioning" []␊ + "makeProvisioner" -> "space_clientCreator" [dir=back]␊ + "bridgeProvisioner" -> "space_provisioning" [dir=back]␊ + "bridgeProvisioner" -> "space_bridgeManager" [dir=back]␊ + "bridgeProvisioner" -> "space_provisionBridgeManager" [dir=back]␊ + "bridgeProvisioner" -> "space_provisionWalletBridgeManager" [dir=back]␊ + "setupClientManager" -> "space_client" []␊ + "setupClientManager" -> "space_clientCreator" []␊ + "setupNetworkProtocols" -> "space_networkVat" []␊ + "setupNetworkProtocols" -> "space_bridgeManager" [dir=back]␊ + "setupNetworkProtocols" -> "space_zoe" [dir=back]␊ + "setupNetworkProtocols" -> "space_provisioning" [dir=back]␊ + "connectChainFaucet" -> "home_faucet" []␊ + }␊ + ` diff --git a/packages/vats/test/snapshots/test-boot-config.js.snap b/packages/vats/test/snapshots/test-boot-config.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..3836ef7c32270ad3d51c046d95ff22335468beac GIT binary patch literal 1833 zcmV+^2iEvORzV8=%I)GA>Cg(Qntj$FMU}GoFTcye4pgwBl-BFKHmnEh3o9oznBwF@%!%r z#(2h4luQzwZU~=jNtPo@?hz*}o@6mfvK8Z`{E>b797TwuKWG1Zb@I)L{QKhTlW)J= z&LXlDW>%A*Cm&8z6t5$aPG*yrZ=RoKd9Y)JG|xCrZ<3UR_$=oumJ)s^!+3~hwSwgD%9(8ROXOROuSm?#LNSC)8Pv&LO_MCkMei@; zE#bwsqYMLDX;p4k_@3k&zvXbn#1F)=v>u4fC~9l`DkN!0YdT$-{y_!h;MkHlosI#SrOro+K3PLpr(i5Z+M|M>w^th#coHM54eP1GGl{{=L{w=Ji_;Xwf)u`h4a( zPS|lodYH6vYybg6X#}@`f>3P&yO!F%ie|r!UX8|K%B&+? znvR`l{_-cd0g2|cD(GaRax5E%6?9&6-3mI#Ac~t59LDZywZHP#Ub}i;c8eAAR$98o zsl448i$`PiI$V2ssE%FNnZq`lOgn5Op$yWlpf#=+P zz9R#7P6>|r9K~xRqLA@`10D&1d1w@)1LWhGoIQj(XN;dSiMNIv%#f2i_(nSXZg&*u zvSeSz;&8N`+bk6g;#SegM|WZ!$=eHxBDt5GWf_KftdmFI00J6a76I8vt3nfog(?U8?&Ohxp0&3E=R=3Zd8{uZiAW8St}0d%$CUzz+~cm=c)) zugmSl+{q!MTB3sj zEtVq(&rB>cqmC&{i|)VLy$Okg7LVwcx{>O>q(R>{f<{X(C@9F@4k^TDq|7HN_HgJc=x| z=M3exEXNj}CkQ2JJu`GwF_O)x=YI`Yl&i3-*dC&`8LrEPEmiFi3&(Rp(@>41_vq?S zU^|@}pufq05fwKKZzeY|+N9vkWWQo9kkejM18){i7+iJJ#2cIB&2eARG)YCcOKrj>9Bu`~%guPpV#=2a7x zayG2tb<$R?W + (args = [], opts = {}) => { + /** @type {ReturnType | undefined } */ + let child; + const exit = new Promise((resolve, reject) => { + // console.debug('spawn', bin, args, { cwd: makefileDir, ...opts }); + child = spawn(bin, args, opts); + child.addListener('exit', code => { + if (code !== 0) { + reject(Error(`exit ${code} from: ${bin} ${args}`)); + return; + } + resolve(0); + }); + }); + return { child: child || assert.fail(), exit }; + }; + // #region NOTE: confine ambient authority to test.before const makeTestContext = async () => { const pathname = new URL(import.meta.url).pathname; @@ -48,7 +72,17 @@ const makeTestContext = async () => { const cacheDir = resolve('..', 'bundles'); const bundleCache = await makeNodeBundleCache(cacheDir, {}, s => import(s)); - return { asset, bundleCache, cacheDir, resolve, basename: path.basename }; + const vizTool = resolve('..', 'tools', 'authorityViz.js'); + const runViz = pspawn(vizTool, { spawn: ambientSpawn }); + + return { + asset, + bundleCache, + cacheDir, + resolve, + basename: path.basename, + runViz, + }; }; test.before(async t => { @@ -116,3 +150,17 @@ test('no test-only code is in production configs', async t => { } } }); + +test('bootstrap permit visualization snapshot', async t => { + const { runViz } = t.context; + + const cmd = runViz(['@agoric/vats/decentral-test-vaults-config.json']); + const output = async () => { + const parts = []; + cmd.child.stdout?.on('data', chunk => parts.push(chunk)); + await cmd.exit; + return parts.join(''); + }; + const diagram = await output(); + t.snapshot(diagram); +}); From 15682d8ea5a5003a59401f2a3b1562901d16976f Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Tue, 7 Mar 2023 14:21:42 -0600 Subject: [PATCH 25/38] test(vats): check production constraints on coreProposals --- packages/vats/test/test-boot-config.js | 126 +++++++++++++++++-------- 1 file changed, 87 insertions(+), 39 deletions(-) diff --git a/packages/vats/test/test-boot-config.js b/packages/vats/test/test-boot-config.js index 76db4ce8513..1261c7cd5f0 100644 --- a/packages/vats/test/test-boot-config.js +++ b/packages/vats/test/test-boot-config.js @@ -8,32 +8,33 @@ import path from 'path'; import { mustMatch } from '@agoric/store'; import { loadSwingsetConfigFile, shape as ssShape } from '@agoric/swingset-vat'; import { makeNodeBundleCache } from '@agoric/swingset-vat/tools/bundleTool.js'; +import { extractCoreProposalBundles } from '@agoric/deploy-script-support/src/extract-proposal.js'; import { ParametersShape as BootParametersShape } from '../src/core/boot-psm.js'; /** @type {import('ava').TestFn>>} */ const test = anyTest; -const CONFIG_FILES = [ - 'decentral-core-config.json', - 'decentral-demo-config.json', - 'decentral-devnet-config.json', +const PROD_CONFIG_FILES = [ 'decentral-main-psm-config.json', 'decentral-psm-config.json', - 'decentral-test-psm-config.json', 'decentral-test-vaults-config.json', + 'decentral-test-psm-config.json', ]; -const PROD_CONFIG_FILES = [ - 'decentral-main-psm-config.json', - 'decentral-psm-config.json', - 'decentral-test-vaults-config.json', +const CONFIG_FILES = [ + 'decentral-core-config.json', // TODO: remove mints from core-config + 'decentral-demo-config.json', + 'decentral-devnet-config.json', + ...PROD_CONFIG_FILES, ]; const NON_UPGRADEABLE_VATS = [ - // TODO: move vat-network to a CoreEval proposal + // TODO(#6687): enforce vat-network + // IDEA: move vat-network to a CoreEval proposal? // 'vat-network', // 'vat-ibc', - // TODO: prune centralSupply from prod config + // 'pegasus', + // TODO(#6687): prune centralSupply from prod config // 'centralSupply', 'mints', 'sharing', @@ -66,20 +67,20 @@ export const pspawn = const makeTestContext = async () => { const pathname = new URL(import.meta.url).pathname; const dirname = path.dirname(pathname); - const resolve = (...ps) => path.join(dirname, ...ps); - const asset = (...ps) => fsPromises.readFile(resolve(...ps), 'utf-8'); + const pathResolve = (...ps) => path.join(dirname, ...ps); + const asset = (...ps) => fsPromises.readFile(pathResolve(...ps), 'utf-8'); - const cacheDir = resolve('..', 'bundles'); + const cacheDir = pathResolve('..', 'bundles'); const bundleCache = await makeNodeBundleCache(cacheDir, {}, s => import(s)); - const vizTool = resolve('..', 'tools', 'authorityViz.js'); + const vizTool = pathResolve('..', 'tools', 'authorityViz.js'); const runViz = pspawn(vizTool, { spawn: ambientSpawn }); return { asset, bundleCache, cacheDir, - resolve, + pathResolve, basename: path.basename, runViz, }; @@ -106,17 +107,60 @@ test('Bootstrap SwingSet config file syntax', async t => { ); }); +const noLog = () => {}; + +const hashCode = s => { + let hash = 0; + let i; + let chr; + if (s.length === 0) return hash; + for (i = 0; i < s.length; i += 1) { + chr = s.charCodeAt(i); + // eslint-disable-next-line no-bitwise + hash = (hash << 5) - hash + chr; + // eslint-disable-next-line no-bitwise + hash |= 0; // Convert to 32bit integer + } + return Math.abs(hash); +}; + +const checkBundle = async (t, sourceSpec, seen, name, configSpec) => { + const { bundleCache, basename } = t.context; + + const targetName = `${hashCode(sourceSpec)}-${basename(sourceSpec, '.js')}`; + + // t.log('checking bundle path', name, spec.sourceSpec); + for (const vatName of NON_UPGRADEABLE_VATS) { + if (targetName.includes(vatName)) { + t.fail(`${configSpec} bundle ${sourceSpec} not upgradeable`); + } + } + + if (!seen.has(targetName)) { + seen.add(targetName); + + t.log(configSpec, ': check bundle:', name, basename(sourceSpec)); + await bundleCache.load(sourceSpec, targetName, noLog); + const meta = await bundleCache.validate(targetName); + t.truthy(meta, name); + + for (const item of meta.contents) { + if (item.relativePath.includes('magic-cookie-test-only')) { + t.fail(`${configSpec} bundle ${name}: ${item.relativePath}`); + } + } + } +}; + test('no test-only code is in production configs', async t => { - const { basename, bundleCache, resolve } = t.context; + const { pathResolve } = t.context; const { entries } = Object; const seen = new Set(); - const noLog = () => {}; - for await (const configSpec of PROD_CONFIG_FILES) { t.log('checking config', configSpec); - const fullPath = resolve('..', configSpec); + const fullPath = pathResolve('..', configSpec); const config = await loadSwingsetConfigFile(fullPath); if (!config) throw t.truthy(config, configSpec); // if/throw refines type const { bundles } = config; @@ -125,28 +169,32 @@ test('no test-only code is in production configs', async t => { for await (const [name, spec] of entries(bundles)) { if (!('sourceSpec' in spec)) throw t.fail(); - // t.log('checking bundle path', name, spec.sourceSpec); - for (const vatName of NON_UPGRADEABLE_VATS) { - if (spec.sourceSpec.includes(vatName)) { - t.fail(`${configSpec} bundle ${spec.sourceSpec} not upgradeable`); - } - } + await checkBundle(t, spec.sourceSpec, seen, name, configSpec); + } + } +}); - await bundleCache.load(spec.sourceSpec, undefined, noLog); - const targetName = basename(spec.sourceSpec, '.js'); +test('no test-only code is in production proposals', async t => { + const { pathResolve } = t.context; - if (!seen.has(targetName)) { - seen.add(targetName); - t.log('checking bundle', targetName); - const meta = await bundleCache.validate(targetName); - t.truthy(meta, name); + const seen = new Set(); - for (const item of meta.contents) { - if (item.relativePath.includes('magic-cookie-test-only')) { - t.fail(`${configSpec} bundle ${name}: ${item.relativePath}`); - } - } - } + for await (const configSpec of PROD_CONFIG_FILES) { + t.log('checking config', configSpec); + const getProposals = async () => { + const fullPath = pathResolve('..', configSpec); + const config = await loadSwingsetConfigFile(fullPath); + if (!config) throw t.truthy(config, configSpec); // if/throw refines type + const { coreProposals } = config; + return coreProposals || []; + }; + + const coreProposals = await getProposals(); + const { bundles } = await extractCoreProposalBundles(coreProposals); + + const { entries } = Object; + for await (const [name, spec] of entries(bundles)) { + await checkBundle(t, spec.sourceSpec, seen, name, configSpec); } } }); From b82073503ef8a184ddffbc7304d1407a32db782a Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Wed, 8 Mar 2023 10:23:29 -0600 Subject: [PATCH 26/38] docs(vats): document purpose etc. of config files --- packages/vats/decentral-core-config.json | 1 + packages/vats/decentral-demo-config.json | 1 + packages/vats/decentral-devnet-config.json | 1 + packages/vats/decentral-main-psm-config.json | 1 + packages/vats/decentral-psm-config.json | 1 + packages/vats/decentral-test-psm-config.json | 1 + packages/vats/decentral-test-vaults-config.json | 1 + 7 files changed, 7 insertions(+) diff --git a/packages/vats/decentral-core-config.json b/packages/vats/decentral-core-config.json index 3560c10fc93..d715e089104 100644 --- a/packages/vats/decentral-core-config.json +++ b/packages/vats/decentral-core-config.json @@ -1,4 +1,5 @@ { + "$comment": "This SwingSet config file (see loadSwingsetConfigFile) is minimal; it has no proposals. It is used by ../cosmic-swingset/Makefile and `agoric start`, which add proposals to it.", "bootstrap": "bootstrap", "defaultReapInterval": 1000, "vats": { diff --git a/packages/vats/decentral-demo-config.json b/packages/vats/decentral-demo-config.json index dd9fd0bcf37..5f651fd2b69 100644 --- a/packages/vats/decentral-demo-config.json +++ b/packages/vats/decentral-demo-config.json @@ -1,4 +1,5 @@ { + "$comment": "This SwingSet config file (see loadSwingsetConfigFile) includes non-production facilities such as a faucet. It is used by the sim chain (agoric start dev) and testnet-load-generator (aka loadgen). TODO: restore vaults proposal", "bootstrap": "bootstrap", "defaultReapInterval": 1000, "snapshotInterval": 1000, diff --git a/packages/vats/decentral-devnet-config.json b/packages/vats/decentral-devnet-config.json index 332784bbbe3..a9072c8f998 100644 --- a/packages/vats/decentral-devnet-config.json +++ b/packages/vats/decentral-devnet-config.json @@ -1,4 +1,5 @@ { + "$comment": "This SwingSet config file (see loadSwingsetConfigFile) includes non-production facilities such as a faucet. It does not include vaults in coreProposals; vaults are expected to be added by devnet governance.", "bootstrap": "bootstrap", "defaultReapInterval": 1000, "snapshotInterval": 1000, diff --git a/packages/vats/decentral-main-psm-config.json b/packages/vats/decentral-main-psm-config.json index fb4e3680a0a..d67ff2f21e9 100644 --- a/packages/vats/decentral-main-psm-config.json +++ b/packages/vats/decentral-main-psm-config.json @@ -1,4 +1,5 @@ { + "$comment": "This config is obsolete. TODO: prune it", "bootstrap": "bootstrap", "defaultReapInterval": 1000, "snapshotInterval": 1000, diff --git a/packages/vats/decentral-psm-config.json b/packages/vats/decentral-psm-config.json index 526148c58e4..d6da255491b 100644 --- a/packages/vats/decentral-psm-config.json +++ b/packages/vats/decentral-psm-config.json @@ -1,4 +1,5 @@ { + "$comment": "This config is obsolete. TODO: prune it", "bootstrap": "bootstrap", "defaultReapInterval": 1000, "snapshotInterval": 1000, diff --git a/packages/vats/decentral-test-psm-config.json b/packages/vats/decentral-test-psm-config.json index 03a13f05eed..e051419a236 100644 --- a/packages/vats/decentral-test-psm-config.json +++ b/packages/vats/decentral-test-psm-config.json @@ -1,4 +1,5 @@ { + "$comment": "This config is obsolete. TODO: prune it", "bootstrap": "bootstrap", "defaultReapInterval": 1000, "snapshotInterval": 1000, diff --git a/packages/vats/decentral-test-vaults-config.json b/packages/vats/decentral-test-vaults-config.json index 09a03a3ed8c..f2e5bed8013 100644 --- a/packages/vats/decentral-test-vaults-config.json +++ b/packages/vats/decentral-test-vaults-config.json @@ -1,4 +1,5 @@ { + "$comment": "This SwingSet config file (see loadSwingsetConfigFile) is designed to bring up vaults test networks in an automated fashion. It includes coreProposals to start vaults. Testing facilities are limited to an initialPrice for ATOM and addresses with known keys.", "bootstrap": "bootstrap", "defaultReapInterval": 1000, "coreProposals": [ From ce4aa3cb29b0b14b3572c531251a330ebcdddd0c Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Wed, 8 Mar 2023 16:24:08 -0600 Subject: [PATCH 27/38] docs: bootstrapArgs is arbitrary JSON-serializable data No change to the runtime names, for now: vatParams.argv --- .../SwingSet/src/controller/initializeSwingset.js | 11 ++++++----- packages/cosmic-swingset/src/launch-chain.js | 10 ++++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/SwingSet/src/controller/initializeSwingset.js b/packages/SwingSet/src/controller/initializeSwingset.js index 90b8a23a66b..449b20bbeee 100644 --- a/packages/SwingSet/src/controller/initializeSwingset.js +++ b/packages/SwingSet/src/controller/initializeSwingset.js @@ -282,7 +282,8 @@ function sortObjectProperties(obj, firsts = []) { return result; } -/** @typedef {{ kernelBundles?: Record, verbose?: boolean, +/** + * @typedef {{ kernelBundles?: Record, verbose?: boolean, * addVatAdmin?: boolean, addComms?: boolean, addVattp?: boolean, * addTimer?: boolean, * }} InitializationOptions @@ -290,14 +291,14 @@ function sortObjectProperties(obj, firsts = []) { /** * @param {SwingSetConfig} config - * @param {string[]} argv + * @param {unknown} bootstrapArgs * @param {SwingStoreKernelStorage} kernelStorage * @param {InitializationOptions} initializationOptions * @param {{ env?: Record }} runtimeOptions */ export async function initializeSwingset( config, - argv = [], + bootstrapArgs, kernelStorage, initializationOptions = {}, runtimeOptions = {}, @@ -353,13 +354,13 @@ export async function initializeSwingset( kvStore.set('lockdownBundle', JSON.stringify(kernelBundles.lockdown)); kvStore.set('supervisorBundle', JSON.stringify(kernelBundles.supervisor)); - if (config.bootstrap && argv) { + if (config.bootstrap && bootstrapArgs) { const bootConfig = config.vats[config.bootstrap]; if (bootConfig) { if (!bootConfig.parameters) { bootConfig.parameters = {}; } - bootConfig.parameters.argv = argv; + bootConfig.parameters.argv = bootstrapArgs; } } diff --git a/packages/cosmic-swingset/src/launch-chain.js b/packages/cosmic-swingset/src/launch-chain.js index bab473a6a97..db22f73fd86 100644 --- a/packages/cosmic-swingset/src/launch-chain.js +++ b/packages/cosmic-swingset/src/launch-chain.js @@ -53,8 +53,8 @@ const getHostKey = path => `host.${path}`; * @param {*} bridgeOutbound * @param {SwingStoreKernelStorage} kernelStorage * @param {string} vatconfig absolute path - * @param {Record} argv XXX argv should be an array but it's being called with object * @param {{ ROLE: string }} env + * @param {unknown} bootstrapArgs JSON-serializable data * @param {*} options */ export async function buildSwingset( @@ -62,7 +62,7 @@ export async function buildSwingset( bridgeOutbound, kernelStorage, vatconfig, - argv, + bootstrapArgs, env, { debugName = undefined, slogCallbacks, slogSender }, ) { @@ -122,8 +122,10 @@ export async function buildSwingset( } config.pinBootstrapRoot = true; - // @ts-expect-error XXX argv object - await initializeSwingset(config, argv, kernelStorage, { debugPrefix }); + await initializeSwingset(config, bootstrapArgs, kernelStorage, { + // @ts-expect-error debugPrefix? what's that? + debugPrefix, + }); } await ensureSwingsetInitialized(); const controller = await makeSwingsetController( From c62a0d65448f7f1513b4050887a92ea5888cb54a Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Wed, 8 Mar 2023 16:28:17 -0600 Subject: [PATCH 28/38] chore: prune remaining uses of bootstrap sim/chain/client ROLE --- packages/cosmic-swingset/src/chain-main.js | 1 - packages/cosmic-swingset/src/launch-chain.js | 7 +------ packages/cosmic-swingset/src/sim-chain.js | 1 - packages/inter-protocol/scripts/init-core.js | 5 +---- packages/vats/src/core/boot-solo.js | 1 - packages/vats/src/core/types.js | 1 - packages/vats/test/bootstrapTests/supports.js | 2 +- 7 files changed, 3 insertions(+), 15 deletions(-) diff --git a/packages/cosmic-swingset/src/chain-main.js b/packages/cosmic-swingset/src/chain-main.js index ca3ec1d570e..7aa21a7707b 100644 --- a/packages/cosmic-swingset/src/chain-main.js +++ b/packages/cosmic-swingset/src/chain-main.js @@ -302,7 +302,6 @@ export default async function main(progname, args, { env, homedir, agcc }) { }; const argv = { - ROLE: 'chain', bootMsg, }; const vatHref = await importMetaResolve( diff --git a/packages/cosmic-swingset/src/launch-chain.js b/packages/cosmic-swingset/src/launch-chain.js index db22f73fd86..7bf2b959a4d 100644 --- a/packages/cosmic-swingset/src/launch-chain.js +++ b/packages/cosmic-swingset/src/launch-chain.js @@ -53,8 +53,8 @@ const getHostKey = path => `host.${path}`; * @param {*} bridgeOutbound * @param {SwingStoreKernelStorage} kernelStorage * @param {string} vatconfig absolute path - * @param {{ ROLE: string }} env * @param {unknown} bootstrapArgs JSON-serializable data + * @param {{}} env * @param {*} options */ export async function buildSwingset( @@ -66,10 +66,6 @@ export async function buildSwingset( env, { debugName = undefined, slogCallbacks, slogSender }, ) { - // FIXME: Find a better way to propagate the role. - process.env.ROLE = argv.ROLE; - env.ROLE = argv.ROLE; - const debugPrefix = debugName === undefined ? '' : `${debugName}:`; /** @type {import('@agoric/swingset-vat').SwingSetConfig | null} */ let config = await loadSwingsetConfigFile(vatconfig); @@ -277,7 +273,6 @@ export async function launch({ kernelStorage, vatconfig, argv, - // @ts-expect-error process.env default env, { debugName, diff --git a/packages/cosmic-swingset/src/sim-chain.js b/packages/cosmic-swingset/src/sim-chain.js index bfbe05ce81f..b817feb5c9a 100644 --- a/packages/cosmic-swingset/src/sim-chain.js +++ b/packages/cosmic-swingset/src/sim-chain.js @@ -58,7 +58,6 @@ export async function connectToFakeChain(basedir, GCI, delay, inbound) { const mailboxStorage = await makeMapStorage(mailboxFile); const argv = { - ROLE: 'sim-chain', giveMeAllTheAgoricPowers: true, hardcodedClientAddresses: [bootAddress], bootMsg: { diff --git a/packages/inter-protocol/scripts/init-core.js b/packages/inter-protocol/scripts/init-core.js index 0574e6327e8..3b952711fdd 100644 --- a/packages/inter-protocol/scripts/init-core.js +++ b/packages/inter-protocol/scripts/init-core.js @@ -104,7 +104,7 @@ export const mainProposalBuilder = async ({ install: install0, wrapInstall, }) => { - const { ROLE = 'chain', VAULT_FACTORY_CONTROLLER_ADDR } = process.env; + const { VAULT_FACTORY_CONTROLLER_ADDR } = process.env; const install = wrapInstall ? wrapInstall(install0) : install0; @@ -119,7 +119,6 @@ export const mainProposalBuilder = async ({ getManifestCall: [ getManifestForMain.name, { - ROLE, vaultFactoryControllerAddress: VAULT_FACTORY_CONTROLLER_ADDR, installKeys: { ...publishGroup(installKeyGroups.main), @@ -139,7 +138,6 @@ export const defaultProposalBuilder = async ( /** @param {string|undefined} s */ const optBigInt = s => s && BigInt(s); const { - ROLE = env.ROLE || 'chain', vaultFactoryControllerAddress = env.VAULT_FACTORY_CONTROLLER_ADDR, minInitialPoolLiquidity = env.MIN_INITIAL_POOL_LIQUIDITY, endorsedUi, @@ -176,7 +174,6 @@ export const defaultProposalBuilder = async ( getManifestCall: [ getManifestForInterProtocol.name, { - ROLE, vaultFactoryControllerAddress, minInitialPoolLiquidity: optBigInt(minInitialPoolLiquidity), endorsedUi, diff --git a/packages/vats/src/core/boot-solo.js b/packages/vats/src/core/boot-solo.js index c99b19c5243..eefe7897784 100644 --- a/packages/vats/src/core/boot-solo.js +++ b/packages/vats/src/core/boot-solo.js @@ -43,7 +43,6 @@ const modules = harden({ * logger: (msg) => void, * }} vatPowers * @param {{ - * argv: { ROLE: string }, * bootstrapManifest?: Record>, * coreProposalCode?: string, * }} vatParameters diff --git a/packages/vats/src/core/types.js b/packages/vats/src/core/types.js index d0e134ad055..90ad96c90f2 100644 --- a/packages/vats/src/core/types.js +++ b/packages/vats/src/core/types.js @@ -226,7 +226,6 @@ * IDEA/TODO: make types of demo stuff invisible in production behaviors * @typedef {{ * argv: { - * ROLE: string, * hardcodedClientAddresses: string[], * FIXME_GCI: string, * PROVISIONER_INDEX: number, diff --git a/packages/vats/test/bootstrapTests/supports.js b/packages/vats/test/bootstrapTests/supports.js index ffe24fc2130..cd5d19313b9 100644 --- a/packages/vats/test/bootstrapTests/supports.js +++ b/packages/vats/test/bootstrapTests/supports.js @@ -285,7 +285,7 @@ export const makeSwingsetTestKit = async (t, specifier) => { kernelStorage, configPath, [], - { ROLE: 'chain' }, + {}, { debugName: 'TESTBOOT' }, ); console.timeLog('makeSwingsetTestKit', 'buildSwingset'); From bca19bb8ece6e73061846d9ef6ead0e411b4ea13 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Wed, 8 Mar 2023 16:29:12 -0600 Subject: [PATCH 29/38] chore: prune pegasus from test-vaults-config --- packages/vats/decentral-test-vaults-config.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/vats/decentral-test-vaults-config.json b/packages/vats/decentral-test-vaults-config.json index f2e5bed8013..799bd7427a2 100644 --- a/packages/vats/decentral-test-vaults-config.json +++ b/packages/vats/decentral-test-vaults-config.json @@ -17,7 +17,6 @@ } ] }, - "@agoric/pegasus/scripts/init-core.js", { "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", "entrypoint": "psmGovernanceBuilder", From 1326966e4b7d9c4992f9971b6577907f52aab7aa Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Wed, 8 Mar 2023 10:33:27 -0600 Subject: [PATCH 30/38] chore(vats): demo-config meets loadgen constraints: vaults, USDC - test: sim/demo config launches Vaults as expected by loadgen - demo-config: add missing proposals: - add-collateral-core for IbcATOM - price-feed-core - test: fill out expected home properties - installSimEgress: make hardcodedClientAddresses optional - type: prune governanceActions (obsolete in favor of coreProposals) - type: prune bootstrapManifest from BootstrapVatParams - no longer dynamic - rename USDC -> DAI in connectFaucet() - add missing harden()s in nameHub, connectFaucet() - factor out makeHomeFor() --- packages/vats/decentral-demo-config.json | 43 +++++++++++++- packages/vats/src/core/demoIssuers.js | 10 ++-- packages/vats/src/core/sim-behaviors.js | 2 +- packages/vats/src/core/types.js | 6 +- packages/vats/src/nameHub.js | 6 +- packages/vats/test/bootstrapTests/supports.js | 2 +- .../vats/test/bootstrapTests/test-solo-dev.js | 56 ++++++++++++++++--- packages/vats/test/test-clientBundle.js | 2 +- packages/vats/test/test-demoAMM.js | 2 +- 9 files changed, 105 insertions(+), 24 deletions(-) diff --git a/packages/vats/decentral-demo-config.json b/packages/vats/decentral-demo-config.json index 5f651fd2b69..d2730fbfd86 100644 --- a/packages/vats/decentral-demo-config.json +++ b/packages/vats/decentral-demo-config.json @@ -7,7 +7,7 @@ "@agoric/vats/scripts/init-core.js", { "module": "@agoric/inter-protocol/scripts/init-core.js", - "entrypoint": "committeeProposalBuilder", + "entrypoint": "defaultProposalBuilder", "args": [ { "econCommitteeOptions": { @@ -21,6 +21,22 @@ "entrypoint": "psmGovernanceBuilder", "args": [] }, + { + "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", + "entrypoint": "defaultProposalBuilder", + "args": [ + { + "interchainAssetOptions": { + "denom": "ibc/toyatom", + "decimalPlaces": 6, + "initialPrice": 12.34, + "keyword": "IbcATOM", + "oracleBrand": "ATOM", + "proposedName": "ATOM" + } + } + ] + }, { "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", "entrypoint": "psmProposalBuilder", @@ -91,6 +107,31 @@ } ] }, + { + "module": "@agoric/inter-protocol/scripts/price-feed-core.js", + "entrypoint": "defaultProposalBuilder", + "args": [ + { + "AGORIC_INSTANCE_NAME": "ATOM-USD price feed", + "oracleAddresses": [ + "agoric1ldmtatp24qlllgxmrsjzcpe20fvlkp448zcuce", + "agoric140dmkrz2e42ergjj7gyvejhzmjzurvqeq82ang" + ], + "IN_BRAND_LOOKUP": [ + "agoricNames", + "oracleBrand", + "ATOM" + ], + "IN_BRAND_DECIMALS": 6, + "OUT_BRAND_LOOKUP": [ + "agoricNames", + "oracleBrand", + "USD" + ], + "OUT_BRAND_DECIMALS": 4 + } + ] + }, { "module": "@agoric/inter-protocol/scripts/invite-committee-core.js", "entrypoint": "defaultProposalBuilder", diff --git a/packages/vats/src/core/demoIssuers.js b/packages/vats/src/core/demoIssuers.js index 82fc0dac7cf..68eeab7227d 100644 --- a/packages/vats/src/core/demoIssuers.js +++ b/packages/vats/src/core/demoIssuers.js @@ -21,7 +21,7 @@ export const DecimalPlaces = { ATOM: 6, WETH: 18, LINK: 18, - USDC: 18, + DAI: 18, moola: 2, simolean: 0, }; @@ -37,7 +37,9 @@ const FaucetPurseDetail = { balance: 53n, }, LINK: { proposedName: 'Oracle fee', balance: 51n }, - USDC: { proposedName: 'USD Coin', balance: 1_323n }, + // WAS: USDC, but that interacts poorly with loadgen + // TODO: move connectFaucet from sim-behaviors to a coreProposal + DAI: { proposedName: 'DAI', balance: 1_323n }, }; const PCT = 100n; @@ -147,7 +149,7 @@ export const AMMDemoState = { ], }, - USDC: { + DAI: { config: { ...defaultConfig, collateralValue: 10_000_000n, @@ -324,7 +326,7 @@ export const connectFaucet = async ({ }), ); - const faucetPaymentInfo = userPaymentRecords.flat(); + const faucetPaymentInfo = harden(userPaymentRecords.flat()); const userFeePurse = await E(E(zoe).getFeeIssuer()).makeEmptyPurse(); diff --git a/packages/vats/src/core/sim-behaviors.js b/packages/vats/src/core/sim-behaviors.js index 10ea676ea4a..3711baab4e7 100644 --- a/packages/vats/src/core/sim-behaviors.js +++ b/packages/vats/src/core/sim-behaviors.js @@ -13,7 +13,7 @@ export const installSimEgress = async ({ const PROVISIONER_INDEX = 1; await Promise.all( - argv.hardcodedClientAddresses.map(async (addr, i) => { + (argv?.hardcodedClientAddresses || []).map(async (addr, i) => { const clientFacet = await E(clientCreator).createClientFacet( `solo${i}`, addr, diff --git a/packages/vats/src/core/types.js b/packages/vats/src/core/types.js index 90ad96c90f2..913f9177ae5 100644 --- a/packages/vats/src/core/types.js +++ b/packages/vats/src/core/types.js @@ -226,12 +226,10 @@ * IDEA/TODO: make types of demo stuff invisible in production behaviors * @typedef {{ * argv: { - * hardcodedClientAddresses: string[], + * hardcodedClientAddresses?: string[], * FIXME_GCI: string, - * PROVISIONER_INDEX: number, + * PROVISIONER_INDEX?: number, * }, - * bootstrapManifest?: Record>, - * governanceActions?: boolean, * }} BootstrapVatParams * @typedef { BootstrapSpace & { * devices: SoloDevices | ChainDevices, diff --git a/packages/vats/src/nameHub.js b/packages/vats/src/nameHub.js index f270619a8bb..7606b0edcad 100644 --- a/packages/vats/src/nameHub.js +++ b/packages/vats/src/nameHub.js @@ -38,7 +38,7 @@ export const makeNameHubKit = () => { return E(firstValue).lookup(...remaining); }, entries: () => { - return [ + return harden([ ...mapIterable( keyToRecord.entries(), ([key, record]) => @@ -47,7 +47,7 @@ export const makeNameHubKit = () => { record.promise || record.value, ]), ), - ]; + ]); }, values: () => { return [ @@ -58,7 +58,7 @@ export const makeNameHubKit = () => { ]; }, keys: () => { - return [...keyToRecord.keys()]; + return harden([...keyToRecord.keys()]); }, }); diff --git a/packages/vats/test/bootstrapTests/supports.js b/packages/vats/test/bootstrapTests/supports.js index cd5d19313b9..5fcc3bfbaca 100644 --- a/packages/vats/test/bootstrapTests/supports.js +++ b/packages/vats/test/bootstrapTests/supports.js @@ -284,7 +284,7 @@ export const makeSwingsetTestKit = async (t, specifier) => { bridgeOutbound, kernelStorage, configPath, - [], + {}, {}, { debugName: 'TESTBOOT' }, ); diff --git a/packages/vats/test/bootstrapTests/test-solo-dev.js b/packages/vats/test/bootstrapTests/test-solo-dev.js index be332281efc..c70b9ec5683 100644 --- a/packages/vats/test/bootstrapTests/test-solo-dev.js +++ b/packages/vats/test/bootstrapTests/test-solo-dev.js @@ -24,12 +24,29 @@ test.before(async t => (t.context = await makeDefaultTestContext(t))); // But on the JS side, aside from vattp, prod config exposes mailbox access // just as much as dev, so we can't test that here. +const makeHomeFor = async (addr, EV) => { + const clientCreator = await EV.vat('bootstrap').consumeItem('clientCreator'); + const clientFacet = await EV(clientCreator).createClientFacet( + 'user1', + addr, + PowerFlags.REMOTE_WALLET, + ); + return EV(clientFacet).getChainBundle(); +}; + test('sim/demo config provides home with .myAddressNameAdmin', async t => { - const devToolKeys = ['behaviors', 'chainTimerService', 'faucet']; + const devToolKeys = [ + 'behaviors', + 'chainTimerService', + 'faucet', + 'priceAuthorityAdminFacet', + 'vaultFactoryCreatorFacet', + ]; // TODO: cross-check these with docs and/or deploy-script-support const homeKeys = [ 'agoricNames', + 'attMaker', 'bank', 'board', 'ibcport', @@ -43,15 +60,38 @@ test('sim/demo config provides home with .myAddressNameAdmin', async t => { const { EV } = t.context.runUtils; await t.notThrowsAsync(EV.vat('bootstrap').consumeItem('provisioning')); t.log('bootstrap produced provisioning vat'); - const clientCreator = await EV.vat('bootstrap').consumeItem('clientCreator'); const addr = 'agoric123'; - const clientFacet = await EV(clientCreator).createClientFacet( - 'user1', - addr, - PowerFlags.REMOTE_WALLET, - ); - const home = await EV(clientFacet).getChainBundle(); + const home = await makeHomeFor(addr, EV); const actual = await EV(home.myAddressNameAdmin).getMyAddress(); t.is(actual, addr, 'my address'); t.deepEqual(keys(home).sort(), homeKeys); }); + +test('sim/demo config launches Vaults as expected by loadgen', async t => { + const { EV } = t.context.runUtils; + const agoricNames = await EV.vat('bootstrap').consumeItem('agoricNames'); + const vaultsInstance = await EV(agoricNames).lookup( + 'instance', + 'VaultFactory', + ); + t.truthy(vaultsInstance); +}); + +/** + * decentral-demo-config.json now uses boot-sim.js, + * which includes connectFaucet, which re-introduced USDC. + * That triggered a compatibility path in the loadgen that + * caused it to try and fail to run the vaults task. + * work-around: rename USDC to DAI in connectFaucet. + * + * TODO: move connectFaucet to a coreProposal and + * separate decentral-demo-config.json into separate + * configurations for sim-chain, loadgen. + */ +test('demo config meets loadgen constraint: no USDC', async t => { + const { EV } = t.context.runUtils; + const home = await makeHomeFor('addr123', EV); + const pmtInfo = await EV(home.faucet).tapFaucet(); + const found = pmtInfo.find(p => p.issuerPetname === 'USDC'); + t.deepEqual(found, undefined); +}); diff --git a/packages/vats/test/test-clientBundle.js b/packages/vats/test/test-clientBundle.js index bf7b74feb39..8f0d83aa718 100644 --- a/packages/vats/test/test-clientBundle.js +++ b/packages/vats/test/test-clientBundle.js @@ -155,6 +155,6 @@ test('connectFaucet produces payments', async t => { ); t.deepEqual(detail, [ ['Oracle fee', '51 LINK'], - ['USD Coin', '1_323 USDC'], + ['DAI', '1_323 DAI'], ]); }); diff --git a/packages/vats/test/test-demoAMM.js b/packages/vats/test/test-demoAMM.js index f2b6f5c7d26..a798e5dc843 100644 --- a/packages/vats/test/test-demoAMM.js +++ b/packages/vats/test/test-demoAMM.js @@ -43,7 +43,7 @@ test('splitAllCentralPayments: count entries, spot check', async t => { // t.log(actual); t.is(actual.ATOM.amount.brand, central.brand); t.deepEqual(showAmount(actual.ATOM.amount), '33_280_000 IST'); - t.deepEqual(Object.keys(actual), ['BLD', 'ATOM', 'WETH', 'LINK', 'USDC']); + t.deepEqual(Object.keys(actual), ['BLD', 'ATOM', 'WETH', 'LINK', 'DAI']); }); test('poolRates: spot check WETH', t => { From 4b9b7c3577d6e4f329884a864b623c741eedcbc5 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 11 Mar 2023 13:58:56 -0600 Subject: [PATCH 31/38] chore(vats): clean up BootstrapManifest typing --- packages/vats/src/core/basic-behaviors.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/vats/src/core/basic-behaviors.js b/packages/vats/src/core/basic-behaviors.js index b035dd7d9d6..82b2051b52c 100644 --- a/packages/vats/src/core/basic-behaviors.js +++ b/packages/vats/src/core/basic-behaviors.js @@ -438,8 +438,7 @@ export const addBankAssets = async ({ harden(addBankAssets); /** @type {import('./lib-boot').BootstrapManifest} */ -export const BASIC_BOOTSTRAP_PERMITS = harden({ - /** @type {import('./lib-boot').BootstrapManifestPermit} */ +export const BASIC_BOOTSTRAP_PERMITS = { bridgeCoreEval: true, // Needs all the powers. [makeOracleBrands.name]: { oracleBrand: { @@ -558,4 +557,5 @@ export const BASIC_BOOTSTRAP_PERMITS = harden({ issuer: { produce: { BLD: 'BLD', IST: 'zoe' } }, brand: { produce: { BLD: 'BLD', IST: 'zoe' } }, }, -}); +}; +harden(BASIC_BOOTSTRAP_PERMITS); From 0d352cfe2c6340b89542d84c6d946f1dacd18e7c Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Mon, 13 Mar 2023 15:14:00 -0500 Subject: [PATCH 32/38] chore(vats): reorg to avoid exporting non-behaviors - move makeMyAddressNameAdminKit to utils - bonus: avoids importing all of basic-behaviors into places such as provisionPool.js - move PowerFlags to walletFlags.js - avoid redundant imports in boot-chain.js, -sim, -client --- packages/smart-wallet/src/walletFactory.js | 2 +- packages/vats/src/core/basic-behaviors.js | 34 ++----------------- packages/vats/src/core/boot-chain.js | 14 +++----- packages/vats/src/core/boot-sim.js | 22 +++++------- packages/vats/src/core/boot-solo.js | 16 +++------ packages/vats/src/core/chain-behaviors.js | 3 +- packages/vats/src/core/utils.js | 21 +++++++++++- packages/vats/src/provisionPool.js | 2 +- packages/vats/src/walletFlags.js | 12 +++++++ .../vats/test/bootstrapTests/test-solo-dev.js | 2 +- packages/vats/test/test-provisionPool.js | 2 +- 11 files changed, 56 insertions(+), 74 deletions(-) create mode 100644 packages/vats/src/walletFlags.js diff --git a/packages/smart-wallet/src/walletFactory.js b/packages/smart-wallet/src/walletFactory.js index ea2b6197ae7..7e5edcb0778 100644 --- a/packages/smart-wallet/src/walletFactory.js +++ b/packages/smart-wallet/src/walletFactory.js @@ -9,7 +9,7 @@ import { observeIteration } from '@agoric/notifier'; import { M, makeExo, makeScalarMapStore, mustMatch } from '@agoric/store'; import { makeAtomicProvider } from '@agoric/store/src/stores/store-utils.js'; import { prepareExo, provideDurableMapStore } from '@agoric/vat-data'; -import { makeMyAddressNameAdminKit } from '@agoric/vats/src/core/basic-behaviors.js'; +import { makeMyAddressNameAdminKit } from '@agoric/vats/src/core/utils.js'; import { provideAll } from '@agoric/zoe/src/contractSupport/durability.js'; import { E } from '@endo/far'; import { prepareSmartWallet } from './smartWallet.js'; diff --git a/packages/vats/src/core/basic-behaviors.js b/packages/vats/src/core/basic-behaviors.js index 82b2051b52c..2b27c2592fb 100644 --- a/packages/vats/src/core/basic-behaviors.js +++ b/packages/vats/src/core/basic-behaviors.js @@ -7,24 +7,12 @@ import { makeScalarMapStore } from '@agoric/store'; import { provideLazy } from '@agoric/store/src/stores/store-utils.js'; import { BridgeId, VBankAccount, WalletName } from '@agoric/internal'; import { makeNameHubKit } from '../nameHub.js'; -import { feeIssuerConfig } from './utils.js'; +import { feeIssuerConfig, makeMyAddressNameAdminKit } from './utils.js'; import { Stable, Stake } from '../tokens.js'; +import { PowerFlags } from '../walletFlags.js'; const { details: X } = assert; -// XXX domain of @agoric/cosmic-proto -/** - * non-exhaustive list of powerFlags - * REMOTE_WALLET is currently a default. - * - * See also MsgProvision in golang/cosmos/proto/agoric/swingset/msgs.proto - */ -export const PowerFlags = /** @type {const} */ ({ - SMART_WALLET: 'SMART_WALLET', - /** The ag-solo wallet is remote. */ - REMOTE_WALLET: 'REMOTE_WALLET', -}); - /** * In golang/cosmos/app/app.go, we define * cosmosInitAction with type AG_COSMOS_INIT, @@ -189,24 +177,6 @@ export const makeBoard = async ({ }; harden(makeBoard); -/** - * @param {string} address - */ -export const makeMyAddressNameAdminKit = address => { - // Create a name hub for this address. - const { nameHub, nameAdmin: rawMyAddressNameAdmin } = makeNameHubKit(); - - /** @type {import('../types').MyAddressNameAdmin} */ - const myAddressNameAdmin = Far('myAddressNameAdmin', { - ...rawMyAddressNameAdmin, - getMyAddress: () => address, - }); - // reserve space for deposit facet - myAddressNameAdmin.reserve(WalletName.depositFacet); - - return { nameHub, myAddressNameAdmin }; -}; - /** * Make the agoricNames, namesByAddress name hierarchies. * diff --git a/packages/vats/src/core/boot-chain.js b/packages/vats/src/core/boot-chain.js index 635aab47634..f0d55bb5b8d 100644 --- a/packages/vats/src/core/boot-chain.js +++ b/packages/vats/src/core/boot-chain.js @@ -2,20 +2,12 @@ import { makeBootstrap } from './lib-boot.js'; import * as basicBehaviorsPlus from './basic-behaviors.js'; -import { CHAIN_BOOTSTRAP_MANIFEST } from './chain-behaviors.js'; import * as chainBehaviorsPlus from './chain-behaviors.js'; import * as utils from './utils.js'; -export const MANIFEST = CHAIN_BOOTSTRAP_MANIFEST; - -const { - BASIC_BOOTSTRAP_PERMITS: _b, - PowerFlags: _p, - makeMyAddressNameAdminKit: _m, - ...basicBehaviors -} = basicBehaviorsPlus; +const { BASIC_BOOTSTRAP_PERMITS: _b, ...basicBehaviors } = basicBehaviorsPlus; const { - CHAIN_BOOTSTRAP_MANIFEST: _c, + CHAIN_BOOTSTRAP_MANIFEST, SHARED_CHAIN_BOOTSTRAP_MANIFEST: _s, ...chainBehaviors } = chainBehaviorsPlus; @@ -26,6 +18,8 @@ const modules = { utils: { ...utils }, }; +export const MANIFEST = CHAIN_BOOTSTRAP_MANIFEST; + /** * Build root object of the bootstrap vat. * diff --git a/packages/vats/src/core/boot-sim.js b/packages/vats/src/core/boot-sim.js index d7bf5d06ce4..d282912b482 100644 --- a/packages/vats/src/core/boot-sim.js +++ b/packages/vats/src/core/boot-sim.js @@ -2,29 +2,23 @@ import { makeBootstrap } from './lib-boot.js'; import * as basicBehaviorsPlus from './basic-behaviors.js'; -import { SHARED_CHAIN_BOOTSTRAP_MANIFEST } from './chain-behaviors.js'; -import { SIM_CHAIN_BOOTSTRAP_PERMITS } from './sim-behaviors.js'; import * as chainBehaviorsPlus from './chain-behaviors.js'; import * as simBehaviorsPlus from './sim-behaviors.js'; import * as utils from './utils.js'; +const { BASIC_BOOTSTRAP_PERMITS: _b, ...basicBehaviors } = basicBehaviorsPlus; +const { + CHAIN_BOOTSTRAP_MANIFEST: _c, + SHARED_CHAIN_BOOTSTRAP_MANIFEST, + ...chainBehaviors +} = chainBehaviorsPlus; +const { SIM_CHAIN_BOOTSTRAP_PERMITS, ...simBehaviors } = simBehaviorsPlus; + export const MANIFEST = { ...SHARED_CHAIN_BOOTSTRAP_MANIFEST, ...SIM_CHAIN_BOOTSTRAP_PERMITS, }; -const { - BASIC_BOOTSTRAP_PERMITS: _b, - PowerFlags: _p, - makeMyAddressNameAdminKit: _m, - ...basicBehaviors -} = basicBehaviorsPlus; -const { - CHAIN_BOOTSTRAP_MANIFEST: _c, - SHARED_CHAIN_BOOTSTRAP_MANIFEST: _s, - ...chainBehaviors -} = chainBehaviorsPlus; -const { SIM_CHAIN_BOOTSTRAP_PERMITS: _sc, ...simBehaviors } = simBehaviorsPlus; const behaviors = { ...basicBehaviors, ...chainBehaviors, ...simBehaviors }; const modules = harden({ behaviors: { ...behaviors }, utils: { ...utils } }); diff --git a/packages/vats/src/core/boot-solo.js b/packages/vats/src/core/boot-solo.js index eefe7897784..47d0ad02ba6 100644 --- a/packages/vats/src/core/boot-solo.js +++ b/packages/vats/src/core/boot-solo.js @@ -3,32 +3,24 @@ import { makeBootstrap } from './lib-boot.js'; import * as basicBehaviorsPlus from './basic-behaviors.js'; import * as chainBehaviorsPlus from './chain-behaviors.js'; -import { CLIENT_BOOTSTRAP_MANIFEST } from './client-behaviors.js'; import * as clientBehaviorsPlus from './client-behaviors.js'; import * as utils from './utils.js'; -export const MANIFEST = CLIENT_BOOTSTRAP_MANIFEST; - -// XXX export basicBehaviors record from basic-behaviors.js? -const { - BASIC_BOOTSTRAP_PERMITS: _b, - PowerFlags: _p, - makeMyAddressNameAdminKit: _m, - ...basicBehaviors -} = basicBehaviorsPlus; +const { BASIC_BOOTSTRAP_PERMITS: _b, ...basicBehaviors } = basicBehaviorsPlus; const { CHAIN_BOOTSTRAP_MANIFEST: _c, SHARED_CHAIN_BOOTSTRAP_MANIFEST: _s, ...chainBehaviors } = chainBehaviorsPlus; -const { CLIENT_BOOTSTRAP_MANIFEST: _cb, ...clientBehaviors } = - clientBehaviorsPlus; +const { CLIENT_BOOTSTRAP_MANIFEST, ...clientBehaviors } = clientBehaviorsPlus; const behaviors = harden({ ...basicBehaviors, ...chainBehaviors, ...clientBehaviors, }); +export const MANIFEST = CLIENT_BOOTSTRAP_MANIFEST; + const modules = harden({ clientBehaviors: { ...clientBehaviors }, behaviors: { ...behaviors }, diff --git a/packages/vats/src/core/chain-behaviors.js b/packages/vats/src/core/chain-behaviors.js index a5b07735bf6..c3ecadff0b0 100644 --- a/packages/vats/src/core/chain-behaviors.js +++ b/packages/vats/src/core/chain-behaviors.js @@ -19,7 +19,8 @@ import { allValues, BridgeId as BRIDGE_ID } from '@agoric/internal'; import * as STORAGE_PATH from '@agoric/internal/src/chain-storage-paths.js'; import { agoricNamesReserved, callProperties, extractPowers } from './utils.js'; -import { PowerFlags, BASIC_BOOTSTRAP_PERMITS } from './basic-behaviors.js'; +import { BASIC_BOOTSTRAP_PERMITS } from './basic-behaviors.js'; +import { PowerFlags } from '../walletFlags.js'; const { Fail } = assert; const { keys } = Object; diff --git a/packages/vats/src/core/utils.js b/packages/vats/src/core/utils.js index 369c2e15a9c..40122399877 100644 --- a/packages/vats/src/core/utils.js +++ b/packages/vats/src/core/utils.js @@ -1,6 +1,7 @@ // @ts-check -import { E } from '@endo/far'; +import { E, Far } from '@endo/far'; import { assertPassable } from '@endo/marshal'; +import { WalletName } from '@agoric/internal'; import { makeNameHubKit } from '../nameHub.js'; import { Stable, Stake } from '../tokens.js'; import { makePromiseSpace } from './promise-space.js'; @@ -256,3 +257,21 @@ export const makeAgoricNamesAccess = ( spaces: typedSpaces, }; }; + +/** + * @param {string} address + */ +export const makeMyAddressNameAdminKit = address => { + // Create a name hub for this address. + const { nameHub, nameAdmin: rawMyAddressNameAdmin } = makeNameHubKit(); + + /** @type {import('../types').MyAddressNameAdmin} */ + const myAddressNameAdmin = Far('myAddressNameAdmin', { + ...rawMyAddressNameAdmin, + getMyAddress: () => address, + }); + // reserve space for deposit facet + myAddressNameAdmin.reserve(WalletName.depositFacet); + + return { nameHub, myAddressNameAdmin }; +}; diff --git a/packages/vats/src/provisionPool.js b/packages/vats/src/provisionPool.js index 11ebf601e19..38593f8ad8f 100644 --- a/packages/vats/src/provisionPool.js +++ b/packages/vats/src/provisionPool.js @@ -8,7 +8,7 @@ import { observeIteration, observeNotifier } from '@agoric/notifier'; import { AmountMath } from '@agoric/ertp'; import { handleParamGovernance, ParamTypes } from '@agoric/governance'; import { makeMetricsPublishKit } from '@agoric/inter-protocol/src/contractSupport.js'; -import { PowerFlags } from './core/basic-behaviors.js'; +import { PowerFlags } from './walletFlags.js'; const { details: X, quote: q } = assert; diff --git a/packages/vats/src/walletFlags.js b/packages/vats/src/walletFlags.js new file mode 100644 index 00000000000..85bbed360da --- /dev/null +++ b/packages/vats/src/walletFlags.js @@ -0,0 +1,12 @@ +// XXX domain of @agoric/cosmic-proto +/** + * non-exhaustive list of powerFlags + * REMOTE_WALLET is currently a default. + * + * See also MsgProvision in golang/cosmos/proto/agoric/swingset/msgs.proto + */ +export const PowerFlags = /** @type {const} */ ({ + SMART_WALLET: 'SMART_WALLET', + /** The ag-solo wallet is remote. */ + REMOTE_WALLET: 'REMOTE_WALLET', +}); diff --git a/packages/vats/test/bootstrapTests/test-solo-dev.js b/packages/vats/test/bootstrapTests/test-solo-dev.js index c70b9ec5683..3a900a75230 100644 --- a/packages/vats/test/bootstrapTests/test-solo-dev.js +++ b/packages/vats/test/bootstrapTests/test-solo-dev.js @@ -1,6 +1,6 @@ // @ts-check import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js'; -import { PowerFlags } from '../../src/core/basic-behaviors.js'; +import { PowerFlags } from '../../src/walletFlags.js'; import { makeSwingsetTestKit } from './supports.js'; diff --git a/packages/vats/test/test-provisionPool.js b/packages/vats/test/test-provisionPool.js index 38744f79a6f..19c43c2965d 100644 --- a/packages/vats/test/test-provisionPool.js +++ b/packages/vats/test/test-provisionPool.js @@ -17,7 +17,7 @@ import { eventLoopIteration } from '@agoric/zoe/tools/eventLoopIteration.js'; import { E } from '@endo/far'; import path from 'path'; import centralSupplyBundle from '../bundles/bundle-centralSupply.js'; -import { PowerFlags } from '../src/core/basic-behaviors.js'; +import { PowerFlags } from '../src/walletFlags.js'; import { makeBoard } from '../src/lib-board.js'; import { makeNameHubKit } from '../src/nameHub.js'; import { makeBridgeProvisionTool } from '../src/provisionPool.js'; From 1f42034ace0d6be60f344649f7418f4a597f7d3e Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Mon, 13 Mar 2023 15:20:32 -0500 Subject: [PATCH 33/38] test(vats): rename test-solo-dev -> test-demo-config --- .../test/bootstrapTests/{test-solo-dev.js => test-demo-config.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/vats/test/bootstrapTests/{test-solo-dev.js => test-demo-config.js} (100%) diff --git a/packages/vats/test/bootstrapTests/test-solo-dev.js b/packages/vats/test/bootstrapTests/test-demo-config.js similarity index 100% rename from packages/vats/test/bootstrapTests/test-solo-dev.js rename to packages/vats/test/bootstrapTests/test-demo-config.js From 84e0608e743f6255ef8905871e4644b771066d53 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Mon, 13 Mar 2023 15:21:52 -0500 Subject: [PATCH 34/38] fixup! chore: move sim stuff out of inter-protocol --- packages/vats/src/core/sim-behaviors.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/vats/src/core/sim-behaviors.js b/packages/vats/src/core/sim-behaviors.js index 3711baab4e7..bfafac62be6 100644 --- a/packages/vats/src/core/sim-behaviors.js +++ b/packages/vats/src/core/sim-behaviors.js @@ -39,9 +39,8 @@ export const grantRunBehaviors = async ({ }; harden(grantRunBehaviors); -/** @type {import('@agoric/vats/src/core/lib-boot').BootstrapManifest} */ -export const SIM_CHAIN_BOOTSTRAP_PERMITS = harden({ - /** @type {import('@agoric/vats/src/core/lib-boot').BootstrapManifestPermit} */ +/** @type {import('./lib-boot').BootstrapManifest} */ +export const SIM_CHAIN_BOOTSTRAP_PERMITS = { [installSimEgress.name]: { vatParameters: { argv: { hardcodedClientAddresses: true } }, vats: { @@ -70,4 +69,5 @@ export const SIM_CHAIN_BOOTSTRAP_PERMITS = harden({ consume: { client: true }, home: { produce: { runBehaviors: true, governanceActions: true } }, }, -}); +}; +harden(SIM_CHAIN_BOOTSTRAP_PERMITS); From a36df1e5dd141d2f138f4d82c04974d7084e6879 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Mon, 13 Mar 2023 15:23:33 -0500 Subject: [PATCH 35/38] fixup! test(vats): stub test for bootstrap upgrade --- packages/vats/test/upgrading/test-upgrade-vats.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vats/test/upgrading/test-upgrade-vats.js b/packages/vats/test/upgrading/test-upgrade-vats.js index 77c5a905313..5137732aef9 100644 --- a/packages/vats/test/upgrading/test-upgrade-vats.js +++ b/packages/vats/test/upgrading/test-upgrade-vats.js @@ -34,7 +34,7 @@ const makeScenario = async (t, bundles) => { /** @type {SwingSetConfig} */ const config = { includeDevDependencies: true, // for vat-data - defaultManagerType: 'local', // better debugging + defaultManagerType: 'xs-worker', bootstrap: 'bootstrap', defaultReapInterval: 'never', vats: { From 879b8cbf71b184d30181b4a0e35e36f40d65b606 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Mon, 13 Mar 2023 15:24:57 -0500 Subject: [PATCH 36/38] fixup! chore(vats): restore authorityViz.js to working order --- packages/vats/tools/viz.mk | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 packages/vats/tools/viz.mk diff --git a/packages/vats/tools/viz.mk b/packages/vats/tools/viz.mk new file mode 100644 index 00000000000..69396a48c58 --- /dev/null +++ b/packages/vats/tools/viz.mk @@ -0,0 +1,17 @@ +# config: tools outsidet the source tree +VIEWER=firefox +DOT=dot + +CONFIG=decentral-test-vaults-config + +SRC=../src/core/chain-behaviors.js ../src/core/basic-behaviors.js + +$(CONFIG).svg: $(CONFIG).dot + $(DOT) -Tsvg $< >$@ || rm $@ + +view: $(CONFIG).svg + $(VIEWER) $< + +$(CONFIG).dot: ../$(CONFIG).json $(SRC) authorityViz.js + node authorityViz.js ../$(CONFIG).json >$@ || rm $@ + From f2dbe66897cdfa351d5222a391e9a000ee3eaec8 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Mon, 13 Mar 2023 15:27:53 -0500 Subject: [PATCH 37/38] fixup! docs(vats): document purpose etc. of config files --- packages/vats/decentral-demo-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vats/decentral-demo-config.json b/packages/vats/decentral-demo-config.json index d2730fbfd86..dcdc4a3c8ca 100644 --- a/packages/vats/decentral-demo-config.json +++ b/packages/vats/decentral-demo-config.json @@ -1,5 +1,5 @@ { - "$comment": "This SwingSet config file (see loadSwingsetConfigFile) includes non-production facilities such as a faucet. It is used by the sim chain (agoric start dev) and testnet-load-generator (aka loadgen). TODO: restore vaults proposal", + "$comment": "This SwingSet config file (see loadSwingsetConfigFile) includes non-production facilities such as a faucet. It is used by the sim chain (agoric start dev) and testnet-load-generator (aka loadgen).", "bootstrap": "bootstrap", "defaultReapInterval": 1000, "snapshotInterval": 1000, From 478dc43cada6c374a137260ba8d65d368b0f2b4c Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Mon, 13 Mar 2023 23:02:02 -0500 Subject: [PATCH 38/38] chore(vats): fewer PSMs to speed up loadgen ci --- packages/vats/decentral-demo-config.json | 42 ------------------------ 1 file changed, 42 deletions(-) diff --git a/packages/vats/decentral-demo-config.json b/packages/vats/decentral-demo-config.json index dcdc4a3c8ca..ddd19622a8f 100644 --- a/packages/vats/decentral-demo-config.json +++ b/packages/vats/decentral-demo-config.json @@ -51,48 +51,6 @@ } ] }, - { - "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", - "entrypoint": "psmProposalBuilder", - "args": [ - { - "anchorOptions": { - "denom": "ibc/usdc5678", - "decimalPlaces": 6, - "keyword": "USDC_grv", - "proposedName": "USC Coin" - } - } - ] - }, - { - "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", - "entrypoint": "psmProposalBuilder", - "args": [ - { - "anchorOptions": { - "denom": "ibc/usdt1234", - "decimalPlaces": 6, - "keyword": "USDT_axl", - "proposedName": "Tether USD" - } - } - ] - }, - { - "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", - "entrypoint": "psmProposalBuilder", - "args": [ - { - "anchorOptions": { - "denom": "ibc/toyollie", - "decimalPlaces": 6, - "keyword": "USDT_grv", - "proposedName": "Tether USD" - } - } - ] - }, { "module": "@agoric/inter-protocol/scripts/add-collateral-core.js", "entrypoint": "psmProposalBuilder",