diff --git a/packages/governance/test/swingsetTests/contractGovernor/bootstrap.js b/packages/governance/test/swingsetTests/contractGovernor/bootstrap.js deleted file mode 100644 index 12dc64fe62b..00000000000 --- a/packages/governance/test/swingsetTests/contractGovernor/bootstrap.js +++ /dev/null @@ -1,558 +0,0 @@ -import { q } from '@endo/errors'; -import { E } from '@endo/eventual-send'; -import { Far } from '@endo/marshal'; -import { makeMockChainStorageRoot } from '@agoric/internal/src/storage-test-utils.js'; -import { observeIteration, subscribeEach } from '@agoric/notifier'; -import { buildZoeManualTimer } from '@agoric/zoe/tools/manualTimer.js'; - -import { - assertContractElectorate, - CONTRACT_ELECTORATE, -} from '../../../src/index.js'; -import { remoteNullMarshaller } from '../utils.js'; -import { makeTerms, MALLEABLE_NUMBER } from './governedContract.js'; - -/** - * @import {ContractGovernanceVoteResult, GovernedPublicFacetMethods, GovernorCreatorFacet, ParamChangesSpec, QuestionDetails, SimpleIssue, StandardParamPath} from '../../../src/types.js'; - */ - -/** - * @param {ERef} zoe - * @param {(string:string) => undefined} log - * @param {Record} installations - * @param {ERef>} contractFacetAccess - * @param {bigint} deadline - */ -const voteToChangeParameter = async ( - zoe, - log, - installations, - contractFacetAccess, - deadline, -) => { - /** @type {ParamChangesSpec} */ - const paramChangeSpec = harden({ - paramPath: { key: 'governedParams' }, - changes: { [MALLEABLE_NUMBER]: 299792458n }, - }); - - const { details, instance, outcomeOfUpdate } = await E( - contractFacetAccess, - ).voteOnParamChanges( - installations.binaryVoteCounter, - deadline, - paramChangeSpec, - ); - - E(E(zoe).getPublicFacet(instance)) - .getOutcome() - .then(outcome => log(`vote outcome: ${q(outcome)}`)) - .catch(e => log(`vote failed ${e}`)); - - E.when(outcomeOfUpdate, outcome => log(`updated to ${q(outcome)}`)).catch(e => - log(`update failed: ${e}`), - ); - return { details, outcomeOfUpdate }; -}; - -const installContracts = async (zoe, cb) => { - const [committee, binaryVoteCounter, contractGovernor, governedContract] = - await Promise.all([ - E(zoe).install(cb.committee), - E(zoe).install(cb.binaryVoteCounter), - E(zoe).install(cb.contractGovernor), - E(zoe).install(cb.governedContract), - ]); - const installations = { - committee, - binaryVoteCounter, - contractGovernor, - governedContract, - }; - return installations; -}; - -/** - * @param {ERef} zoe - * @param {Record} installations - * @param {Record} electorateTerms - * @returns {Promise<{electorateCreatorFacet: *, electorateInstance: Instance}>} - */ -const startElectorate = async (zoe, installations, electorateTerms) => { - const { creatorFacet: electorateCreatorFacet, instance: electorateInstance } = - await E(zoe).startInstance(installations.committee, {}, electorateTerms, { - storageNode: makeMockChainStorageRoot().makeChildNode('thisElectorate'), - marshaller: remoteNullMarshaller, - }); - return { electorateCreatorFacet, electorateInstance }; -}; - -const createVoters = async (electorateCreatorFacet, voterCreator) => { - const invitations = await E(electorateCreatorFacet).getVoterInvitations(); - - const aliceP = E(voterCreator).createVoter('Alice', invitations[0]); - const bobP = E(voterCreator).createVoter('Bob', invitations[1]); - const carolP = E(voterCreator).createVoter('Carol', invitations[2]); - const daveP = E(voterCreator).createVoter('Dave', invitations[3]); - const emmaP = E(voterCreator).createVoter('Emma', invitations[4]); - return Promise.all([aliceP, bobP, carolP, daveP, emmaP]); -}; - -const votersVote = async (detailsP, votersP, selections) => { - const [voters, details] = await Promise.all([votersP, detailsP]); - const { positions, questionHandle } = details; - - await Promise.all( - voters.map((v, i) => { - return E(v).castBallotFor(questionHandle, positions[selections[i]]); - }), - ); -}; - -/** - * @param {ERef} votersP - * @param {ERef} detailsP - * @param {ERef} governedInstanceP - * @param {Instance} electorateInstance - * @param {ERef} governorInstanceP - * @param {Record} installations - * @returns {Promise} - */ -const oneVoterValidate = async ( - votersP, - detailsP, - governedInstanceP, - electorateInstance, - governorInstanceP, - installations, -) => { - const [voters, details, governedInstance, governorInstance] = - await Promise.all([ - votersP, - detailsP, - governedInstanceP, - governorInstanceP, - ]); - const { counterInstance } = details; - - return E(voters[0]).validate( - counterInstance, - governedInstance, - electorateInstance, - governorInstance, - installations, - ); -}; - -const watchParams = async (zoe, contractInstanceP, log) => { - const contractInstance = await contractInstanceP; - /** @type {GovernedPublicFacetMethods} */ - const contractPublic = E(zoe).getPublicFacet(contractInstance); - const subscription = await E(contractPublic).getSubscription(); - /** @type {any} */ - let prev = await E(contractPublic).getGovernedParams(); - const paramChangeObserver = Far('param observer', { - updateState: ({ current }) => { - const changed = []; - if ( - prev.Electorate.value.value[0].handle !== - current.Electorate.value.value[0].handle - ) { - changed.push('Electorate'); - } - if (prev.MalleableNumber.value !== current.MalleableNumber.value) { - changed.push('MalleableNumber'); - } - log(`params update: `, changed.join(',')); - log( - `current value of MalleableNumber is ${current.MalleableNumber.value}`, - ); - prev = current; - }, - }); - void observeIteration(subscribeEach(subscription), paramChangeObserver); -}; - -const setupParameterChanges = async ( - zoe, - log, - governor, - installations, - invitation, - changes = { [CONTRACT_ELECTORATE]: invitation }, -) => { - const paramChangeSpec = harden({ - paramPath: { key: 'governedParams' }, - changes, - }); - /** @type {ContractGovernanceVoteResult} */ - const { details, instance, outcomeOfUpdate } = await E( - governor, - ).voteOnParamChanges(installations.binaryVoteCounter, 2n, paramChangeSpec); - - E(E(zoe).getPublicFacet(instance)) - .getOutcome() - .then(outcome => log(`vote outcome: ${q(outcome)}`)) - .catch(e => log(`vote failed ${e}`)); - - E.when(outcomeOfUpdate, outcome => log(`updated to (${q(outcome)})`)).catch( - e => log(`update failed: ${e}`), - ); - return { details, outcomeOfUpdate }; -}; - -const setupOfferFilterChange = async ( - zoe, - log, - governor, - installations, - invitation, - strings = ['foo', 'bar:'], -) => { - const filterChangeSpec = harden(strings); - /** @type {ContractGovernanceVoteResult} */ - const { details, instance, outcomeOfUpdate } = await E( - governor, - ).voteOnOfferFilter(installations.binaryVoteCounter, 2n, filterChangeSpec); - - E(E(zoe).getPublicFacet(instance)) - .getOutcome() - .then(outcome => log(`vote outcome: ${q(outcome)}`)) - .catch(e => log(`vote failed ${e}`)); - - E.when(outcomeOfUpdate, outcome => log(`updated to (${q(outcome)})`)).catch( - e => log(`update failed: ${e}`), - ); - return { details, outcomeOfUpdate }; -}; - -const setupApiCall = async (zoe, log, governor, installations) => { - const { details, instance, outcomeOfUpdate } = await E( - governor, - ).voteOnApiInvocation( - 'governanceApi', - [], // empty params - installations.binaryVoteCounter, - 2n, - ); - - E(E(zoe).getPublicFacet(instance)) - .getOutcome() - .then(outcome => log(`vote outcome: ${q(outcome)}`)) - .catch(e => log(`vote failed ${e}`)); - - E.when(outcomeOfUpdate, outcome => log(`update value: ${q(outcome)}`)).catch( - e => log(`update failed: ${e}`), - ); - return { details, outcomeOfUpdate }; -}; - -const validateElectorateChange = async ( - zoe, - log, - voters1, - detailsP, - governorInstance, - electorateInstance, - publicFacet, -) => { - const electorateValid = E(publicFacet).validateElectorate(electorateInstance); - const details = await detailsP; - const timerValid = E(publicFacet).validateTimer(details.closingRule); - - await assertContractElectorate(zoe, governorInstance, electorateInstance); - - await Promise.all([electorateValid, timerValid]); - - return log('Validation complete'); -}; - -const makeBootstrap = (argv, cb, vatPowers) => async (vats, devices) => { - const log = vatPowers.testLog; - const vatAdminSvc = await E(vats.vatAdmin).createVatAdminService( - devices.vatAdmin, - ); - /** @type {{zoeService: ERef}} */ - const { zoeService: zoe } = await E(vats.zoe).buildZoe( - vatAdminSvc, - undefined, - 'zcf', - ); - const installations = await installContracts(zoe, cb); - const timer = buildZoeManualTimer(log); - const voterCreator = E(vats.voter).build(zoe); - const firstElectorateTerms = { - committeeName: 'TwentyCommittee', - committeeSize: 5, - }; - const { - electorateCreatorFacet: firstElectorateCreatorFacet, - electorateInstance: firstElectorateInstance, - } = await startElectorate(zoe, installations, firstElectorateTerms); - - log(`=> voter and electorate vats are set up`); - - const initialPoserInvitation = await E( - firstElectorateCreatorFacet, - ).getPoserInvitation(); - const invitationIssuer = await E(zoe).getInvitationIssuer(); - const invitationValue = await E(invitationIssuer).getAmountOf( - initialPoserInvitation, - ); - - const terms = makeTerms(602214090000000000000000n, invitationValue); - const governedContractTerms = { - timer, - governedContractInstallation: installations.governedContract, - governed: { - issuerKeywordRecord: {}, - terms, - }, - }; - - const { creatorFacet: governor, instance: governorInstance } = await E( - zoe, - ).startInstance(installations.contractGovernor, {}, governedContractTerms, { - governed: { - initialPoserInvitation, - }, - }); - const governedInstance = E(governor).getInstance(); - const governedPF = E(governor).getPublicFacet(); - - const [testName] = argv; - switch (testName) { - case 'contractGovernorStart': { - await watchParams(zoe, governedInstance, log); - E(governedPF) - .getNum() - .then(num => log(`Number before: ${num}`)); - - const votersP = createVoters(firstElectorateCreatorFacet, voterCreator); - const { details: detailsP, outcomeOfUpdate: outcome1 } = - await voteToChangeParameter(zoe, log, installations, governor, 3n); - await votersVote(detailsP, votersP, [0, 1, 1, 0, 0]); - - await oneVoterValidate( - votersP, - detailsP, - governedInstance, - firstElectorateInstance, - governorInstance, - installations, - ); - - await E(timer).tick(); - await E(timer).tick(); - await E(timer).tick(); - await outcome1; - - await E(governedPF) - .getNum() - .then(num => log(`Number after: ${num}`)); - break; - } - case 'changeElectorateStart': { - await watchParams(zoe, governedInstance, log); - const voters1 = createVoters(firstElectorateCreatorFacet, voterCreator); - - const secondElectorateTerms = { - committeeName: 'ThirtyCommittee', - committeeSize: 5, - }; - const { - electorateCreatorFacet: secondElectorateCreatorFacet, - electorateInstance: secondElectorateInstance, - } = await startElectorate(zoe, installations, secondElectorateTerms); - const voters2 = createVoters(secondElectorateCreatorFacet, voterCreator); - - const newPoserInvitationP = E( - secondElectorateCreatorFacet, - ).getPoserInvitation(); - const [newPoserInvitation] = await Promise.all([newPoserInvitationP]); - - const { details: details1, outcomeOfUpdate: electorateOutcome } = - await setupParameterChanges( - zoe, - log, - governor, - installations, - newPoserInvitation, - ); - - await votersVote(details1, voters1, [1, 0, 0, 0, 1]); - await E(timer).tick(); - await E(timer).tick(); - await electorateOutcome; - - await validateElectorateChange( - zoe, - log, - voters1, - details1, - governorInstance, - secondElectorateInstance, - E(zoe).getPublicFacet(governorInstance), - ); - - const { details: details2, outcomeOfUpdate: outcome2 } = - await voteToChangeParameter(zoe, log, installations, governor, 4n); - await votersVote(details2, voters2, [0, 0, 1, 0, 1]); - await E(timer).tick(); - await E(timer).tick(); - await outcome2; - - break; - } - case 'brokenUpdateStart': { - await watchParams(zoe, governedInstance, log); - const voters1 = createVoters(firstElectorateCreatorFacet, voterCreator); - - const secondElectorateTerms = { - committeeName: 'ThirtyCommittee', - committeeSize: 5, - }; - const { electorateCreatorFacet: secondElectorateCreatorFacet } = - await startElectorate(zoe, installations, secondElectorateTerms); - - const newPoserInvitationP = E( - secondElectorateCreatorFacet, - ).getPoserInvitation(); - const [newPoserInvitation] = await Promise.all([newPoserInvitationP]); - - const changes = { - [MALLEABLE_NUMBER]: 42n, - [CONTRACT_ELECTORATE]: newPoserInvitation, - }; - const { details: details1, outcomeOfUpdate: electorateOutcome } = - await setupParameterChanges( - zoe, - log, - governor, - installations, - newPoserInvitation, - changes, - ); - await votersVote(details1, voters1, [1, 0, 0, 0, 1]); - - // The update will fail. - await E(E(zoe).getInvitationIssuer()).burn(newPoserInvitation); - - await E(timer).tick(); - await E(timer).tick(); - void E.when( - electorateOutcome, - o => log(`vote (unexpected) successful outcome: ${o} `), - e => log(`vote rejected outcome: ${e}`), - ); - - await validateElectorateChange( - zoe, - log, - voters1, - details1, - governorInstance, - // The electorate didn't change - firstElectorateInstance, - E(zoe).getPublicFacet(governorInstance), - ); - - break; - } - case 'changeTwoParams': { - await watchParams(zoe, governedInstance, log); - const voters1 = createVoters(firstElectorateCreatorFacet, voterCreator); - - const secondElectorateTerms = { - committeeName: 'ThirtyCommittee', - committeeSize: 5, - }; - const { - electorateCreatorFacet: secondElectorateCreatorFacet, - electorateInstance: secondElectorateInstance, - } = await startElectorate(zoe, installations, secondElectorateTerms); - - const newPoserInvitationP = E( - secondElectorateCreatorFacet, - ).getPoserInvitation(); - const [newPoserInvitation] = await Promise.all([newPoserInvitationP]); - - const changes = { - [MALLEABLE_NUMBER]: 42n, - [CONTRACT_ELECTORATE]: newPoserInvitation, - }; - const { details: details1, outcomeOfUpdate: electorateOutcome } = - await setupParameterChanges( - zoe, - log, - governor, - installations, - newPoserInvitation, - changes, - ); - await votersVote(details1, voters1, [1, 0, 0, 0, 1]); - - await E(timer).tick(); - await E(timer).tick(); - void E.when( - electorateOutcome, - o => log(`successful outcome: ${q(o)} `), - e => log(`vote (unexpected) rejected outcome: ${e}`), - ); - - await electorateOutcome; - await validateElectorateChange( - zoe, - log, - voters1, - details1, - governorInstance, - secondElectorateInstance, - E(zoe).getPublicFacet(governorInstance), - ); - - break; - } - case 'contractApiGovernanceStart': { - E(governedPF) - .getApiCalled() - .then(called => log(`Number before: ${called}`)); - - const voters1 = createVoters(firstElectorateCreatorFacet, voterCreator); - const { details: details1, outcomeOfUpdate: electorateOutcome } = - await setupApiCall(zoe, log, governor, installations); - - await votersVote(details1, voters1, [1, 0, 0, 0, 1]); - await E(timer).tick(); - await E(timer).tick(); - await electorateOutcome; - - await E(governedPF) - .getApiCalled() - .then(called => log(`Number after: ${called}`)); - break; - } - case 'offerFilterGovernanceStart': { - const voters = createVoters(firstElectorateCreatorFacet, voterCreator); - const { details: details1, outcomeOfUpdate: electorateOutcome } = - await setupOfferFilterChange(zoe, log, governor, installations); - - await votersVote(details1, voters, [1, 0, 0, 0, 1]); - await E(timer).tick(); - await E(timer).tick(); - await electorateOutcome; - - await E(zoe) - .getOfferFilter(governedInstance) - .then(strings => log(`filters set: ${strings}`)); - break; - } - default: - log(`didn't find test: ${argv}`); - } -}; - -export const buildRootObject = (vatPowers, vatParameters) => { - const { argv, contractBundles: cb } = vatParameters; - return Far('root', { bootstrap: makeBootstrap(argv, cb, vatPowers) }); -}; diff --git a/packages/governance/test/swingsetTests/contractGovernor/governedContract.js b/packages/governance/test/swingsetTests/contractGovernor/governedContract.js deleted file mode 100644 index b0231c0c78e..00000000000 --- a/packages/governance/test/swingsetTests/contractGovernor/governedContract.js +++ /dev/null @@ -1,52 +0,0 @@ -import { handleParamGovernance } from '../../../src/contractHelper.js'; -import { ParamTypes } from '../../../src/index.js'; -import { CONTRACT_ELECTORATE } from '../../../src/contractGovernance/governParam.js'; - -/** - * @import {GovernanceTerms} from '../../../src/types.js'; - */ - -const MALLEABLE_NUMBER = 'MalleableNumber'; - -const makeTerms = (number, invitationAmount) => { - return harden({ - governedParams: { - [MALLEABLE_NUMBER]: { type: ParamTypes.NAT, value: number }, - [CONTRACT_ELECTORATE]: { - type: ParamTypes.INVITATION, - value: invitationAmount, - }, - }, - }); -}; - -/** - * - * @param {ZCF< - * GovernanceTerms<{ - * MalleableNumber: 'nat', - * }>>} zcf - * @param {{initialPoserInvitation: Invitation}} privateArgs - */ -const start = async (zcf, privateArgs) => { - const { augmentPublicFacet, makeGovernorFacet, params } = - await handleParamGovernance(zcf, privateArgs.initialPoserInvitation, { - [MALLEABLE_NUMBER]: ParamTypes.NAT, - }); - - let governanceAPICalled = 0; - const governanceApi = () => (governanceAPICalled += 1); - return { - publicFacet: augmentPublicFacet({ - getNum: () => params.getMalleableNumber(), - getApiCalled: () => governanceAPICalled, - }), - creatorFacet: makeGovernorFacet({}, { governanceApi }), - }; -}; - -harden(start); -harden(MALLEABLE_NUMBER); -harden(makeTerms); - -export { start, MALLEABLE_NUMBER, makeTerms }; diff --git a/packages/governance/test/swingsetTests/contractGovernor/governor.test.js b/packages/governance/test/swingsetTests/contractGovernor/governor.test.js deleted file mode 100644 index de24bb0268b..00000000000 --- a/packages/governance/test/swingsetTests/contractGovernor/governor.test.js +++ /dev/null @@ -1,227 +0,0 @@ -import { test } from '@agoric/swingset-vat/tools/prepare-test-env-ava.js'; -import path from 'path'; - -import { buildVatController, buildKernelBundles } from '@agoric/swingset-vat'; -import bundleSource from '@endo/bundle-source'; -import zcfBundle from '@agoric/zoe/bundles/bundle-contractFacet.js'; - -const CONTRACT_FILES = [ - 'committee', - 'contractGovernor', - 'binaryVoteCounter', - { - contractPath: '/governedContract', - bundleName: 'governedContract', - }, -]; - -const dirname = path.dirname(new URL(import.meta.url).pathname); - -test.before(async t => { - const start = Date.now(); - const kernelBundles = await buildKernelBundles(); - const step2 = Date.now(); - const contractBundles = {}; - await Promise.all( - CONTRACT_FILES.map(async settings => { - let bundleName; - let contractPath; - if (typeof settings === 'string') { - bundleName = settings; - contractPath = `/../../../src/${settings}`; - } else { - ({ bundleName, contractPath } = settings); - } - const source = `${dirname}${contractPath}`; - const bundle = await bundleSource(source); - contractBundles[bundleName] = bundle; - }), - ); - const step3 = Date.now(); - - const vats = {}; - await Promise.all( - ['voter'].map(async name => { - const source = `${dirname}/vat-${name}.js`; - const bundle = await bundleSource(source); - vats[name] = { bundle }; - }), - ); - vats.zoe = { - sourceSpec: `${dirname}/../../../../vats/src/vat-zoe.js`, - }; - const bootstrapSource = `${dirname}/bootstrap.js`; - vats.bootstrap = { - bundle: await bundleSource(bootstrapSource, { dev: true }), - parameters: { contractBundles }, // argv will be added to this - }; - const config = { bootstrap: 'bootstrap', vats }; - config.bundles = { zcf: { bundle: zcfBundle } }; - config.defaultManagerType = 'xs-worker'; - - const step4 = Date.now(); - const ktime = `${(step2 - start) / 1000}s kernel`; - const ctime = `${(step3 - step2) / 1000}s contracts`; - const vtime = `${(step4 - step3) / 1000}s vats`; - const ttime = `${(step4 - start) / 1000}s total`; - console.log(`bundling: ${ktime}, ${ctime}, ${vtime}, ${ttime}`); - - // @ts-expect-error - t.context.data = { kernelBundles, config }; -}); - -const main = async (t, argv) => { - const { kernelBundles, config } = t.context.data; - const controller = await buildVatController(config, argv, { kernelBundles }); - t.teardown(controller.shutdown); - await controller.run(); - return controller.dump(); -}; - -test.serial('contract governance', async t => { - const dump = await main(t, ['contractGovernorStart']); - t.deepEqual(dump.log, [ - '=> voter and electorate vats are set up', - 'Number before: 602214090000000000000000', - 'params update: ', - 'current value of MalleableNumber is 602214090000000000000000', - '@@ schedule task for:3, currently: 0 @@', - 'Voter Alice voted for {"changes":{"MalleableNumber":"[299792458n]"}}', - 'Voter Bob voted for {"noChange":["MalleableNumber"]}', - 'Voter Carol voted for {"noChange":["MalleableNumber"]}', - 'Voter Dave voted for {"changes":{"MalleableNumber":"[299792458n]"}}', - 'Voter Emma voted for {"changes":{"MalleableNumber":"[299792458n]"}}', - 'Voter Alice validated all the things', - '@@ tick:1 @@', - '@@ tick:2 @@', - '@@ tick:3 @@', - 'vote outcome: {"changes":{"MalleableNumber":"[299792458n]"}}', - 'params update: MalleableNumber', - 'current value of MalleableNumber is 299792458', - 'updated to {"changes":{"MalleableNumber":"[299792458n]"}}', - 'Number after: 299792458', - ]); -}); - -test.serial('change electorate', async t => { - const dump = await main(t, ['changeElectorateStart']); - t.deepEqual(dump.log, [ - '=> voter and electorate vats are set up', - 'params update: ', - 'current value of MalleableNumber is 602214090000000000000000', - '@@ schedule task for:2, currently: 0 @@', - 'Voter Alice voted for {"noChange":["Electorate"]}', - 'Voter Bob voted for {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]}}}', - 'Voter Carol voted for {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]}}}', - 'Voter Dave voted for {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]}}}', - 'Voter Emma voted for {"noChange":["Electorate"]}', - '@@ tick:1 @@', - '@@ tick:2 @@', - 'vote outcome: {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]}}}', - 'params update: Electorate', - 'current value of MalleableNumber is 602214090000000000000000', - 'updated to ({"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]}}})', - 'Validation complete', - '@@ schedule task for:4, currently: 2 @@', - 'Voter Alice voted for {"changes":{"MalleableNumber":"[299792458n]"}}', - 'Voter Bob voted for {"changes":{"MalleableNumber":"[299792458n]"}}', - 'Voter Carol voted for {"noChange":["MalleableNumber"]}', - 'Voter Dave voted for {"changes":{"MalleableNumber":"[299792458n]"}}', - 'Voter Emma voted for {"noChange":["MalleableNumber"]}', - '@@ tick:3 @@', - '@@ tick:4 @@', - 'vote outcome: {"changes":{"MalleableNumber":"[299792458n]"}}', - 'params update: MalleableNumber', - 'current value of MalleableNumber is 299792458', - 'updated to {"changes":{"MalleableNumber":"[299792458n]"}}', - ]); -}); - -test.serial('brokenUpdateStart', async t => { - const dump = await main(t, ['brokenUpdateStart']); - t.deepEqual(dump.log, [ - '=> voter and electorate vats are set up', - 'params update: ', - 'current value of MalleableNumber is 602214090000000000000000', - '@@ schedule task for:2, currently: 0 @@', - 'Voter Alice voted for {"noChange":["Electorate","MalleableNumber"]}', - 'Voter Bob voted for {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]},"MalleableNumber":"[42n]"}}', - 'Voter Carol voted for {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]},"MalleableNumber":"[42n]"}}', - 'Voter Dave voted for {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]},"MalleableNumber":"[42n]"}}', - 'Voter Emma voted for {"noChange":["Electorate","MalleableNumber"]}', - '@@ tick:1 @@', - '@@ tick:2 @@', - 'vote outcome: {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]},"MalleableNumber":"[42n]"}}', - 'Validation complete', - // [`prepareToSetInvitation`](https://github.com/Agoric/agoric-sdk/blob/c6570b015fd23c411e48981bec309b32eedd3a28/packages/governance/src/contractGovernance/paramManager.js#L199-L212) - // does a `Promise.all` on 2 calls using the `invite` promise. If that promise - // is rejected, this will result in a rejection race between the 2 paths. The - // following 2 entries may come back as the commented out lines if the kernel - // changes the order in which messages are processed. - // TODO: allow either message - // 'vote rejected outcome: Error: (an object) was not a live payment for brand (an object). It could be a used-up payment, a payment for another brand, or it might not be a payment at all.', - // 'update failed: Error: (an object) was not a live payment for brand (an object). It could be a used-up payment, a payment for another brand, or it might not be a payment at all.', - 'vote rejected outcome: Error: (an object) was not a live payment for brand "[Alleged: Zoe Invitation brand]". It could be a used-up payment, a payment for another brand, or it might not be a payment at all.', - 'update failed: Error: (an object) was not a live payment for brand "[Alleged: Zoe Invitation brand]". It could be a used-up payment, a payment for another brand, or it might not be a payment at all.', - ]); -}); - -test.serial('changeTwoParams', async t => { - const dump = await main(t, ['changeTwoParams']); - t.deepEqual(dump.log, [ - '=> voter and electorate vats are set up', - 'params update: ', - 'current value of MalleableNumber is 602214090000000000000000', - '@@ schedule task for:2, currently: 0 @@', - 'Voter Alice voted for {"noChange":["Electorate","MalleableNumber"]}', - 'Voter Bob voted for {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]},"MalleableNumber":"[42n]"}}', - 'Voter Carol voted for {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]},"MalleableNumber":"[42n]"}}', - 'Voter Dave voted for {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]},"MalleableNumber":"[42n]"}}', - 'Voter Emma voted for {"noChange":["Electorate","MalleableNumber"]}', - '@@ tick:1 @@', - '@@ tick:2 @@', - 'vote outcome: {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]},"MalleableNumber":"[42n]"}}', - 'params update: Electorate,MalleableNumber', - 'current value of MalleableNumber is 42', - 'updated to ({"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]},"MalleableNumber":"[42n]"}})', - 'successful outcome: {"changes":{"Electorate":{"brand":"[Alleged: Zoe Invitation brand]","value":[{"description":"questionPoser","handle":"[Alleged: InvitationHandle]","installation":"[Alleged: BundleInstallation]","instance":"[Alleged: InstanceHandle]"}]},"MalleableNumber":"[42n]"}} ', - 'Validation complete', - ]); -}); - -test.serial('api Governance', async t => { - const dump = await main(t, ['contractApiGovernanceStart']); - t.deepEqual(dump.log, [ - '=> voter and electorate vats are set up', - 'Number before: 0', - '@@ schedule task for:2, currently: 0 @@', - 'Voter Alice voted for {"dontInvoke":"governanceApi"}', - 'Voter Bob voted for {"apiMethodName":"governanceApi","methodArgs":[]}', - 'Voter Carol voted for {"apiMethodName":"governanceApi","methodArgs":[]}', - 'Voter Dave voted for {"apiMethodName":"governanceApi","methodArgs":[]}', - 'Voter Emma voted for {"dontInvoke":"governanceApi"}', - '@@ tick:1 @@', - '@@ tick:2 @@', - 'vote outcome: {"apiMethodName":"governanceApi","methodArgs":[]}', - 'update value: {"apiMethodName":"governanceApi","methodArgs":[]}', - 'Number after: 1', - ]); -}); - -test.serial('offer filter', async t => { - const dump = await main(t, ['offerFilterGovernanceStart']); - t.deepEqual(dump.log, [ - '=> voter and electorate vats are set up', - '@@ schedule task for:2, currently: 0 @@', - 'Voter Alice voted for {"dontUpdate":["foo","bar:"]}', - 'Voter Bob voted for {"strings":["foo","bar:"]}', - 'Voter Carol voted for {"strings":["foo","bar:"]}', - 'Voter Dave voted for {"strings":["foo","bar:"]}', - 'Voter Emma voted for {"dontUpdate":["foo","bar:"]}', - '@@ tick:1 @@', - '@@ tick:2 @@', - 'vote outcome: {"strings":["foo","bar:"]}', - 'updated to ({"strings":["foo","bar:"]})', - 'filters set: foo,bar:', - ]); -}); diff --git a/packages/governance/test/swingsetTests/contractGovernor/vat-voter.js b/packages/governance/test/swingsetTests/contractGovernor/vat-voter.js deleted file mode 100644 index 4f8cb994f86..00000000000 --- a/packages/governance/test/swingsetTests/contractGovernor/vat-voter.js +++ /dev/null @@ -1,115 +0,0 @@ -import { q } from '@endo/errors'; -import { E } from '@endo/eventual-send'; -import { Far } from '@endo/marshal'; - -import { - assertContractElectorate, - assertContractGovernance, - validateQuestionFromCounter, - validateQuestionDetails, - assertBallotConcernsParam, -} from '../../../src/index.js'; -import { MALLEABLE_NUMBER } from './governedContract.js'; - -const build = async (log, zoe) => { - return Far('voter', { - createVoter: async (name, invitation) => { - const seat = E(zoe).offer(invitation); - const { voter } = E.get(E(seat).getOfferResult()); - - return Far(`Voter ${name}`, { - castBallotFor: async (questionHandle, choice) => { - log(`Voter ${name} voted for ${q(choice)}`); - return E(voter).castBallotFor(questionHandle, [choice]); - }, - /** - * - * @param {Instance} counterInstance - * @param {Instance} governedInstance - * @param {Instance} electorateInstance - * @param {Instance} governorInstance - * @param {Record} installations - * @returns {Promise} - */ - validate: async ( - counterInstance, - governedInstance, - electorateInstance, - governorInstance, - installations, - ) => { - const validateQuestionFromCounterP = validateQuestionFromCounter( - zoe, - electorateInstance, - counterInstance, - ); - - const contractGovernanceP = assertContractGovernance( - zoe, - governedInstance, - governorInstance, - installations.contractGovernor, - ); - - const [ - questionDetails, - electorateInstallation, - voteCounterInstallation, - governedInstallation, - governorInstallation, - validatedQuestion, - contractGovernance, - ] = await Promise.all([ - E(E(zoe).getPublicFacet(counterInstance)).getDetails(), - E(zoe).getInstallationForInstance(electorateInstance), - E(zoe).getInstallationForInstance(counterInstance), - E(zoe).getInstallationForInstance(governedInstance), - E(zoe).getInstallationForInstance(governorInstance), - validateQuestionFromCounterP, - contractGovernanceP, - ]); - - assertBallotConcernsParam( - harden({ - paramPath: { key: 'governedParams' }, - parameterName: MALLEABLE_NUMBER, - }), - questionDetails, - ); - assert(installations.binaryVoteCounter === voteCounterInstallation); - assert(installations.governedContract === governedInstallation); - assert(installations.contractGovernor === governorInstallation); - assert(installations.committee === electorateInstallation); - await assertContractElectorate( - zoe, - governorInstance, - electorateInstance, - ); - - await validateQuestionDetails( - zoe, - electorateInstance, - questionDetails, - ); - assert(validatedQuestion, 'governor failed to validate electorate'); - assert( - contractGovernance, - "governor and governed aren't tightly linked", - ); - - log(`Voter ${name} validated all the things`); - }, - }); - }, - }); -}; - -/** - * @typedef {ReturnType>['createVoter']>} EVatVoter - */ - -/** @type {import('@agoric/swingset-vat/src/kernel/vat-loader/types.js').BuildRootObjectForTestVat} */ -export const buildRootObject = vatPowers => - Far('root', { - build: (...args) => build(vatPowers.testLog, ...args), - });