Skip to content

Commit

Permalink
test: a test framework for verifying upgrade of Zoe and ZCF
Browse files Browse the repository at this point in the history
It starts from the currently installed version of Zoe and ZCF. First
it verifies that reallocation via staging and via the helper work and
that the version internal to ZCF is not present. It then upgrades Zoe
and ZCF as necessary to introduce the new behavior. Finally, it
re-runs the initial verification to show that the ZCF internal version
works.

This currently fails on the first step since it runs in a state in
which the new Zoe/ZCF code has already replaced the old.

Variants of this test will run on master without this PR to verify
that upgrading to the new Zoe/ZCF works, and in
deployment/upgrade-test to show that the upgrade to the new zoe & zcf
will succeed.
  • Loading branch information
Chris-Hibbert committed Jun 22, 2023
1 parent a7895a9 commit 700e334
Show file tree
Hide file tree
Showing 8 changed files with 587 additions and 153 deletions.
1 change: 1 addition & 0 deletions packages/vats/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"build:boot-viz-sim": "node src/authorityViz.js --sim-chain >docs/boot-sim.dot && dot -Tsvg docs/boot-sim.dot >docs/boot-sim.dot.svg",
"build:boot-viz-sim-gov": "node src/authorityViz.js --sim-chain --gov >docs/boot-sim-gov.dot && dot -Tsvg docs/boot-sim-gov.dot >docs/boot-sim-gov.dot.svg",
"build:restart-vats-proposal": "agoric run scripts/restart-vats.js",
"build:zcf-proposal": "agoric run scripts/replace-zoe.js",
"prepack": "tsc --build jsconfig.build.json",
"postpack": "git clean -f '*.d.ts*'",
"test": "ava",
Expand Down
19 changes: 19 additions & 0 deletions packages/vats/scripts/replace-zoe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { makeHelpers } from '@agoric/deploy-script-support';

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').ProposalBuilder} */
export const defaultProposalBuilder = async ({ publishRef, install }) =>
harden({
sourceSpec: '../src/proposals/zcf-proposal.js',
getManifestCall: [
'getManifestForZoe',
{
zoeRef: publishRef(install('../src/vat-zoe.js')),
zcfRef: publishRef(install('../../zoe/src/contractFacet/vatRoot.js')),
},
],
});

export default async (homeP, endowments) => {
const { writeCoreProposal } = await makeHelpers(homeP, endowments);
await writeCoreProposal('replace-zcf', defaultProposalBuilder);
};
44 changes: 44 additions & 0 deletions packages/vats/src/proposals/zcf-proposal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { E } from '@endo/far';

/**
* @param { BootstrapPowers & {
* consume: {
* vatAdminSvc: VatAdminSve,
* vatStore: MapStore<string, CreateVatResults>,
* }
* }} powers
*
* @param {object} options
* @param {{zoeRef: VatSourceRef, zcfRef: VatSourceRef}} options.options
*/
export const upgradeZcf = async (
{ consume: { vatAdminSvc, vatStore } },
options,
) => {
const { zoeRef, zcfRef } = options.options;

const zoeBundleCap = await E(vatAdminSvc).getBundleCap(zoeRef.bundleID);

const { adminNode, root: zoeRoot } = await E(vatStore).get('zoe');

await E(adminNode).upgrade(zoeBundleCap, {});

const zoeConfigFacet = await E(zoeRoot).getZoeConfigFacet();
await E(zoeConfigFacet).updateZcfBundleId(zcfRef.bundleID);
};

export const getManifestForZoe = (_powers, { zoeRef, zcfRef }) => ({
manifest: {
[upgradeZcf.name]: {
consume: {
vatAdminSvc: 'vatAdminSvc',
vatStore: 'vatStore',
},
produce: {},
},
},
options: {
zoeRef,
zcfRef,
},
});
82 changes: 82 additions & 0 deletions packages/vats/test/bootstrapTests/drivers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Offers } from '@agoric/inter-protocol/src/clientSupport.js';
import { SECONDS_PER_MINUTE } from '@agoric/inter-protocol/src/proposals/econ-behaviors.js';
import { unmarshalFromVstorage } from '@agoric/internal/src/lib-chainStorage.js';
import { slotToRemotable } from '@agoric/internal/src/storage-test-utils.js';

import { boardSlottingMarshaller } from '../../tools/board-utils.js';

/**
Expand Down Expand Up @@ -339,3 +340,84 @@ export const makeGovernanceDriver = async (
},
};
};

/**
* @param {import('./supports.js').SwingsetTestKit} testKit
*/
export const makeZoeDriver = async testKit => {
const { EV } = testKit.runUtils;
const zoe = await EV.vat('bootstrap').consumeItem('zoe');
let creatorFacet;
let adminFacet;
let brand;
const sub = (a, v) => {
return { brand: a.brand, value: a.value - v };
};

return {
async instantiateProbeContract(probeContractBundle) {
const installation = await EV(zoe).install(probeContractBundle);
const startResults = await EV(zoe).startInstance(installation);
({ creatorFacet, adminFacet } = startResults);

const issuers = await EV(zoe).getIssuers(startResults.instance);
const brands = await EV(zoe).getBrands(startResults.instance);
brand = brands.Ducats;
return { creatorFacet, issuer: issuers.Ducats, brand };
},
async upgradeProbe(probeContractBundle) {
const fabricateBundleId = bundle => {
return `b1-${bundle.endoZipBase64Sha512}`;
};

debugger;
await EV(adminFacet).upgradeContract(
fabricateBundleId(probeContractBundle),
);
},

verifyRealloc() {
const alloc = EV(creatorFacet).getAllocation();
return alloc;
},
async probeReallocation(value, payment) {
const stagingInv = await EV(creatorFacet).makeProbeStagingInvitation();

const stagingSeat = await EV(zoe).offer(
stagingInv,
{ give: { Ducats: value } },
{ Ducats: payment },
);
const helperPayments = await EV(stagingSeat).getPayouts();

const helperInv = await EV(creatorFacet).makeProbeHelperInvitation();
const helperSeat = await EV(zoe).offer(
helperInv,
{ give: { Ducats: sub(value, 1n) } },
{ Ducats: helperPayments.Ducats },
);
const internalPayments = await EV(helperSeat).getPayouts();

const internalInv = await EV(creatorFacet).makeProbeInternalInvitation();
const internalSeat = await EV(zoe).offer(
internalInv,
{ give: { Ducats: sub(value, 2n) } },
{ Ducats: internalPayments.Ducats },
);
const leftoverPayments = await EV(internalSeat).getPayouts();

return {
stagingResult: await EV(stagingSeat).getOfferResult(),
helperResult: await EV(helperSeat).getOfferResult(),
internalResult: await EV(internalSeat).getOfferResult(),
leftoverPayments,
};
},
async faucet() {
const faucetInv = await EV(creatorFacet).makeFaucetInvitation();
const seat = await EV(zoe).offer(faucetInv);

return EV(seat).getPayout('Ducats');
},
};
};
Loading

0 comments on commit 700e334

Please sign in to comment.