Skip to content

Commit

Permalink
test(bootstrap): restart all contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
turadg committed May 11, 2023
1 parent e2b3e34 commit e0a2711
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 16 deletions.
8 changes: 7 additions & 1 deletion packages/inter-protocol/src/price/fluxAggregatorContract.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,13 @@ export const prepare = async (zcf, privateArgs, baggage) => {
namesByAddressAdmin,
storageNode,
} = privateArgs;
assertAllDefined({ initialPoserInvitation, marshaller, storageNode });
// XXX omit initialPoserInvitation to simplify testing of restart
assertAllDefined({
highPrioritySendersManager,
marshaller,
namesByAddressAdmin,
storageNode,
});

const { description, timer } = zcf.getTerms();

Expand Down
1 change: 1 addition & 0 deletions packages/inter-protocol/src/proposals/core-proposal.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ const SHARED_MAIN_MANIFEST = harden({
consume: {
board: 'board',
chainStorage: true,
diagnostics: true,
feeMintAccess: 'zoe',
chainTimerService: 'timer',
zoe: 'zoe',
Expand Down
25 changes: 16 additions & 9 deletions packages/inter-protocol/src/proposals/econ-behaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export const setupReserve = async ({
feeMintAccess: feeMintAccessP,
chainStorage,
chainTimerService,
diagnostics,
zoe,
economicCommitteeCreatorFacet: committeeCreator,
},
Expand Down Expand Up @@ -120,19 +121,20 @@ export const setupReserve = async ({
},
}),
);
const privateArgs = {
governed: {
feeMintAccess,
initialPoserInvitation: poserInvitation,
marshaller,
storageNode,
},
};
/** @type {GovernorStartedInstallationKit<typeof reserveInstallation>} */
const g = await E(zoe).startInstance(
governorInstallation,
{},
reserveGovernorTerms,
{
governed: {
feeMintAccess,
initialPoserInvitation: poserInvitation,
marshaller,
storageNode,
},
},
privateArgs,
'reserve.governor',
);

Expand All @@ -155,6 +157,9 @@ export const setupReserve = async ({
governorAdminFacet: g.adminFacet,
}),
);
const { instancePrivateArgs } = await diagnostics;
instancePrivateArgs.set(instance, privateArgs.governed);
instancePrivateArgs.set(g.instance, privateArgs);

reserveInstanceProducer.resolve(instance);
reserveGovernor.resolve(g.instance);
Expand Down Expand Up @@ -459,7 +464,9 @@ export const startRewardDistributor = async ({
),
});

feeDistributorKit.resolve(instanceKit);
feeDistributorKit.resolve(
harden({ ...instanceKit, label: 'feeDistributor' }),
);
feeDistributorP.resolve(instanceKit.instance);

