From d8a109edcc78c977ef856131b52dd449e6a9d724 Mon Sep 17 00:00:00 2001 From: Chris Hibbert Date: Wed, 27 Nov 2024 18:02:25 -0800 Subject: [PATCH] feat: upgrade v7-board and test it (#10516) closes: #10394 ## Description Upgrade v7-board. ### Security Considerations The Board is a critical vat. ### Scaling Considerations v7-Board is consuming more resources than it should. restarting it should clean up a fair amount of space. **...checking** ### Documentation Considerations None ### Testing Considerations Verify that the board doesn't lose anything. ### Upgrade Considerations Can go out in Upgrade 19. --- .../proposals/p:upgrade-19/.gitignore | 1 + .../proposals/p:upgrade-19/eval.sh | 9 +++- .../proposals/p:upgrade-19/package.json | 5 +- .../registry.test.js | 0 .../proposals/p:upgrade-19/test.sh | 1 + .../p:upgrade-19/upgradedBoard.test.js | 15 ++++++ golang/cosmos/app/upgrade.go | 22 ++++---- .../inter-protocol/replace-feeDistributor.js | 4 +- .../testing/replace-feeDistributor-short.js | 8 ++- .../scripts/testing/test-upgraded-board.js | 15 ++++++ .../builders/scripts/vats/upgrade-board.js | 20 ++++++++ .../vats/src/proposals/testUpgradedBoard.js | 35 +++++++++++++ .../src/proposals/upgrade-board-proposal.js | 50 +++++++++++++++++++ 13 files changed, 171 insertions(+), 14 deletions(-) rename a3p-integration/proposals/{n:upgrade-next => p:upgrade-19}/registry.test.js (100%) create mode 100644 a3p-integration/proposals/p:upgrade-19/upgradedBoard.test.js create mode 100644 packages/builders/scripts/testing/test-upgraded-board.js create mode 100644 packages/builders/scripts/vats/upgrade-board.js create mode 100644 packages/vats/src/proposals/testUpgradedBoard.js create mode 100644 packages/vats/src/proposals/upgrade-board-proposal.js diff --git a/a3p-integration/proposals/p:upgrade-19/.gitignore b/a3p-integration/proposals/p:upgrade-19/.gitignore index 8c6dbb7f6af..17bb7d663e2 100644 --- a/a3p-integration/proposals/p:upgrade-19/.gitignore +++ b/a3p-integration/proposals/p:upgrade-19/.gitignore @@ -1 +1,2 @@ replaceFeeDistributor/ +testUpgradedBoard/ diff --git a/a3p-integration/proposals/p:upgrade-19/eval.sh b/a3p-integration/proposals/p:upgrade-19/eval.sh index 612011ea52b..d5a8d48bf87 100644 --- a/a3p-integration/proposals/p:upgrade-19/eval.sh +++ b/a3p-integration/proposals/p:upgrade-19/eval.sh @@ -1,3 +1,10 @@ #!/bin/bash -# Do nothing because this is only testing the state resulting from previous proposals. +# evaluate the proposals in the /submission/ directory + +echo "UPGRADE-19 Running proposal declared in package.json" +# copy to run in the proposal package so the dependencies can be resolved +cp /usr/src/upgrade-test-scripts/eval_submission.js . + +echo RUNNING ./eval_submission.js +./eval_submission.js diff --git a/a3p-integration/proposals/p:upgrade-19/package.json b/a3p-integration/proposals/p:upgrade-19/package.json index e2f705ad798..f3b062f3c76 100644 --- a/a3p-integration/proposals/p:upgrade-19/package.json +++ b/a3p-integration/proposals/p:upgrade-19/package.json @@ -2,7 +2,10 @@ "agoricProposal": { "type": "/agoric.swingset.CoreEvalProposal", "sdk-generate": [ - "testing/replace-feeDistributor-short.js replaceFeeDistributor" + "testing/replace-feeDistributor-short.js replaceFeeDistributor", + "vats/upgrade-paRegistry.js", + "vats/upgrade-board.js", + "testing/test-upgraded-board.js testUpgradedBoard" ] }, "type": "module", diff --git a/a3p-integration/proposals/n:upgrade-next/registry.test.js b/a3p-integration/proposals/p:upgrade-19/registry.test.js similarity index 100% rename from a3p-integration/proposals/n:upgrade-next/registry.test.js rename to a3p-integration/proposals/p:upgrade-19/registry.test.js 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..c72b130c7f3 --- /dev/null +++ b/a3p-integration/proposals/p:upgrade-19/upgradedBoard.test.js @@ -0,0 +1,15 @@ +/* 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 => { + // agoricProposal.sdk-generate in package.json generates this proposal + await evalBundles('testUpgradedBoard'); + + t.pass(); +}); diff --git a/golang/cosmos/app/upgrade.go b/golang/cosmos/app/upgrade.go index 1396a18879b..8770675d792 100644 --- a/golang/cosmos/app/upgrade.go +++ b/golang/cosmos/app/upgrade.go @@ -214,15 +214,19 @@ func unreleasedUpgradeHandler(app *GaiaApp, targetUpgrade string) func(sdk.Conte ), ) - // CoreProposals for Upgrade 19 - CoreProposalSteps = append(CoreProposalSteps, - vm.CoreProposalStepForModules( - "@agoric/builders/scripts/inter-protocol/replace-feeDistributor.js", - ), - vm.CoreProposalStepForModules( - "@agoric/builders/scripts/vats/upgrade-paRegistry.js", - ), - ) + // // CoreProposals for Upgrade 19. These should not be introduced + // // before upgrade 18 is done because they would be run in n:upgrade-next + // CoreProposalSteps = append(CoreProposalSteps, + // vm.CoreProposalStepForModules( + // "@agoric/builders/scripts/inter-protocol/replace-feeDistributor.js", + // ), + // vm.CoreProposalStepForModules( + // "@agoric/builders/scripts/vats/upgrade-paRegistry.js", + // ), + // vm.CoreProposalStepForModules( + // "@agoric/builders/scripts/vats/upgrade-board.js", + // ), + // ) } app.upgradeDetails = &upgradeDetails{ diff --git a/packages/builders/scripts/inter-protocol/replace-feeDistributor.js b/packages/builders/scripts/inter-protocol/replace-feeDistributor.js index 4cfd846b873..60f0f5f3e6b 100644 --- a/packages/builders/scripts/inter-protocol/replace-feeDistributor.js +++ b/packages/builders/scripts/inter-protocol/replace-feeDistributor.js @@ -4,7 +4,7 @@ import { SECONDS_PER_HOUR } from '@agoric/inter-protocol/src/proposals/econ-beha /** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */ export const defaultProposalBuilder = async (_, opts) => { - console.log('OPTS', opts); + console.log('feeDist OPTS', opts); return harden({ sourceSpec: '@agoric/inter-protocol/src/proposals/replace-fee-distributor.js', @@ -16,7 +16,7 @@ export const defaultProposalBuilder = async (_, opts) => { export default async (homeP, endowments) => { const { writeCoreEval } = await makeHelpers(homeP, endowments); - await writeCoreEval('replace-feeDistributor-testing', utils => + await writeCoreEval('replace-feeDistributor', utils => defaultProposalBuilder(utils, { collectionInterval: 1n * SECONDS_PER_HOUR, keywordShares: { diff --git a/packages/builders/scripts/testing/replace-feeDistributor-short.js b/packages/builders/scripts/testing/replace-feeDistributor-short.js index 99a3987d87c..2cad2cca9ad 100644 --- a/packages/builders/scripts/testing/replace-feeDistributor-short.js +++ b/packages/builders/scripts/testing/replace-feeDistributor-short.js @@ -1,9 +1,15 @@ import { makeHelpers } from '@agoric/deploy-script-support'; import { getManifestForReplaceFeeDistributor } from '@agoric/inter-protocol/src/proposals/replace-fee-distributor.js'; +/** + * @file + * a Variant of ../inter-protocol/replace-feeDistributor.js that shortens the + * collectionInterval for testing + */ + /** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */ export const defaultProposalBuilder = async (_, opts) => { - console.log('OPTS', opts); + console.log('feeDist OPTS', opts); return harden({ sourceSpec: '@agoric/inter-protocol/src/proposals/replace-fee-distributor.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..78b21079d0a --- /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]+$/)); + + 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); + // /////// can we retrieve something stored long ago? //////// + 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..e98398fb9b3 --- /dev/null +++ b/packages/vats/src/proposals/upgrade-board-proposal.js @@ -0,0 +1,50 @@ +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: { board, 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 idsBefore = await E(board).ids(); + + const { adminNode } = await E(vatStore).get('board'); + await E(adminNode).upgrade(boardBundleCap, {}); + + const idsAfter = await E(board).ids(); + const same = + idsBefore.length === idsAfter.length && + idsBefore.every((element, index) => element === idsAfter[index]); + assert(same, 'keys must stay the same'); + + console.log('Board upgrade complete'); +}; + +export const getManifestForUpgradingBoard = (_powers, { boardRef }) => ({ + manifest: { + [upgradeBoard.name]: { + consume: { + board: 'board', + vatAdminSvc: 'vatAdminSvc', + vatStore: 'vatStore', + }, + }, + }, + options: { boardRef }, +});