Skip to content

Commit

Permalink
test: Verify that new APIs are recognized on upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris-Hibbert committed Jan 15, 2025
1 parent 1dc3e9a commit 0edc4ac
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ test.serial('EC can govern reserve parameter', async t => {
const { reserve } = agoricNamesRemotes.instance;
const { IST } = agoricNamesRemotes.brand;

t.log('Proposing question using new charter invitation for reserve');
t.log('Proposing question using new charter invitation for reserve', reserve);
await governanceDriver.proposeApiCall(
reserve,
'burnFeesToReduceShortfall',
Expand Down
170 changes: 149 additions & 21 deletions packages/boot/test/bootstrapTests/upgradeAPI.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,28 @@ import path from 'path';
import bundleSource from '@endo/bundle-source';
import { CONTRACT_ELECTORATE, ParamTypes } from '@agoric/governance';
import { MALLEABLE_NUMBER } from '@agoric/governance/test/swingsetTests/contractGovernor/governedContract.js';
import { makeAgoricNamesRemotesFromFakeStorage } from '@agoric/vats/tools/board-utils.js';

import { makeSwingsetTestKit } from '../../tools/supports.js';
import {
makeGovernanceDriver,
makeWalletFactoryDriver,
} from '../../tools/drivers.js';

const dirname = path.dirname(new URL(import.meta.url).pathname);

const GOVERNED_CONTRACT_SRC = './governedContract.js';
const GOVERNED_CONTRACT2_SRC = './governedContract2.js';

const wallets = [
'agoric1gx9uu7y6c90rqruhesae2t7c2vlw4uyyxlqxrx',
'agoric1d4228cvelf8tj65f4h7n2td90sscavln2283h5',
'agoric14543m33dr28x7qhwc558hzlj9szwhzwzpcmw6a',
'agoric13p9adwk0na5npfq64g22l6xucvqdmu3xqe70wq',
'agoric1el6zqs8ggctj5vwyukyk4fh50wcpdpwgugd5l5',
'agoric1zayxg4e9vd0es9c9jlpt36qtth255txjp6a8yc',
];

const setUpGovernedContract = async (zoe, timer, EV, controller) => {
const installBundle = contractBundle => EV(zoe).install(contractBundle);
const installBundleToVatAdmin = contractBundle =>
Expand Down Expand Up @@ -88,7 +103,7 @@ const setUpGovernedContract = async (zoe, timer, EV, controller) => {
};

// A more minimal set would be better. We need governance, but not econ vats.
const PLATFORM_CONFIG = '@agoric/vm-config/decentral-test-vaults-config.json';
const PLATFORM_CONFIG = '@agoric/vm-config/decentral-main-vaults-config.json';

const makeDefaultTestContext = async t => {
console.time('DefaultTestContext');
Expand All @@ -102,9 +117,25 @@ const makeDefaultTestContext = async t => {
const zoe: ZoeService = await EV.vat('bootstrap').consumeItem('zoe');
const timer = await EV.vat('bootstrap').consumeItem('chainTimerService');

// has to be late enough for agoricNames data to have been published
const agoricNamesRemotes = makeAgoricNamesRemotesFromFakeStorage(storage);

const walletFactoryDriver = await makeWalletFactoryDriver(
runUtils,
storage,
agoricNamesRemotes,
);

const governanceDriver = await makeGovernanceDriver(
swingsetTestKit,
agoricNamesRemotes,
walletFactoryDriver,
wallets,
);

const facets = await setUpGovernedContract(zoe, timer, EV, controller);

return { ...swingsetTestKit, facets };
return { ...swingsetTestKit, facets, governanceDriver };
};

const test = anyTest as TestFn<
Expand All @@ -119,7 +150,7 @@ test.after.always(t => {
return t.context.shutdown && t.context.shutdown();
});

test(`start contract; verify`, async t => {
test.serial(`start contract; verify`, async t => {
const { runUtils, facets } = t.context;
const {
governorFacets: { creatorFacet },
Expand All @@ -132,39 +163,95 @@ test(`start contract; verify`, async t => {
t.is(avogadro, 602214090000000000000000n);
});

test(`verify API governance`, async t => {
const { runUtils, facets } = t.context;
const getQuestionId = id => `propose-question-${id}`;
const getVoteId = id => `vote-${id}`;

const offerIds = {
invite: { charter: 'ch', committee: 'ctt' },
add1: { outgoing: 'add1' },
add2: { outgoing: 'add2' },
};

let governedContract;
test.serial(`verify API governance`, async t => {
const { runUtils, facets, governanceDriver, storage, advanceTimeBy } =
t.context;
const {
governorFacets: { creatorFacet },
governorFacets: { creatorFacet, instance },
voteCounterInstallation: vci,
} = facets;

const { EV } = runUtils;
const contractPublicFacet = await EV(creatorFacet).getPublicFacet();

const committee = governanceDriver.ecMembers;

const question = await EV(creatorFacet).voteOnApiInvocation(
const agoricNamesAdmin =
await EV.vat('bootstrap').consumeItem('agoricNamesAdmin');
const instanceAdmin = await EV(agoricNamesAdmin).lookupAdmin('instance');
await EV(instanceAdmin).update('governedContract', instance);
const agoricNamesRemotes = makeAgoricNamesRemotesFromFakeStorage(storage);
({ governedContract } = agoricNamesRemotes.instance);

await null;
for (const member of committee) {
await member.acceptOutstandingCharterInvitation(offerIds.invite.charter);
await member.acceptOutstandingCommitteeInvitation(
offerIds.invite.committee,
);
}
const econCharterKit =
await EV.vat('bootstrap').consumeItem('econCharterKit');

const charterCreatorFacet = await EV.get(econCharterKit).creatorFacet;
await EV(charterCreatorFacet).addInstance(
instance,
creatorFacet,
'governedContract',
);

await governanceDriver.proposeApiCall(
governedContract,
'add1',
[],
vci,
37n,
committee[0],
getQuestionId(1),
offerIds.invite.charter,
);
t.truthy(question.instance);

await t.throwsAsync(
() => EV(creatorFacet).voteOnApiInvocation('add2', [], vci, 37n),
{
message: /"add2" is not a governed API./,
},
t.like(committee[0].getLatestUpdateRecord(), {
status: { id: getQuestionId(1), numWantsSatisfied: 1 },
});

await governanceDriver.enactLatestProposal(
committee,
getVoteId(1),
offerIds.invite.committee,
);

for (const w of committee.slice(0, 2)) {
t.like(w.getLatestUpdateRecord(), {
status: { id: getVoteId(1), numWantsSatisfied: 1 },
});
}
await advanceTimeBy(1, 'minutes');

const lastOutcome = await governanceDriver.getLatestOutcome();
t.is(lastOutcome.outcome, 'win');

const calls = await EV(contractPublicFacet).getApiCalled();
t.is(calls, 1);
});

test(`upgrade; verify enhanced API governance`, async t => {
const { runUtils, facets } = t.context;
test.serial(`upgrade`, async t => {
const { runUtils, facets, governanceDriver, advanceTimeBy } = t.context;
const {
governorFacets: { creatorFacet },
voteCounterInstallation: vci,
contract2SHA,
poserInvitation2,
} = facets;
const committee = governanceDriver.ecMembers;

const { EV } = runUtils;
const af = await EV(creatorFacet).getAdminFacet();
Expand All @@ -173,11 +260,52 @@ test(`upgrade; verify enhanced API governance`, async t => {
initialPoserInvitation: poserInvitation2,
});

const question2 = await EV(creatorFacet).voteOnApiInvocation(
const contractPublicFacet = await EV(creatorFacet).getPublicFacet();
const calls = await EV(contractPublicFacet).getApiCalled();
t.is(calls, 1);
});

test.serial(`verify API governance post-upgrade`, async t => {
const { runUtils, facets, governanceDriver, advanceTimeBy } = t.context;
const {
governorFacets: { creatorFacet, instance },
voteCounterInstallation: vci,
} = facets;

const { EV } = runUtils;

const committee = governanceDriver.ecMembers;

await governanceDriver.proposeApiCall(
governedContract,
'add2',
[],
vci,
37n,
committee[0],
getQuestionId(2),
offerIds.invite.charter,
);
t.truthy(question2.instance);

t.like(committee[0].getLatestUpdateRecord(), {
status: { id: getQuestionId(2), numWantsSatisfied: 1 },
});

await governanceDriver.enactLatestProposal(
committee,
getVoteId(2),
offerIds.invite.committee,
);

for (const w of committee.slice(0, 2)) {
t.like(w.getLatestUpdateRecord(), {
status: { id: getVoteId(2), numWantsSatisfied: 1 },
});
}
await advanceTimeBy(1, 'minutes');

const lastOutcome = await governanceDriver.getLatestOutcome();
t.is(lastOutcome.outcome, 'win');

const contractPublicFacet = await EV(creatorFacet).getPublicFacet();
const calls = await EV(contractPublicFacet).getApiCalled();
t.is(calls, 3);
});
3 changes: 3 additions & 0 deletions packages/boot/tools/drivers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ export const makeGovernanceDriver = async (
charterOfferId = charterMembershipId,
instance = agoricNamesRemotes.instance.econCommitteeCharter,
) => {
console.log('ECM accept', charterOfferId);
if (!findInvitation(w, 'charter member invitation')) {
console.log('No charter member invitation found');
return;
Expand Down Expand Up @@ -320,6 +321,7 @@ export const makeGovernanceDriver = async (
}));

const ensureInvitationsAccepted = async () => {
console.log('DRIV ensure', invitationsAccepted);
if (invitationsAccepted) {
return;
}
Expand Down Expand Up @@ -400,6 +402,7 @@ export const makeGovernanceDriver = async (
enactLatestProposal,
getLatestOutcome,
async changeParams(instance: Instance, params: Object, path?: object) {
console.log('DRIV changePs');
instance || Fail`missing instance`;
await ensureInvitationsAccepted();
await proposeParams(instance, params, path);
Expand Down

0 comments on commit 0edc4ac

Please sign in to comment.