// Initialize the periodic collectors list if we don't have one.
Expand Down
20 changes: 14 additions & 6 deletions packages/inter-protocol/src/proposals/startEconCommittee.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const sanitizePathSegment = name => {
*/
export const startEconomicCommittee = async (
{
consume: { board, chainStorage, zoe },
consume: { board, chainStorage, diagnostics, zoe },
produce: { economicCommitteeKit, economicCommitteeCreatorFacet },
installation: {
consume: { committee },
Expand Down Expand Up @@ -59,19 +59,26 @@ export const startEconomicCommittee = async (
// NB: committee must only publish what it intended to be public
const marshaller = await E(board).getPublishingMarshaller();

const privateArgs = {
storageNode,
marshaller,
};
const startResult = await E(zoe).startInstance(
committee,
{},
{ committeeName, committeeSize, ...rest },
{
storageNode,
marshaller,
},
privateArgs,
'economicCommittee',
);
const { creatorFacet, instance } = startResult;

economicCommitteeKit.resolve(startResult);
economicCommitteeKit.resolve(
// XXX should startInstance return its label?
harden({ ...startResult, label: 'economicCommittee' }),
);
const { instancePrivateArgs } = await diagnostics;
instancePrivateArgs.set(startResult.instance, privateArgs);

economicCommitteeCreatorFacet.resolve(creatorFacet);
economicCommittee.resolve(instance);
};
Expand All @@ -82,6 +89,7 @@ export const ECON_COMMITTEE_MANIFEST = harden({
consume: {
board: true,
chainStorage: true,
diagnostics: true,
zoe: true,
},
produce: {
Expand Down
1 change: 1 addition & 0 deletions packages/inter-protocol/src/proposals/startPSM.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ export const startPSM = async (
/** @type {MapStore<Brand,psmKit>} */
const psmKitMap = await psmKit;

// TODO init into governedContractKits too to simplify testing
psmKitMap.init(anchorBrand, newpsmKit);
const instanceAdmin = E(agoricNamesAdmin).lookupAdmin('instance');

Expand Down
9 changes: 9 additions & 0 deletions packages/vats/decentral-test-vaults-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,15 @@
}
}
]
},
{
"module": "@agoric/vats/scripts/restart-vats.js",
"entrypoint": "defaultProposalBuilder",
"args": [
{
"skip": {}
}
]
}
],
"vats": {
Expand Down
15 changes: 15 additions & 0 deletions packages/vats/scripts/restart-vats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { makeHelpers } from '@agoric/deploy-script-support';

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').ProposalBuilder} */
export const defaultProposalBuilder = async () => {
const skip = [];
return harden({
sourceSpec: '../src/proposals/restart-vats-proposal.js',
getManifestCall: ['getManifestForRestart', { skip }],
});
};

export default async (homeP, endowments) => {
const { writeCoreProposal } = await makeHelpers(homeP, endowments);
await writeCoreProposal('restart-vats', defaultProposalBuilder);
};
138 changes: 138 additions & 0 deletions packages/vats/src/proposals/restart-vats-proposal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/* eslint-disable no-await-in-loop */
// @ts-check

import { Fail } from '@agoric/assert';
import { deeplyFulfilledObject, makeTracer } from '@agoric/internal';
import { E, getInterfaceOf } from '@endo/far';

const trace = makeTracer('RV');

const HR = '----------------';

// FIXME a skip for each
// A YESlist isn't necessary because the collections are known to be complete (tested in test-vaults-upgrade.js)
const SKIP = [
// can be replaced instead of upgraded
'auctioneer',
'feeDistributor',
// below are failing, burn these down
];

// FIXME cover each of these collections
// contractKits, psmKit, governedContractKits, vatStore

// TODO get the privateArgs from the space
// a simple JS Map keyed by Instance like the contractKits are (for join)

/**
* @param {BootstrapPowers & import('@agoric/inter-protocol/src/proposals/econ-behaviors.js').EconomyBootstrapSpace} space
* @param {{ skip: Array<unknown>}} opts
*/
export const restartVats = async ({ consume }, opts) => {
console.log(HR);
console.log(HR);
trace('restartVats start', opts);

trace('awaiting VaultFactorKit as a proxy for "bootstrap done"');
await consume.vaultFactoryKit;

trace('testing restarts');
const { contractKits, governedContractKits } = await deeplyFulfilledObject(
harden({
contractKits: consume.contractKits,
governedContractKits: consume.governedContractKits,
}),
);

const { instancePrivateArgs } = await consume.diagnostics;

// TODO prepare appropriate privateArgs (potentially by saving with startUpgradable)

const failures = [];
/**
*
* @param {string} debugName
* @param {Instance} instance
* @param {ERef<AdminFacet>} adminFacet
*/
const tryRestart = async (debugName, instance, adminFacet) => {
// TODO document that privateArgs cannot contain promises
// TODO try making all the contract starts take resolved values
const privateArgs = await deeplyFulfilledObject(
// @ts-expect-error cast
harden(instancePrivateArgs.get(instance) || {}),
);

console.log(HR);
console.log(HR);
console.log(HR);
console.log(HR);
trace('tryRestart', debugName, privateArgs);

if (SKIP.includes(debugName)) {
trace('SKIPPED', debugName);
return;
}
try {
await E(adminFacet).restartContract(privateArgs);
trace('RESTARTED', debugName);
} catch (err) {
trace('🚨 RESTART FAILED', debugName, err);
failures.push(debugName);
}
};

// iterate over the two contractKits and use the adminFacet to restartContract
for (const kit of contractKits.values()) {
const debugName =
kit.label || getInterfaceOf(kit.publicFacet) || 'UNLABELED';
if (debugName !== kit.label) {
console.warn('MISSING LABEL:', kit);
}
await tryRestart(debugName, kit.instance, kit.adminFacet);
}

for (const kit of governedContractKits.values()) {
const debugName =
kit.label || getInterfaceOf(kit.publicFacet) || 'UNLABELED';
if (debugName !== kit.label) {
console.warn('MISSING LABEL:', kit);
}

trace('restarting governed', debugName);
await tryRestart(debugName, kit.instance, kit.adminFacet);

trace('restarting governor of', debugName);
await tryRestart(
`${debugName} [Governor]`,
kit.governor,
kit.governorAdminFacet,
);
}

trace('restartVats done with ', failures.length, 'failures');
console.log(HR);
if (failures.length) {
Fail`restart failed for ${failures.join(',')}`;
}
console.log(HR);
};
harden(restartVats);

export const getManifestForRestart = _powers => ({
manifest: {
[restartVats.name]: {
consume: {
contractKits: true,
diagnostics: true,
governedContractKits: true,
loadCriticalVat: true,
zoe: 'zoe',
provisioning: 'provisioning',
vaultFactoryKit: true,
},
produce: {},
},
},
});
harden(getManifestForRestart);
23 changes: 23 additions & 0 deletions packages/vats/test/bootstrapTests/test-vats-restart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// @ts-check
/**
* @file Bootstrap test of restarting (almost) all vats
*/
import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js';

/**
* @type {import('ava').TestFn<Awaited<ReturnType<typeof makeDefaultTestContext>>>}
*/
const test = anyTest;

const makeDefaultTestContext = t => {
t.log('TODO');
};

test.before(async t => {
t.context = await makeDefaultTestContext(t);
});

// TODO add an ability to bootstrap tests to execute a proposal
// Until then, the proposal is part of decentral-test-vaults-config.json so it's being
// run with every bootstrapTest
test.todo('restart-vats proposal');
1 change: 1 addition & 0 deletions packages/vats/test/bootstrapTests/test-vaults-upgrade.js
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ test.serial(
EV.vat('bootstrap').snapshotStore(await EV(powerStore).get(name));

const contractKits = await getStoreSnapshot('contractKits');
// TODO refactor the entries to go into governedContractKits too (so the latter is sufficient to test)
const psmKit = await getStoreSnapshot('psmKit');
const governedContractKits = await getStoreSnapshot('governedContractKits');
const vatStore = await getStoreSnapshot('vatStore');
Expand Down

0 comments on commit e0a2711

Please sign in to comment.