From f2a2b8d87461bfed4d194512a756f6570d9e409a Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Wed, 23 Aug 2023 16:02:53 -0500 Subject: [PATCH] chore: split game1 proposal from walletFactory upgrade --- .../scripts/smart-wallet/build-game1-start.js | 34 +++++ .../build-walletFactory-upgrade.js | 35 +++++ .../agoric-upgrade-11/actions.sh | 0 .../wallet-all-ertp/wf-game-propose.sh | 3 +- .../wallet-all-ertp/wf-install-bundles.sh | 7 +- packages/smart-wallet/scripts/wfup.js | 57 -------- .../upgrade-walletFactory-proposal.js | 129 +----------------- .../smart-wallet/test/start-game1-proposal.js | 125 +++++++++++++++++ 8 files changed, 203 insertions(+), 187 deletions(-) create mode 100644 packages/builders/scripts/smart-wallet/build-game1-start.js create mode 100644 packages/builders/scripts/smart-wallet/build-walletFactory-upgrade.js mode change 100644 => 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/actions.sh delete mode 100644 packages/smart-wallet/scripts/wfup.js create mode 100644 packages/smart-wallet/test/start-game1-proposal.js diff --git a/packages/builders/scripts/smart-wallet/build-game1-start.js b/packages/builders/scripts/smart-wallet/build-game1-start.js new file mode 100644 index 000000000000..6de32ba2804b --- /dev/null +++ b/packages/builders/scripts/smart-wallet/build-game1-start.js @@ -0,0 +1,34 @@ +/** + * @file Proposal Builder: Upgrade walletFactory + * + * Usage: + * agoric run build-game1-start.js + */ + +import { makeHelpers } from '@agoric/deploy-script-support'; +import { getManifestForGame1 } from '@agoric/smart-wallet/test/start-game1-proposal.js'; + +/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').ProposalBuilder} */ +export const game1ProposalBuilder = async ({ publishRef, install }) => { + return harden({ + sourceSpec: '@agoric/smart-wallet/test/start-game1-proposal.js', + getManifestCall: [ + getManifestForGame1.name, + { + game1Ref: publishRef( + install( + '@agoric/smart-wallet/test/gameAssetContract.js', + '../bundles/bundle-game1.js', + { persist: true }, + ), + ), + }, + ], + }); +}; + +/** @type {DeployScriptFunction} */ +export default async (homeP, endowments) => { + const { writeCoreProposal } = await makeHelpers(homeP, endowments); + await writeCoreProposal('start-game1', game1ProposalBuilder); +}; diff --git a/packages/builders/scripts/smart-wallet/build-walletFactory-upgrade.js b/packages/builders/scripts/smart-wallet/build-walletFactory-upgrade.js new file mode 100644 index 000000000000..c7cfcdcd93d5 --- /dev/null +++ b/packages/builders/scripts/smart-wallet/build-walletFactory-upgrade.js @@ -0,0 +1,35 @@ +/** + * @file Proposal Builder: Upgrade walletFactory + * + * Usage: + * agoric run build-walletFactory-upgrade.js + */ + +import { makeHelpers } from '@agoric/deploy-script-support'; +import { getManifestForUpgrade } from '@agoric/smart-wallet/src/proposals/upgrade-walletFactory-proposal.js'; + +/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').ProposalBuilder} */ +export const defaultProposalBuilder = async ({ publishRef, install }) => { + return harden({ + sourceSpec: + '@agoric/smart-wallet/src/proposals/upgrade-walletFactory-proposal.js', + getManifestCall: [ + getManifestForUpgrade.name, + { + walletFactoryRef: publishRef( + install( + '@agoric/smart-wallet/src/walletFactory.js', + '../bundles/bundle-walletFactory.js', + { persist: true }, + ), + ), + }, + ], + }); +}; + +/** @type {DeployScriptFunction} */ +export default async (homeP, endowments) => { + const { writeCoreProposal } = await makeHelpers(homeP, endowments); + await writeCoreProposal('upgrade-walletFactory', defaultProposalBuilder); +}; diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/actions.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/actions.sh old mode 100644 new mode 100755 diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/wf-game-propose.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/wf-game-propose.sh index c7c89e452adc..80b1e1d41b1f 100755 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/wf-game-propose.sh +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/wf-game-propose.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Propose and carry out Wallet Factory upgrade +# Propose and carry out starting game contract SDK=${SDK:-/usr/src/agoric-sdk} UP11=${UP11:-$SDK/upgrade-test-scripts/agoric-upgrade-11} @@ -15,6 +15,7 @@ TITLE="Start Game1 Contract" DESC="Start Game1 and register well-known Place issuer" +# TODO: fix error recovery (or don't bother with it at all) [ -f ./start-game1-permit.json ] || (echo run wf-install-bundle.sh first ; exit 1) agd tx gov submit-proposal \ diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/wf-install-bundles.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/wf-install-bundles.sh index 9695bf2e244d..b4432fdf7a7d 100755 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/wf-install-bundles.sh +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/wf-install-bundles.sh @@ -9,8 +9,10 @@ UP11=${UP11:-$SDK/upgrade-test-scripts/agoric-upgrade-11} cd $UP11/wallet-all-ertp -echo +++ run walletFactory upgrade proposal builder +++ -agoric run $SDK/packages/smart-wallet/scripts/wfup.js >/tmp/,run.log +echo +++ run walletFactory, game upgrade proposal builders +++ +(agoric run $SDK/packages/builders/scripts/smart-wallet/build-walletFactory-upgrade.js; \ +agoric run $SDK/packages/builders/scripts/smart-wallet/build-game1-start.js + )>/tmp/,run.log bundles=$($UP11/tools/parseProposals.mjs { - return harden({ - sourceSpec: '../src/proposals/upgrade-walletFactory-proposal.js', - getManifestCall: [ - getManifestForUpgrade.name, - { - walletFactoryRef: publishRef( - install( - '../src/walletFactory.js', - '../bundles/bundle-walletFactory.js', - { persist: true }, - ), - ), - }, - ], - }); -}; - -/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').ProposalBuilder} */ -export const game1ProposalBuilder = async ({ publishRef, install }) => { - return harden({ - sourceSpec: '../src/proposals/upgrade-walletFactory-proposal.js', - getManifestCall: [ - getManifestForGame1.name, - { - game1Ref: publishRef( - install( - '../test/gameAssetContract.js', - '../bundles/bundle-game1.js', - { persist: true }, - ), - ), - }, - ], - }); -}; - -/** @type {DeployScriptFunction} */ -export default async (homeP, endowments) => { - const { writeCoreProposal } = await makeHelpers(homeP, endowments); - await writeCoreProposal('upgrade-walletFactory', defaultProposalBuilder); - await writeCoreProposal('start-game1', game1ProposalBuilder); -}; diff --git a/packages/smart-wallet/src/proposals/upgrade-walletFactory-proposal.js b/packages/smart-wallet/src/proposals/upgrade-walletFactory-proposal.js index f28a62ee8271..b2199453140d 100644 --- a/packages/smart-wallet/src/proposals/upgrade-walletFactory-proposal.js +++ b/packages/smart-wallet/src/proposals/upgrade-walletFactory-proposal.js @@ -1,10 +1,10 @@ // @ts-check import { E } from '@endo/far'; import { makeMarshal } from '@endo/marshal'; +import { allValues } from '@agoric/internal'; -console.warn('@@@ upgrade-walletFactory-proposal.js module evaluating'); +console.warn('upgrade-walletFactory-proposal.js module evaluating'); -const { fromEntries, keys, values } = Object; const { Fail } = assert; // vstorage paths under published.* @@ -13,18 +13,6 @@ const BOARD_AUX = 'boardAux'; const marshalData = makeMarshal(_val => Fail`data only`); -// borrow zip, allValues from @agoric/interal -// but don't bring in all of @endo/marshal etc. -/** @type { (xs: X[], ys: Y[]) => [X, Y][]} */ -const zip = (xs, ys) => harden(xs.map((x, i) => [x, ys[+i]])); - -/** @type { >>(obj: T) => Promise<{ [K in keyof T]: Awaited}> } */ -const allValues = async obj => { - const resolved = await Promise.all(values(obj)); - // @ts-expect-error cast - return harden(fromEntries(zip(keys(obj), resolved))); -}; - /** * @param { BootstrapPowers } powers * @@ -137,116 +125,3 @@ export const getManifestForUpgrade = (_powers, { walletFactoryRef }) => { options: { walletFactoryRef }, }); }; - -// avoid importing all of ERTP -const makeAmount = (brand, value) => harden({ brand, value }); - -const IST_UNIT = 1_000_000n; -const CENT = IST_UNIT / 100n; - -/** - * Make a storage node for auxilliary data for a value on the board. - * - * @param {ERef} chainStorage - * @param {string} boardId - */ -const makeBoardAuxNode = async (chainStorage, boardId) => { - const boardAux = E(chainStorage).makeChildNode(BOARD_AUX); - return E(boardAux).makeChildNode(boardId); -}; - -const publishBrandInfo = async (chainStorage, board, brand) => { - const [id, displayInfo] = await Promise.all([ - E(board).getId(brand), - E(brand).getDisplayInfo(), - ]); - const node = makeBoardAuxNode(chainStorage, id); - const aux = marshalData.toCapData(harden({ displayInfo })); - await E(node).setValue(JSON.stringify(aux)); -}; - -/** - * Core eval script to start contract - * - * @param {BootstrapPowers} permittedPowers - */ -export const startGameContract = async permittedPowers => { - console.error('@@@startGameContract()...'); - const { - consume: { agoricNames, board, chainStorage, startUpgradable, zoe }, - brand: { - // @ts-expect-error dynamic extension to promise space - produce: { Place: producePlaceBrand }, - }, - issuer: { - // @ts-expect-error dynamic extension to promise space - produce: { Place: producePlaceIssuer }, - }, - instance: { - // @ts-expect-error dynamic extension to promise space - produce: { game1: produceInstance }, - }, - } = permittedPowers; - - const istBrand = await E(agoricNames).lookup('brand', 'IST'); - const ist = { - brand: istBrand, - }; - // NOTE: joinPrice could be configurable - const terms = { joinPrice: makeAmount(ist.brand, 25n * CENT) }; - - // agoricNames gets updated each time; the promise space only once XXXXXXX - const installation = await E(agoricNames).lookup('installation', 'game1'); - - const { instance } = await E(startUpgradable)({ - installation, - label: 'game1', - terms, - }); - console.log('CoreEval script: started game contract', instance); - const { - brands: { Place: brand }, - issuers: { Place: issuer }, - } = await E(zoe).getTerms(instance); - - console.log('CoreEval script: share via agoricNames:', brand); - - produceInstance.reset(); - produceInstance.resolve(instance); - - producePlaceBrand.reset(); - producePlaceIssuer.reset(); - producePlaceBrand.resolve(brand); - producePlaceIssuer.resolve(issuer); - - await publishBrandInfo(chainStorage, board, brand); - console.log('game1 (re)installed'); -}; - -/** @type { import("@agoric/vats/src/core/lib-boot").BootstrapManifest } */ -const gameManifest = { - [startGameContract.name]: { - // include rationale for closely-held, high authority capabilities - consume: { - agoricNames: true, - board: 'to publish boardAux info for game NFT', - chainStorage: 'to publish boardAux info for game NFT', - startUpgradable: 'to start contract and save adminFacet', - zoe: 'to get contract terms, including issuer/brand', - }, - installation: { consume: { game1: true } }, - issuer: { produce: { Place: true } }, - brand: { produce: { Place: true } }, - instance: { produce: { game1: true } }, - }, -}; -harden(manifest); - -export const getManifestForGame1 = ({ restoreRef }, { game1Ref }) => { - return harden({ - manifest: gameManifest, - installations: { - game1: restoreRef(game1Ref), - }, - }); -}; diff --git a/packages/smart-wallet/test/start-game1-proposal.js b/packages/smart-wallet/test/start-game1-proposal.js new file mode 100644 index 000000000000..5b1459bc0eb6 --- /dev/null +++ b/packages/smart-wallet/test/start-game1-proposal.js @@ -0,0 +1,125 @@ +// @ts-check +import { E } from '@endo/far'; +import { makeMarshal } from '@endo/marshal'; + +console.warn('start-game1-proposal.js module evaluating'); + +const { Fail } = assert; + +// vstorage paths under published.* +const WALLET_STORAGE_PATH_SEGMENT = 'wallet'; +const BOARD_AUX = 'boardAux'; + +const marshalData = makeMarshal(_val => Fail`data only`); + +// avoid importing all of ERTP +const makeAmount = (brand, value) => harden({ brand, value }); + +const IST_UNIT = 1_000_000n; +const CENT = IST_UNIT / 100n; + +/** + * Make a storage node for auxilliary data for a value on the board. + * + * @param {ERef} chainStorage + * @param {string} boardId + */ +const makeBoardAuxNode = async (chainStorage, boardId) => { + const boardAux = E(chainStorage).makeChildNode(BOARD_AUX); + return E(boardAux).makeChildNode(boardId); +}; + +const publishBrandInfo = async (chainStorage, board, brand) => { + const [id, displayInfo] = await Promise.all([ + E(board).getId(brand), + E(brand).getDisplayInfo(), + ]); + const node = makeBoardAuxNode(chainStorage, id); + const aux = marshalData.toCapData(harden({ displayInfo })); + await E(node).setValue(JSON.stringify(aux)); +}; + +/** + * Core eval script to start contract + * + * @param {BootstrapPowers} permittedPowers + */ +export const startGameContract = async permittedPowers => { + console.error('startGameContract()...'); + const { + consume: { agoricNames, board, chainStorage, startUpgradable, zoe }, + brand: { + // @ts-expect-error dynamic extension to promise space + produce: { Place: producePlaceBrand }, + }, + issuer: { + // @ts-expect-error dynamic extension to promise space + produce: { Place: producePlaceIssuer }, + }, + instance: { + // @ts-expect-error dynamic extension to promise space + produce: { game1: produceInstance }, + }, + } = permittedPowers; + + const istBrand = await E(agoricNames).lookup('brand', 'IST'); + const ist = { + brand: istBrand, + }; + // NOTE: joinPrice could be configurable + const terms = { joinPrice: makeAmount(ist.brand, 25n * CENT) }; + + // agoricNames gets updated each time; the promise space only once XXXXXXX + const installation = await E(agoricNames).lookup('installation', 'game1'); + + const { instance } = await E(startUpgradable)({ + installation, + label: 'game1', + terms, + }); + console.log('CoreEval script: started game contract', instance); + const { + brands: { Place: brand }, + issuers: { Place: issuer }, + } = await E(zoe).getTerms(instance); + + console.log('CoreEval script: share via agoricNames:', brand); + + produceInstance.reset(); + produceInstance.resolve(instance); + + producePlaceBrand.reset(); + producePlaceIssuer.reset(); + producePlaceBrand.resolve(brand); + producePlaceIssuer.resolve(issuer); + + await publishBrandInfo(chainStorage, board, brand); + console.log('game1 (re)installed'); +}; + +/** @type { import("@agoric/vats/src/core/lib-boot").BootstrapManifest } */ +const gameManifest = { + [startGameContract.name]: { + consume: { + agoricNames: true, + board: true, // to publish boardAux info for game NFT + chainStorage: true, // to publish boardAux info for game NFT + startUpgradable: true, // to start contract and save adminFacet + zoe: true, // to get contract terms, including issuer/brand + }, + installation: { consume: { game1: true } }, + issuer: { produce: { Place: true } }, + brand: { produce: { Place: true } }, + instance: { produce: { game1: true } }, + }, +}; +harden(gameManifest); + +export const getManifestForGame1 = ({ restoreRef }, { game1Ref }) => { + return harden({ + manifest: gameManifest, + installations: { + game1: restoreRef(game1Ref), + }, + }); +};