diff --git a/a3p-integration/proposals/p:upgrade-19/package.json b/a3p-integration/proposals/p:upgrade-19/package.json index 2afd33dfb4b..c49beccaf1f 100644 --- a/a3p-integration/proposals/p:upgrade-19/package.json +++ b/a3p-integration/proposals/p:upgrade-19/package.json @@ -2,7 +2,8 @@ "agoricProposal": { "type": "/agoric.swingset.CoreEvalProposal", "sdk-generate": [ - "testing/replace-feeDistributor-short.js replaceFeeDistributor" + "testing/replace-feeDistributor-short.js replaceFeeDistributor", + "testing/test-upgraded-board.js" ] }, "type": "module", diff --git a/a3p-integration/proposals/p:upgrade-19/test.sh b/a3p-integration/proposals/p:upgrade-19/test.sh index 7b9ea0090c5..056fe6836ac 100644 --- a/a3p-integration/proposals/p:upgrade-19/test.sh +++ b/a3p-integration/proposals/p:upgrade-19/test.sh @@ -1,3 +1,4 @@ #!/bin/bash yarn ava replaceFeeDistributor.test.js +yarn ava upgradedBoard.test.js diff --git a/a3p-integration/proposals/p:upgrade-19/upgradedBoard.test.js b/a3p-integration/proposals/p:upgrade-19/upgradedBoard.test.js new file mode 100644 index 00000000000..410025f9388 --- /dev/null +++ b/a3p-integration/proposals/p:upgrade-19/upgradedBoard.test.js @@ -0,0 +1,14 @@ +/* eslint-env node */ +// @ts-check + +/** @file test that the upgraded board can store and retrieve values. */ + +import '@endo/init/legacy.js'; +import test from 'ava'; +import { evalBundles } from '@agoric/synthetic-chain'; + +test('test upgraded board', async t => { + await evalBundles('submission'); + + t.pass(); +}); diff --git a/golang/cosmos/app/upgrade.go b/golang/cosmos/app/upgrade.go index 818c1fd63ce..5777c4d6c6d 100644 --- a/golang/cosmos/app/upgrade.go +++ b/golang/cosmos/app/upgrade.go @@ -219,6 +219,9 @@ func unreleasedUpgradeHandler(app *GaiaApp, targetUpgrade string) func(sdk.Conte vm.CoreProposalStepForModules( "@agoric/builders/scripts/inter-protocol/replace-feeDistributor.js", ), + vm.CoreProposalStepForModules( + "@agoric/builders/scripts/vats/upgrade-board.js", + ), ) } diff --git a/packages/builders/scripts/testing/test-upgraded-board.js b/packages/builders/scripts/testing/test-upgraded-board.js new file mode 100644 index 00000000000..28d90d2346d --- /dev/null +++ b/packages/builders/scripts/testing/test-upgraded-board.js @@ -0,0 +1,15 @@ +import { makeHelpers } from '@agoric/deploy-script-support'; +import { getManifestForTestUpgradedBoard } from '@agoric/vats/src/proposals/testUpgradedBoard.js'; + +/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */ +export const defaultProposalBuilder = async () => + harden({ + sourceSpec: '@agoric/vats/src/proposals/testUpgradedBoard.js', + getManifestCall: [getManifestForTestUpgradedBoard.name], + }); + +/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').DeployScriptFunction} */ +export default async (homeP, endowments) => { + const { writeCoreEval } = await makeHelpers(homeP, endowments); + await writeCoreEval('testUpgradedBoard', defaultProposalBuilder); +}; diff --git a/packages/builders/scripts/vats/upgrade-board.js b/packages/builders/scripts/vats/upgrade-board.js new file mode 100644 index 00000000000..b2b3070b2cd --- /dev/null +++ b/packages/builders/scripts/vats/upgrade-board.js @@ -0,0 +1,20 @@ +import { makeHelpers } from '@agoric/deploy-script-support'; +import { getManifestForUpgradingBoard } from '@agoric/vats/src/proposals/upgrade-board-proposal.js'; + +/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */ +export const defaultProposalBuilder = async ({ publishRef, install }) => + harden({ + sourceSpec: '@agoric/vats/src/proposals/upgrade-board-proposal.js', + getManifestCall: [ + getManifestForUpgradingBoard.name, + { + boardRef: publishRef(install('@agoric/vats/src/vat-board.js')), + }, + ], + }); + +/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').DeployScriptFunction} */ +export default async (homeP, endowments) => { + const { writeCoreEval } = await makeHelpers(homeP, endowments); + await writeCoreEval('upgrade-board', defaultProposalBuilder); +}; diff --git a/packages/vats/src/proposals/testUpgradedBoard.js b/packages/vats/src/proposals/testUpgradedBoard.js new file mode 100644 index 00000000000..7289c6bc60c --- /dev/null +++ b/packages/vats/src/proposals/testUpgradedBoard.js @@ -0,0 +1,35 @@ +import { E, Far } from '@endo/far'; +import { Stable } from '@agoric/internal/src/tokens.js'; + +export const testUpgradedBoard = async ({ + consume: { board }, + brand: { + consume: { [Stable.symbol]: stableBrandP }, + }, +}) => { + // /////// can we store something and get it back? //////// + const thing1 = Far('thing1', {}); + const thing1Id = await E(board).getId(thing1); + assert(thing1Id.match(/^board0[0-9]+$/)); + + // /////// can we retrieve something stored long ago? //////// + const marshaller = await E(board).getReadonlyMarshaller(); + assert(marshaller, 'expected a marshaller'); + + const stableBrand = await stableBrandP; + // /////// can we retrieve a well-known object via its ID? //////// + const stableID = await E(board).getId(stableBrand); + const stableBrandRetrieved = await E(board).getValue(stableID); + assert(stableBrandRetrieved === stableBrand, 'retrieved matching brand'); +}; + +export const getManifestForTestUpgradedBoard = () => ({ + manifest: { + [testUpgradedBoard.name]: { + consume: { board: true }, + brand: { + consume: { [Stable.symbol]: true }, + }, + }, + }, +}); diff --git a/packages/vats/src/proposals/upgrade-board-proposal.js b/packages/vats/src/proposals/upgrade-board-proposal.js new file mode 100644 index 00000000000..394da36fcba --- /dev/null +++ b/packages/vats/src/proposals/upgrade-board-proposal.js @@ -0,0 +1,41 @@ +import { E } from '@endo/far'; + +/** + * @param {BootstrapPowers & { + * consume: { + * vatAdminSvc: VatAdminSvc; + * vatStore: MapStore< + * string, + * import('@agoric/swingset-vat').CreateVatResults + * >; + * }; + * }} powers + * @param {object} options + * @param {{ boardRef: VatSourceRef }} options.options + */ +export const upgradeBoard = async ( + { consume: { vatAdminSvc, vatStore } }, + options, +) => { + const { boardRef } = options.options; + + assert(boardRef.bundleID); + const boardBundleCap = await E(vatAdminSvc).getBundleCap(boardRef.bundleID); + console.log(`Board BUNDLE ID: `, boardRef.bundleID); + + const { adminNode } = await E(vatStore).get('board'); + + await E(adminNode).upgrade(boardBundleCap, {}); +}; + +export const getManifestForUpgradingBoard = (_powers, { boardRef }) => ({ + manifest: { + [upgradeBoard.name]: { + consume: { + vatAdminSvc: 'vatAdminSvc', + vatStore: 'vatStore', + }, + }, + }, + options: { boardRef }, +});