From f582901fb3835d95d493c777aac6a63fc3ee4681 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Mon, 31 Jul 2023 22:55:58 -0600 Subject: [PATCH 01/35] fix(vibc): accommodate ibc-go v3 breaking changes --- golang/cosmos/x/vibc/keeper/keeper.go | 16 +--------------- golang/cosmos/x/vibc/types/expected_keepers.go | 3 ++- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/golang/cosmos/x/vibc/keeper/keeper.go b/golang/cosmos/x/vibc/keeper/keeper.go index cd0329498ec..465b171c2e0 100644 --- a/golang/cosmos/x/vibc/keeper/keeper.go +++ b/golang/cosmos/x/vibc/keeper/keeper.go @@ -92,13 +92,7 @@ func (k Keeper) ChanOpenInit(ctx sdk.Context, order channeltypes.Order, connecti return err } - // We need to emit a channel event to notify the relayer. - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, channeltypes.AttributeValueCategory), - ), - }) + k.channelKeeper.WriteOpenInitChannel(ctx, portID, channelID, order, connectionHops, counterparty, version) return nil } @@ -157,14 +151,6 @@ func (k Keeper) ChanCloseInit(ctx sdk.Context, portID, channelID string) error { if err != nil { return err } - - // We need to emit a channel event to notify the relayer. - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, channeltypes.AttributeValueCategory), - ), - }) return nil } diff --git a/golang/cosmos/x/vibc/types/expected_keepers.go b/golang/cosmos/x/vibc/types/expected_keepers.go index 6967e7dca4c..49dc2953ff6 100644 --- a/golang/cosmos/x/vibc/types/expected_keepers.go +++ b/golang/cosmos/x/vibc/types/expected_keepers.go @@ -16,7 +16,8 @@ type ChannelKeeper interface { WriteAcknowledgement(ctx sdk.Context, channelCap *capability.Capability, packet ibcexported.PacketI, acknowledgement ibcexported.Acknowledgement) error ChanOpenInit(ctx sdk.Context, order channel.Order, connectionHops []string, portID string, portCap *capability.Capability, counterparty channel.Counterparty, version string) (string, *capability.Capability, error) - + WriteOpenInitChannel(ctx sdk.Context, portID, channelID string, order channel.Order, + connectionHops []string, counterparty channel.Counterparty, version string) ChanCloseInit(ctx sdk.Context, portID, channelID string, chanCap *capability.Capability) error TimeoutExecuted(ctx sdk.Context, channelCap *capability.Capability, packet ibcexported.PacketI) error } From 1ca6e848550e858bcffb11d09d165020cef190fe Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Wed, 2 Aug 2023 14:36:30 -0600 Subject: [PATCH 02/35] docs(SwingSet): remove mention of obsolete "need prompt ACK" for IBC network --- packages/SwingSet/docs/networking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SwingSet/docs/networking.md b/packages/SwingSet/docs/networking.md index 8e0345bb92d..bb71c5ea869 100644 --- a/packages/SwingSet/docs/networking.md +++ b/packages/SwingSet/docs/networking.md @@ -120,7 +120,7 @@ You can omit any of the methods and those events will simply be ignored. All the `onReceive()` is the most important method. Each time the remote end sends a packet, your `onReceive()` method will be called with the data inside that packet (currently as a String due to inter-vat marshalling limitations, but ideally as an ArrayBuffer with a custom `toString(encoding='latin1')` method so that it can contain arbitrary bytes). The return value of `onReceive()` is nominally a Promise for ACK data of the message (that will eventually appear on the other side as resolution of the Promise returned by `connection.send()`). -For IBC, this Promise must be resolved within the same block as receiving the message, and if it does not resolve (or resolves to an empty value `''`, which is not supported by [Cosmos ibc-go](https://github.com/cosmos/ibc-go)) then the implementation will automatically send a trivial `'\x01'` ACK. This behavior may be different for other network implementations. +For IBC, if the ACK data settles to an empty value `''` then the implementation will automatically send a trivial `'\x01'` ACK, because empty ACKs are not supported by [Cosmos ibc-go](https://github.com/cosmos/ibc-go). This behavior may be different for other network implementations. It is recommended to avoid ACK data where possible. ## Closing the Connection From 946997192cec0ed6b07fdaa18d8f380f460ab004 Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Wed, 2 Aug 2023 16:08:55 -0600 Subject: [PATCH 03/35] fix(vibc): put extraneous `CounterpartyChannelID` in `Counterparty` struct --- golang/cosmos/x/vibc/ibc.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/golang/cosmos/x/vibc/ibc.go b/golang/cosmos/x/vibc/ibc.go index 5c3e990e635..a8a73e07ed1 100644 --- a/golang/cosmos/x/vibc/ibc.go +++ b/golang/cosmos/x/vibc/ibc.go @@ -228,7 +228,6 @@ type channelOpenAckEvent struct { Event string `json:"event"` // channelOpenAck PortID string `json:"portID"` ChannelID string `json:"channelID"` - CounterpartyChannelID string `json:"counterpartyChannelID"` CounterpartyVersion string `json:"counterpartyVersion"` Counterparty channeltypes.Counterparty `json:"counterparty"` ConnectionHops []string `json:"connectionHops"` @@ -247,12 +246,12 @@ func (im IBCModule) OnChanOpenAck( // returns an empty channel object that we can still use without crashing. channel, _ := im.keeper.GetChannel(ctx, portID, channelID) + channel.Counterparty.ChannelId = counterpartyChannelID event := channelOpenAckEvent{ Type: "IBC_EVENT", Event: "channelOpenAck", PortID: portID, ChannelID: channelID, - CounterpartyChannelID: counterpartyChannelID, CounterpartyVersion: counterpartyVersion, Counterparty: channel.Counterparty, ConnectionHops: channel.ConnectionHops, From 90b1a06cc6dfe1320005d3a17867108c2111a475 Mon Sep 17 00:00:00 2001 From: Ikenna Omekam Date: Thu, 17 Aug 2023 17:22:34 -0400 Subject: [PATCH 04/35] feat: port bash tests to javascript --- .eslintrc.cjs | 8 + packages/deployment/upgrade-test/Dockerfile | 4 +- .../agoric-upgrade-10/.keep | 0 .../agoric-upgrade-10/actions.mjs | 342 ++++++++++++++++++ .../agoric-upgrade-10/actions.sh | 201 ---------- .../agoric-upgrade-10/actions.test.js | 108 ++++++ .../agoric-upgrade-10/env_setup.sh | 156 -------- .../agoric-upgrade-10/legacy.sh | 85 +++++ .../param-change-offer-gen.mjs | 104 ------ .../agoric-upgrade-10/post.test.js | 70 ++++ .../agoric-upgrade-10/pre.test.js | 216 +++++++++++ .../agoric-upgrade-10/pre_test.sh | 80 ---- .../agoric-upgrade-10/test.sh | 45 --- .../agoric-upgrade-10/upgradeHelpers.mjs | 76 ++++ .../upgrade-test-scripts/cliHelper.mjs | 110 ++++++ .../upgrade-test-scripts/constants.mjs | 14 + .../coreUpgradeHelpers.mjs | 133 +++++++ .../upgrade-test-scripts/env_setup.sh | 0 .../upgrade-test-scripts/package.json | 20 + .../upgrade-test-scripts/start_to_to.sh | 15 +- 20 files changed, 1196 insertions(+), 591 deletions(-) delete mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/.keep create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.mjs delete mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.sh create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.test.js delete mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/env_setup.sh create mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/legacy.sh delete mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/param-change-offer-gen.mjs create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/post.test.js create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre.test.js delete mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre_test.sh delete mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/test.sh create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/upgradeHelpers.mjs create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/cliHelper.mjs create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/constants.mjs create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/coreUpgradeHelpers.mjs mode change 100644 => 100755 packages/deployment/upgrade-test/upgrade-test-scripts/env_setup.sh create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/package.json diff --git a/.eslintrc.cjs b/.eslintrc.cjs index a5a24ebb559..73043157427 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -119,5 +119,13 @@ module.exports = { project: false, }, }, + { + files: ['packages/**/upgrade-test-scripts/**/*.*js'], + rules: { + // NOTE: This rule is enabled for the repository in general. We turn it + // off for test code for now. + '@jessie.js/safe-await-separator': 'off', + }, + }, ], }; diff --git a/packages/deployment/upgrade-test/Dockerfile b/packages/deployment/upgrade-test/Dockerfile index 6ef270a54e3..ed8eb49b131 100644 --- a/packages/deployment/upgrade-test/Dockerfile +++ b/packages/deployment/upgrade-test/Dockerfile @@ -60,10 +60,10 @@ ARG DEST_IMAGE #this is agoric-upgrade-10 / vaults FROM ghcr.io/agoric/agoric-sdk:35 as agoric-upgrade-10 ARG BOOTSTRAP_MODE -ENV THIS_NAME=agoric-upgrade-10 BOOTSTRAP_MODE=${BOOTSTRAP_MODE} +ENV THIS_NAME=agoric-upgrade-10 USE_JS=1 BOOTSTRAP_MODE=${BOOTSTRAP_MODE} WORKDIR /usr/src/agoric-sdk/ -COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./upgrade-test-scripts/ +COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./package.json ./*.mjs ./upgrade-test-scripts/ COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ COPY --from=agoric-upgrade-9 /root/.agoric /root/.agoric RUN chmod +x ./upgrade-test-scripts/*.sh diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/.keep b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/.keep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.mjs new file mode 100644 index 00000000000..2d0c654da28 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.mjs @@ -0,0 +1,342 @@ +import { promises as fs } from 'fs'; +import assert from 'assert'; + +import { + waitForBlock, + provisionSmartWallet, + getUser, + executeOffer, +} from './upgradeHelpers.mjs'; +import { + agd, + agoric, + agops, + agopsLocation, + executeCommand, +} from '../cliHelper.mjs'; +import { + HOME, + ATOM_DENOM, + GOV1ADDR, + GOV2ADDR, + GOV3ADDR, +} from '../constants.mjs'; + +const govAccounts = [GOV1ADDR, GOV2ADDR, GOV3ADDR]; + +const acceptEC = async () => { + console.log('ACTIONS Tickling the wallets so they are revived'); + + let voter = 0; + for (const account of govAccounts) { + console.log(`${account}: 1: Accepting EC Committee`); + + try { + const params = ['ec', 'committee', '--send-from', account]; + await executeCommand(agopsLocation, params, { + timeout: 30000, + }); + } catch (error) { + console.warn(error.message); + } + + await waitForBlock(3); + + console.log(`${account}: 2: Accepting EC Committee`); + + try { + await agops.ec('committee', '--send-from', account, '--voter', voter); + } catch (error) { + console.warn(error.message); + } + + voter += 1; + + await waitForBlock(3); + + console.log(`${account}: Accepting EC Charter`); + + try { + await agops.ec('charter', '--send-from', account); + } catch (error) { + console.warn(error.message); + } + } +}; + +const acceptOracles = oracles => { + const promiseArray = []; + + for (const oracle of oracles) { + console.log(`${oracle.address}: Accept oracle invitations`); + promiseArray.push( + executeOffer( + oracle.address, + agops.oracle('accept', '--offerId', oracle.id), + ), + ); + } + + return Promise.all(promiseArray); +}; + +const proposeNewAuctionParams = async ( + address, + startFequency, + clockStep, + priceLockPeriod, +) => { + const charterAcceptOfferId = await agops.ec( + 'find-continuing-id', + '--for', + `${'charter\\ member\\ invitation'}`, + '--from', + address, + ); + + return executeOffer( + address, + agops.auctioneer( + 'proposeParamChange', + '--charterAcceptOfferId', + charterAcceptOfferId, + '--start-frequency', + startFequency, + '--clock-step', + clockStep, + '--price-lock-period', + priceLockPeriod, + ), + ); +}; + +const voteForNewParams = (accounts, position) => { + return Promise.all( + accounts.map(account => + agops.ec('vote', '--forPosition', position, '--send-from', account), + ), + ); +}; + +const paramChangeOfferGeneration = async ( + previousOfferId, + voteDur, + debtLimit, +) => { + const ISTunit = 1_000_000n; // aka displayInfo: { decimalPlaces: 6 } + const voteDurSec = BigInt(voteDur); + const debtLimitValue = BigInt(debtLimit) * ISTunit; + const toSec = ms => BigInt(Math.round(ms / 1000)); + + const id = `propose-${Date.now()}`; + const deadline = toSec(Date.now()) + voteDurSec; + + const zip = (xs, ys) => xs.map((x, i) => [x, ys[i]]); + const fromSmallCapsEntries = txt => { + const { body, slots } = JSON.parse(txt); + const theEntries = zip(JSON.parse(body.slice(1)), slots).map( + ([[name, ref], boardID]) => { + const iface = ref.replace(/^\$\d+\./, ''); + return [name, { iface, boardID }]; + }, + ); + return Object.fromEntries(theEntries); + }; + + const slots = []; // XXX global mutable state + const smallCaps = { + Nat: n => `+${n}`, + // XXX mutates obj + ref: obj => { + if (obj.ix) return obj.ix; + const ix = slots.length; + slots.push(obj.boardID); + obj.ix = `$${ix}.Alleged: ${obj.iface}`; + return obj.ix; + }, + }; + + const instance = fromSmallCapsEntries( + await agoric.follow('-lF', ':published.agoricNames.instance', '-o', 'text'), + ); + assert(instance.VaultFactory); + + const brand = fromSmallCapsEntries( + await agoric.follow('-lF', ':published.agoricNames.brand', '-o', 'text'), + ); + assert(brand.IST); + assert(brand.ATOM); + + const body = { + method: 'executeOffer', + offer: { + id, + invitationSpec: { + invitationMakerName: 'VoteOnParamChange', + previousOffer: previousOfferId, + source: 'continuing', + }, + offerArgs: { + deadline: smallCaps.Nat(deadline), + instance: smallCaps.ref(instance.VaultFactory), + params: { + DebtLimit: { + brand: smallCaps.ref(brand.IST), + value: smallCaps.Nat(debtLimitValue), + }, + }, + path: { + paramPath: { + key: { + collateralBrand: smallCaps.ref(brand.ATOM), + }, + }, + }, + }, + proposal: {}, + }, + }; + + const capData = { body: `#${JSON.stringify(body)}`, slots }; + return JSON.stringify(capData); +}; + +export const provisionWallet = async user => { + const userKeyData = await agd.keys('add', user, '--keyring-backend=test'); + await fs.writeFile(`${HOME}/.agoric/${user}.key`, userKeyData.mnemonic); + + const userAddress = await getUser(user); + + await provisionSmartWallet( + userAddress, + `20000000ubld,100000000${ATOM_DENOM}`, + ); + await waitForBlock(); +}; + +export const implementNewAuctionParams = async ( + address, + oracles, + startFequency, + clockStep, + priceLockPeriod, +) => { + await acceptEC(); + await waitForBlock(3); + + await acceptOracles(oracles); + + await proposeNewAuctionParams( + address, + startFequency, + clockStep, + priceLockPeriod, + ); + + console.log('ACTIONS voting for new auction params'); + await voteForNewParams(govAccounts, 0); + + console.log('ACTIONS wait for the vote deadline to pass'); + await new Promise(r => setTimeout(r, 65000)); +}; + +export const proposeNewDebtCeiling = async address => { + const charterAcceptOfferId = await agops.ec( + 'find-continuing-id', + '--for', + `${'charter\\ member\\ invitation'}`, + '--from', + address, + ); + + return executeOffer( + address, + paramChangeOfferGeneration(charterAcceptOfferId, 30, 123000000), + ); +}; + +export const raiseDebtCeiling = async address => { + console.log('ACTIONS Raising debt limit'); + + await proposeNewDebtCeiling(address); + await voteForNewParams(govAccounts, 0); + + console.log('ACTIONS wait for the vote to pass'); + await new Promise(r => setTimeout(r, 65000)); +}; + +export const openVault = (address, mint, collateral) => { + return executeOffer( + address, + agops.vaults('open', '--wantMinted', mint, '--giveCollateral', collateral), + ); +}; + +export const adjustVault = (address, vaultId, vaultParams) => { + let params = [ + 'adjust', + '--vaultId', + vaultId, + '--from', + address, + ' --keyring-backend=test', + ]; + + if ('wantCollateral' in vaultParams) { + params = [...params, '--wantCollateral', vaultParams.wantCollateral]; + } + + if ('wantMinted' in vaultParams) { + params = [...params, '--wantMinted', vaultParams.wantMinted]; + } + + if ('giveCollateral' in vaultParams) { + params = [...params, '--giveCollateral', vaultParams.giveCollateral]; + } + + if ('giveMinted' in vaultParams) { + params = [...params, '--giveMinted', vaultParams.giveMinted]; + } + + return executeOffer(address, agops.vaults(...params)); +}; + +export const closeVault = (address, vaultId, mint) => { + return executeOffer( + address, + agops.vaults( + 'close', + '--vaultId', + vaultId, + '--giveMinted', + mint, + '--from', + address, + '--keyring-backend=test', + ), + ); +}; + +export const pushPrice = (oracles, price = 10.0) => { + console.log(`ACTIONS pushPrice ${price}`); + const promiseArray = []; + + for (const oracle of oracles) { + console.log(`Pushing Price from oracle ${oracle.address}`); + + promiseArray.push( + executeOffer( + oracle.address, + agops.oracle( + 'pushPriceRound', + '--price', + price, + '--oracleAdminAcceptOfferId', + oracle.id, + ), + ), + ); + } + + return Promise.all(promiseArray); +}; diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.sh deleted file mode 100644 index cc53553a99b..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.sh +++ /dev/null @@ -1,201 +0,0 @@ -#!/bin/bash - -. ./upgrade-test-scripts/env_setup.sh - -# Enable debugging -set -x - -# For development: -# TARGET=agoric-upgrade-10 make local_sdk build_test run -# agoric wallet show --from $GOV1ADDR -waitForBlock 20 - -# user1 has no mailbox provisioned; later we test that this was discarded -submitDeliverInbound user1 - -# provision a new user wallet - -agd keys add user2 --keyring-backend=test 2>&1 | tee "$HOME/.agoric/user2.out" -cat "$HOME/.agoric/user2.out" | tail -n1 | tee "$HOME/.agoric/user2.key" -export USER2ADDR=$($binary keys show user2 -a --keyring-backend="test" 2> /dev/null) -provisionSmartWallet $USER2ADDR "20000000ubld,100000000${ATOM_DENOM}" -waitForBlock - -test_not_val "$(agd q vstorage data published.wallet.$USER2ADDR -o json | jq -r .value)" "" "ensure user2 provisioned" - -echo "ACTIONS Tickling the wallets so they are revived" -# Until they are revived, the invitations can't be deposited. So the first action can't be to accept an invitation (because it won't be there). -govaccounts=("$GOV1ADDR" "$GOV2ADDR" "$GOV3ADDR") -cm=0 -for i in "${govaccounts[@]}"; do - for run in {1..2}; do - echo "$i: $run: Accepting EC Committee" - if [[ "$run" == "1" ]]; then - timeout 3 yarn run --silent agops ec committee --send-from "$i" || true - else - agops ec committee --send-from "$i" --voter "$cm" - cm=$((cm + 1)) - fi - waitForBlock 3 - done - echo "$i: Accepting EC Charter" - agops ec charter --send-from "$i" -done - -waitForBlock 3 - -oracles=("$GOV1ADDR" "$GOV2ADDR") -for i in "${oracles[@]}"; do - echo "$i: Accept oracle invitations" - ORACLE_OFFER=$(mktemp -t agops.XXX) - OFFER_ID="$(newOfferId)" - agops oracle accept --offerId "$OFFER_ID" >|"$ORACLE_OFFER" - agoric wallet print --file "$ORACLE_OFFER" - agops perf satisfaction --from "$i" --executeOffer "$ORACLE_OFFER" --keyring-backend=test - echo "${i}_ORACLE=$OFFER_ID" >>"$HOME/.agoric/envs" -done - -echo ACTIONS Sourcing environment -source "$HOME/.agoric/envs" - -echo ACTIONS proposing new auction params -START_FREQUENCY=600 #StartFrequency: 600s (auction runs every 10m) -CLOCK_STEP=20 #ClockStep: 20s (ensures auction completes in time) -PRICE_LOCK_PERIOD=300 - -FASTER_AUCTIONS_OFFER=$(mktemp -t agops.XXX) -agops auctioneer proposeParamChange --charterAcceptOfferId "$(agops ec find-continuing-id --for "charter member invitation" --from "$GOV1ADDR")" --start-frequency $START_FREQUENCY --clock-step $CLOCK_STEP --price-lock-period $PRICE_LOCK_PERIOD >|"$FASTER_AUCTIONS_OFFER" -agoric wallet print --file "$FASTER_AUCTIONS_OFFER" -agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$FASTER_AUCTIONS_OFFER" --keyring-backend=test - -echo ACTIONS voting for new auction params -govaccounts=("$GOV1ADDR" "$GOV2ADDR" "$GOV3ADDR") -for i in "${govaccounts[@]}"; do - agops ec vote --forPosition 0 --send-from "$i" -done - -echo ACTIONS wait for the vote deadline to pass -sleep 65 - -echo ACTIONS ensuring params were changed -test_val "$(agoric follow -l -F :published.auction.governance -o jsonlines | jq -r .current.ClockStep.value.relValue)" "$CLOCK_STEP" -test_val "$(agoric follow -l -F :published.auction.governance -o jsonlines | jq -r .current.StartFrequency.value.relValue)" "$START_FREQUENCY" - -##### -echo ACTIONS Raising debt limit -DEBT_LIMIT_OFFER=$(mktemp -t agops.XXX) -previous="$(agops ec find-continuing-id --for "charter member invitation" --from "$GOV1ADDR")" -node ./upgrade-test-scripts/agoric-upgrade-10/param-change-offer-gen.mjs $previous 30 123000000 >|"$DEBT_LIMIT_OFFER" -agoric wallet print --file "$DEBT_LIMIT_OFFER" -agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$DEBT_LIMIT_OFFER" --keyring-backend=test - -# wait for question to post. XXX right way is to check deadline of .latestQuestion -waitForBlock 3 - -govaccounts=("$GOV1ADDR" "$GOV2ADDR" "$GOV3ADDR") -for i in "${govaccounts[@]}"; do - agops ec vote --forPosition 0 --send-from "$i" -done - -echo ACTIONS wait for the vote to pass -sleep 65 - -echo ACTIONS ensure params were changed -test_val "$(agoric follow -l -F :published.vaultFactory.managers.manager0.governance -o jsonlines | jq -r .current.DebtLimit.value.value)" "123000000000000" - -pushPrice 12.01 - -## vaults -# attempt to open vaults under the minimum amount -for vid in {1..2}; do - OFFER=$(mktemp -t agops.XXX) - if [[ "$vid" == "2" ]]; then - amount=3.00 - collateral=5.0 - else - amount=2.00 - collateral=4.0 - fi - agops vaults open --wantMinted $amount --giveCollateral $collateral >|"$OFFER" - agoric wallet print --file "$OFFER" - agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$OFFER" --keyring-backend=test || true -done - -# we should still have no vaults -test_val "$(agops vaults list --from $GOV1ADDR)" "" "gov1 has no vaults" - -# open up some vaults -for vid in {1..2}; do - OFFER=$(mktemp -t agops.XXX) - if [[ "$vid" == "2" ]]; then - amount=6.00 - collateral=10.0 - else - amount=5.00 - collateral=9.0 - fi - agops vaults open --wantMinted $amount --giveCollateral $collateral >|"$OFFER" - agoric wallet print --file "$OFFER" - agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$OFFER" --keyring-backend=test -done - -# remove some collateral from the first vault -OFFER=$(mktemp -t agops.XXX) -agops vaults adjust --vaultId vault0 --wantCollateral 1.0 --from $GOV1ADDR --keyring-backend="test" >|"$OFFER" -agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$OFFER" --keyring-backend=test - -# take some IST from the first vault, increasing debt -OFFER=$(mktemp -t agops.XXX) -agops vaults adjust --vaultId vault0 --wantMinted 1.0 --from $GOV1ADDR --keyring-backend="test" >|"$OFFER" -agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$OFFER" --keyring-backend=test - -# close the second vault -OFFER=$(mktemp -t agops.XXX) -agops vaults close --vaultId vault1 --giveMinted 6.06 --from $GOV1ADDR --keyring-backend="test" >|"$OFFER" -agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$OFFER" --keyring-backend=test - -# make sure the same works for user2 -OFFER=$(mktemp -t agops.XXX) -agops vaults open --wantMinted 7.00 --giveCollateral 11.0 >|"$OFFER" -agops perf satisfaction --from "$USER2ADDR" --executeOffer "$OFFER" --keyring-backend=test - -# put some IST in -OFFER=$(mktemp -t agops.XXX) -agops vaults adjust --vaultId vault2 --giveMinted 1.5 --from $USER2ADDR --keyring-backend=test >|"$OFFER" -agops perf satisfaction --from "$USER2ADDR" --executeOffer "$OFFER" --keyring-backend=test - -# add some collateral -OFFER=$(mktemp -t agops.XXX) -agops vaults adjust --vaultId vault2 --giveCollateral 2.0 --from $USER2ADDR --keyring-backend="test" >|"$OFFER" -agops perf satisfaction --from "$USER2ADDR" --executeOffer "$OFFER" --keyring-backend=test - -# close out -OFFER=$(mktemp -t agops.XXX) -agops vaults close --vaultId vault2 --giveMinted 5.75 --from $USER2ADDR --keyring-backend="test" >|"$OFFER" -agops perf satisfaction --from "$USER2ADDR" --executeOffer "$OFFER" --keyring-backend=test - -# replicate state-sync of node -# this will cause the swing-store to prune some data -# we will save the pruned artifact for later -killAgd -EXPORT_DIR=$(mktemp -t -d swing-store-export-upgrade-10-XXX) -make_swing_store_snapshot $EXPORT_DIR || fail "Couldn't make swing-store snapshot" -test_val "$(compare_swing_store_export_data $EXPORT_DIR)" "match" "swing-store export data" -EXPORT_DIR_ALL_ARTIFACTS=$(mktemp -t -d swing-store-export-upgrade-10-all-artifacts-XXX) -make_swing_store_snapshot $EXPORT_DIR_ALL_ARTIFACTS --export-mode archival || fail "Couldn't make swing-store snapshot for historical artifacts" -restore_swing_store_snapshot $EXPORT_DIR || fail "Couldn't restore swing-store snapshot" -( - cd $EXPORT_DIR_ALL_ARTIFACTS - mkdir $HOME/.agoric/data/agoric/swing-store-historical-artifacts - for i in *; do - [ -f $EXPORT_DIR/$i ] && continue - mv $i $HOME/.agoric/data/agoric/swing-store-historical-artifacts/ - done -) -rm -rf $EXPORT_DIR -rm -rf $EXPORT_DIR_ALL_ARTIFACTS -startAgd - -# # TODO fully test bidding -# # TODO test liquidations -agops inter bid by-price --price 1 --give 1.0IST --from $GOV1ADDR --keyring-backend test diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.test.js new file mode 100644 index 00000000000..2fcec2ab6ed --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.test.js @@ -0,0 +1,108 @@ +import test from 'ava'; + +import { + waitForBlock, + submitDeliverInbound, + getUser, + newOfferId, +} from './upgradeHelpers.mjs'; +import { + provisionWallet, + implementNewAuctionParams, + raiseDebtCeiling, + openVault, + adjustVault, + closeVault, + pushPrice, +} from './actions.mjs'; +import { agd, agoric, agops } from '../cliHelper.mjs'; +import { GOV1ADDR, GOV2ADDR } from '../constants.mjs'; + +const START_FREQUENCY = 600; // StartFrequency: 600s (auction runs every 10m) +const CLOCK_STEP = 20; // ClockStep: 20s (ensures auction completes in time) +const PRICE_LOCK_PERIOD = 300; +const oraclesAddresses = [GOV1ADDR, GOV2ADDR]; + +test.before(async t => { + await waitForBlock(2); + await submitDeliverInbound('user1'); + + const oracles = []; + for (const oracle of oraclesAddresses) { + const offerId = await newOfferId(); + oracles.push({ address: oracle, id: offerId }); + } + + t.context.oracles = oracles; +}); + +test.serial('Ensure user2 provisioned', async t => { + await provisionWallet('user2'); + + const user2Address = await getUser('user2'); + const data = await agd.query( + 'vstorage', + 'data', + `published.wallet.${user2Address}`, + ); + + t.not(data.value, ''); +}); + +test.serial('Ensure auction params have changed', async t => { + await implementNewAuctionParams( + GOV1ADDR, + t.context.oracles, + START_FREQUENCY, + CLOCK_STEP, + PRICE_LOCK_PERIOD, + ); + + const govParams = await agoric.follow('-lF', ':published.auction.governance'); + t.is(govParams.current.ClockStep.value.relValue, CLOCK_STEP.toString()); + t.is( + govParams.current.StartFrequency.value.relValue, + START_FREQUENCY.toString(), + ); +}); + +test.serial('Ensure debt ceiling raised', async t => { + await raiseDebtCeiling(GOV1ADDR); + const params = await agoric.follow( + '-lF', + ':published.vaultFactory.managers.manager0.governance', + ); + t.is(params.current.DebtLimit.value.value, '123000000000000'); +}); + +test.serial('Update oracle prices', async t => { + await pushPrice(t.context.oracles, 12.01); + + t.pass(); +}); + +test.serial('Open Vaults', async t => { + const currentVaults = await agops.vaults('list', '--from', GOV1ADDR); + t.is(currentVaults.length, 0); + + const vaults = [ + { mint: 5.0, collateral: 9.0 }, + { mint: 6.0, collateral: 10.0 }, + ]; + + for (const vault of vaults) { + await openVault(GOV1ADDR, vault.mint, vault.collateral); + } + + await adjustVault(GOV1ADDR, 'vault0', { wantCollateral: 1.0 }); + await adjustVault(GOV1ADDR, 'vault0', { wantMinted: 1.0 }); + await closeVault(GOV1ADDR, 'vault1', 6.06); + + const user2 = await getUser('user2'); + await openVault(user2, 7, 11); + await adjustVault(user2, 'vault2', { giveMinted: 1.5 }); + await adjustVault(user2, 'vault2', { giveCollateral: 2.0 }); + await closeVault(user2, 'vault2', 5.75); + + t.pass(); +}); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/env_setup.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/env_setup.sh deleted file mode 100644 index 22d6425887f..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/env_setup.sh +++ /dev/null @@ -1,156 +0,0 @@ -#!/bin/bash - -# agoric-upgrade-10 specific env here... -export USER2ADDR=$($binary keys show user2 -a --keyring-backend="test" 2> /dev/null) - -printKeys() { - echo "========== GOVERNANCE KEYS ==========" - echo "gov1: $GOV1ADDR" - cat ~/.agoric/gov1.key || true - echo "gov2: $GOV2ADDR" - cat ~/.agoric/gov2.key || true - echo "gov3: $GOV3ADDR" - cat ~/.agoric/gov3.key || true - echo "validator: $VALIDATORADDR" - cat ~/.agoric/validator.key || true - echo "user1: $USER1ADDR" - cat ~/.agoric/user1.key || true - echo "user2: $USER2ADDR" - cat ~/.agoric/user2.key || true - echo "========== GOVERNANCE KEYS ==========" -} - -pushPrice () { - echo ACTIONS pushPrice $1 - newPrice="${1:-10.00}" - for oracleNum in {1..2}; do - if [[ ! -e "$HOME/.agoric/lastOracle" ]]; then - echo "$GOV1ADDR" > "$HOME/.agoric/lastOracle" - fi - - lastOracle=$(cat "$HOME/.agoric/lastOracle") - nextOracle="$GOV1ADDR" - if [[ "$lastOracle" == "$GOV1ADDR" ]]; then - nextOracle="$GOV2ADDR" - fi - echo "Pushing Price from oracle $nextOracle" - - oid="${nextOracle}_ORACLE" - offer=$(mktemp -t pushPrice.XXX) - agops oracle pushPriceRound --price "$newPrice" --oracleAdminAcceptOfferId "${!oid}" >|"$offer" - sleep 1 - timeout --preserve-status 15 yarn run --silent agops perf satisfaction --from $nextOracle --executeOffer "$offer" --keyring-backend test - if [ $? -ne 0 ]; then - echo "WARNING: pushPrice for $nextOracle failed!" - fi - echo "$nextOracle" > "$HOME/.agoric/lastOracle" - done -} - - -# variant of pushPrice() that figures out which oracle to send from -# WIP because it doesn't always work -pushPriceOnce () { - echo ACTIONS pushPrice $1 - newPrice="${1:-10.00}" - timeout 3 agoric follow -lF :published.priceFeed.ATOM-USD_price_feed.latestRound -ojson > "$HOME/.agoric/latestRound-ATOM.json" - - lastStartedBy=$(jq -r .startedBy "$HOME/.agoric/latestRound-ATOM.json" || echo null) - echo lastStartedBy $lastStartedBy - nextOracle="ERROR" - # cycle to next among oracles (first of the two governance accounts) - case $lastStartedBy in - "$GOV1ADDR") nextOracle=$GOV2ADDR;; - "$GOV2ADDR") nextOracle=$GOV1ADDR;; - *) - echo last price was pushed by a different account, using GOV1 - nextOracle=$GOV1ADDR - ;; - esac - echo nextOracle $nextOracle - - adminOfferId="${nextOracle}_ORACLE" - - echo "Pushing Price from oracle $nextOracle with offer $adminOfferId" - - offer=$(mktemp -t pushPrice.XXX) - agops oracle pushPriceRound --price "$newPrice" --oracleAdminAcceptOfferId "${adminOfferId}" >|"$offer" - cat "$offer" - sleep 1 - timeout --preserve-status 15 yarn run --silent agops perf satisfaction --from $nextOracle --executeOffer "$offer" --keyring-backend test - if [ $? -eq 0 ]; then - echo SUCCESS - else - echo "ERROR: pushPrice failed (using $nextOracle)" - fi -} - -# submit a DeliverInbound transaction -# -# see {agoric.swingset.MsgDeliverInbound} in swingset/msgs.proto -# https://github.com/Agoric/agoric-sdk/blob/5cc5ec8836dcd0c6e11b10799966b6e74601295d/golang/cosmos/proto/agoric/swingset/msgs.proto#L23 -submitDeliverInbound() { - sender="${1:-user1}" - - # ag-solo is a client that sends DeliverInbound transactions using a golang client - # @see {connectToChain} in chain-cosmos-sdk.js - # runHelper - # https://github.com/Agoric/agoric-sdk/blob/5cc5ec8836dcd0c6e11b10799966b6e74601295d/packages/solo/src/chain-cosmos-sdk.js - - # The payload is JSON.stringify([messages, highestAck]) - # https://github.com/Agoric/agoric-sdk/blob/5cc5ec8836dcd0c6e11b10799966b6e74601295d/packages/solo/src/chain-cosmos-sdk.js#L625 - # for example, this json was captured from a running `agoric start local-solo` - json='[[[1,"1:0:deliver:ro+1:rp-44;#[\"getConfiguration\",[]]"]],0]' - - agd tx swingset deliver "${json}" \ - --chain-id="$CHAINID" -ojson --yes \ - --from="$sender" --keyring-backend=test -b block -} - -make_swing_store_snapshot() {( set -euo pipefail - EXPORT_DIR="$1" - shift - /usr/src/agoric-sdk/packages/cosmic-swingset/src/export-kernel-db.js --home "$HOME/.agoric" --export-dir "$EXPORT_DIR" --verbose --include-export-data "$@" - - EXPORT_MANIFEST_FILE="$EXPORT_DIR/export-manifest.json" - EXPORT_DATA_FILE="$EXPORT_DIR/$(cat "$EXPORT_MANIFEST_FILE" | jq -r .data)" - EXPORT_DATA_UNTRUSTED_FILE="${EXPORT_DATA_FILE%.*}-untrusted.jsonl" - EXPORT_HEIGHT=$(cat "$EXPORT_MANIFEST_FILE" | jq -r .blockHeight) - EXPORT_MANIFEST="$(cat $EXPORT_MANIFEST_FILE)" - - mv "$EXPORT_DATA_FILE" "$EXPORT_DATA_UNTRUSTED_FILE" - agd export --height $EXPORT_HEIGHT | jq -cr '.app_state.vstorage.data[] | if .path | startswith("swingStore.") then [.path[11:],.value] else empty end' > "$EXPORT_DATA_FILE" - - jq -n "$EXPORT_MANIFEST | .untrustedData=\"$(basename -- "$EXPORT_DATA_UNTRUSTED_FILE")\"" > "$EXPORT_MANIFEST_FILE" - - echo "Successful swing-store export for block $EXPORT_HEIGHT" -)} - -restore_swing_store_snapshot() {( set -euo pipefail - rm -f $HOME/.agoric/data/agoric/swingstore.sqlite - - /usr/src/agoric-sdk/packages/cosmic-swingset/src/import-kernel-db.js --home "$HOME/.agoric" --export-dir "$1" --verbose -)} - -compare_swing_store_export_data() { - EXPORT_DIR="$1" - EXPORT_MANIFEST_FILE="$EXPORT_DIR/export-manifest.json" - EXPORT_DATA_FILE="$(cat "$EXPORT_MANIFEST_FILE" | jq -r .data)" - EXPORT_DATA_UNTRUSTED_FILE="$(cat "$EXPORT_MANIFEST_FILE" | jq -r .untrustedData)" - - if [ -z "$EXPORT_DATA_FILE" ]; then - echo "missing-export-data" - return - fi - - if [ -z "$EXPORT_DATA_UNTRUSTED_FILE" ]; then - echo "missing-untrusted-export-data" - return - fi - - diff <(cat "$EXPORT_DIR/$EXPORT_DATA_FILE" | sort) <(cat "$EXPORT_DIR/$EXPORT_DATA_UNTRUSTED_FILE" | sort) >&2 && { - echo "match" - } || { - echo "mismatch" - } -} diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/legacy.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/legacy.sh new file mode 100755 index 00000000000..1fadfd4804f --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/legacy.sh @@ -0,0 +1,85 @@ +#!/bin/bash +. /usr/src/agoric-sdk/upgrade-test-scripts/env_setup.sh + +make_swing_store_snapshot() {( set -euo pipefail + EXPORT_DIR="$1" + shift + /usr/src/agoric-sdk/packages/cosmic-swingset/src/export-kernel-db.js --home "$HOME/.agoric" --export-dir "$EXPORT_DIR" --verbose --include-export-data "$@" + + EXPORT_MANIFEST_FILE="$EXPORT_DIR/export-manifest.json" + EXPORT_DATA_FILE="$EXPORT_DIR/$(cat "$EXPORT_MANIFEST_FILE" | jq -r .data)" + EXPORT_DATA_UNTRUSTED_FILE="${EXPORT_DATA_FILE%.*}-untrusted.jsonl" + EXPORT_HEIGHT=$(cat "$EXPORT_MANIFEST_FILE" | jq -r .blockHeight) + EXPORT_MANIFEST="$(cat $EXPORT_MANIFEST_FILE)" + + mv "$EXPORT_DATA_FILE" "$EXPORT_DATA_UNTRUSTED_FILE" + agd export --height $EXPORT_HEIGHT | jq -cr '.app_state.vstorage.data[] | if .path | startswith("swingStore.") then [.path[11:],.value] else empty end' > "$EXPORT_DATA_FILE" + + jq -n "$EXPORT_MANIFEST | .untrustedData=\"$(basename -- "$EXPORT_DATA_UNTRUSTED_FILE")\"" > "$EXPORT_MANIFEST_FILE" + + echo "Successful swing-store export for block $EXPORT_HEIGHT" +)} + +restore_swing_store_snapshot() {( set -euo pipefail + rm -f $HOME/.agoric/data/agoric/swingstore.sqlite + + /usr/src/agoric-sdk/packages/cosmic-swingset/src/import-kernel-db.js --home "$HOME/.agoric" --export-dir "$1" --verbose +)} + +compare_swing_store_export_data() { + EXPORT_DIR="$1" + EXPORT_MANIFEST_FILE="$EXPORT_DIR/export-manifest.json" + EXPORT_DATA_FILE="$(cat "$EXPORT_MANIFEST_FILE" | jq -r .data)" + EXPORT_DATA_UNTRUSTED_FILE="$(cat "$EXPORT_MANIFEST_FILE" | jq -r .untrustedData)" + + if [ -z "$EXPORT_DATA_FILE" ]; then + echo "missing-export-data" + return + fi + + if [ -z "$EXPORT_DATA_UNTRUSTED_FILE" ]; then + echo "missing-untrusted-export-data" + return + fi + + diff <(cat "$EXPORT_DIR/$EXPORT_DATA_FILE" | sort) <(cat "$EXPORT_DIR/$EXPORT_DATA_UNTRUSTED_FILE" | sort) >&2 && { + echo "match" + } || { + echo "mismatch" + } +} + +# replicate state-sync of node +# this will cause the swing-store to prune some data +# we will save the pruned artifact for later +killAgd +EXPORT_DIR=$(mktemp -t -d swing-store-export-upgrade-10-XXX) +make_swing_store_snapshot $EXPORT_DIR || fail "Couldn't make swing-store snapshot" +# test_val "$(compare_swing_store_export_data $EXPORT_DIR)" "match" "swing-store export data" +EXPORT_DIR_ALL_ARTIFACTS=$(mktemp -t -d swing-store-export-upgrade-10-all-artifacts-XXX) +make_swing_store_snapshot $EXPORT_DIR_ALL_ARTIFACTS --export-mode archival || fail "Couldn't make swing-store snapshot for historical artifacts" +restore_swing_store_snapshot $EXPORT_DIR || fail "Couldn't restore swing-store snapshot" +( + cd $EXPORT_DIR_ALL_ARTIFACTS + mkdir $HOME/.agoric/data/agoric/swing-store-historical-artifacts + for i in *; do + [ -f $EXPORT_DIR/$i ] && continue + mv $i $HOME/.agoric/data/agoric/swing-store-historical-artifacts/ + done +) +rm -rf $EXPORT_DIR +rm -rf $EXPORT_DIR_ALL_ARTIFACTS + +startAgd +sleep 5 +killAgd + +EXPORT_DIR=$(mktemp -t -d swing-store-export-upgrade-10-XXX) +make_swing_store_snapshot $EXPORT_DIR || fail "Couldn't make swing-store snapshot" +test_val "$(compare_swing_store_export_data $EXPORT_DIR)" "mismatch" "swing-store broken state-sync" +rm -rf $EXPORT_DIR +startAgd + +# # TODO fully test bidding +# # TODO test liquidations +agops inter bid by-price --price 1 --give 1.0IST --from $GOV1ADDR --keyring-backend test \ No newline at end of file diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/param-change-offer-gen.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/param-change-offer-gen.mjs deleted file mode 100644 index a9e17895b6b..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/param-change-offer-gen.mjs +++ /dev/null @@ -1,104 +0,0 @@ -/* global process */ -import assert from 'assert'; -import { execFile } from 'child_process'; - -const ISTunit = 1_000_000n; // aka displayInfo: { decimalPlaces: 6 } - -const [_node, _script, previousOffer, voteDur, debtLimit] = process.argv; -assert(previousOffer, 'previousOffer is required'); -assert(voteDur, 'voteDur is required'); -assert(debtLimit, 'debtLimit is required'); -const voteDurSec = BigInt(voteDur); -const debtLimitValue = BigInt(debtLimit) * ISTunit; - -const toSec = ms => BigInt(Math.round(ms / 1000)); - -const id = `propose-${Date.now()}`; -const deadline = toSec(Date.now()) + voteDurSec; - -// look up boardIDs for brands, instances in agoricNames - -// poor-man's zx -const $ = cmd => { - console.error(cmd); - const [file, ...args] = cmd.split(' '); - - return new Promise((resolve, reject) => { - execFile(file, args, { encoding: 'utf8' }, (err, out) => { - if (err) return reject(err); - resolve(out); - }); - }); -}; - -const zip = (xs, ys) => xs.map((x, i) => [x, ys[i]]); -const fromSmallCapsEntries = txt => { - const { body, slots } = JSON.parse(txt); - const theEntries = zip(JSON.parse(body.slice(1)), slots).map( - ([[name, ref], boardID]) => { - const iface = ref.replace(/^\$\d+\./, ''); - return [name, { iface, boardID }]; - }, - ); - return Object.fromEntries(theEntries); -}; - -const instance = fromSmallCapsEntries( - await $('agoric follow -lF :published.agoricNames.instance -o text'), -); -assert(instance.VaultFactory); - -const brand = fromSmallCapsEntries( - await $('agoric follow -lF :published.agoricNames.brand -o text'), -); -assert(brand.IST); -assert(brand.ATOM); - -const slots = []; // XXX global mutable state - -const smallCaps = { - Nat: n => `+${n}`, - // XXX mutates obj - ref: obj => { - if (obj.ix) return obj.ix; - const ix = slots.length; - slots.push(obj.boardID); - obj.ix = `$${ix}.Alleged: ${obj.iface}`; - return obj.ix; - }, -}; - -const body = { - method: 'executeOffer', - offer: { - id, - invitationSpec: { - invitationMakerName: 'VoteOnParamChange', - previousOffer, - source: 'continuing', - }, - offerArgs: { - deadline: smallCaps.Nat(deadline), - instance: smallCaps.ref(instance.VaultFactory), - params: { - DebtLimit: { - brand: smallCaps.ref(brand.IST), - value: smallCaps.Nat(debtLimitValue), - }, - }, - path: { - paramPath: { - key: { - collateralBrand: smallCaps.ref(brand.ATOM), - }, - }, - }, - }, - proposal: {}, - }, -}; - -const capData = { body: `#${JSON.stringify(body)}`, slots }; -const action = JSON.stringify(capData); - -console.log(action); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/post.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/post.test.js new file mode 100644 index 00000000000..30ac69ca947 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/post.test.js @@ -0,0 +1,70 @@ +import test from 'ava'; + +import { agd, agoric } from '../cliHelper.mjs'; +import { GOV1ADDR, GOV2ADDR, GOV3ADDR, USER1ADDR } from '../constants.mjs'; +import { calculateWalletState } from './upgradeHelpers.mjs'; + +test('DeliverInbound from un-provisioned account is discarded', async t => { + const result = await agd.query('swingset', 'mailbox', USER1ADDR); + const value = JSON.parse(result.value); + t.is(value.outbox.length, 0); +}); + +test('provision pool has right balance', async t => { + const result = await agd.query( + 'bank', + 'balances', + 'agoric1megzytg65cyrgzs6fvzxgrcqvwwl7ugpt62346', + ); + t.is(result.balances[0].amount, '18750000'); +}); + +test('Validate wallet state', async t => { + t.is(await calculateWalletState(USER1ADDR), 'upgraded'); + t.is(await calculateWalletState(GOV1ADDR), 'revived'); + t.is(await calculateWalletState(GOV2ADDR), 'revived'); + t.is(await calculateWalletState(GOV3ADDR), 'revived'); +}); + +test('Validate vaults', async t => { + const vaults = await agd.query( + 'vstorage', + 'children', + 'published.vaultFactory.managers.manager0.vaults', + ); + + t.is(vaults.children.length, 3); + + const metrics = await agoric.follow( + '-lF', + ':published.vaultFactory.managers.manager0.metrics', + ); + + t.is(metrics.numActiveVaults, 1); + t.is(metrics.totalDebt.value, '6030000'); + t.is(metrics.totalCollateral.value, '8000000'); + + const vault0 = await agoric.follow( + '-lF', + ':published.vaultFactory.managers.manager0.vaults.vault0', + ); + t.is(vault0.vaultState, 'active'); + t.is(vault0.locked.value, '8000000'); + t.is(vault0.debtSnapshot.debt.value, '6030000'); + + const vault1 = await agoric.follow( + '-lF', + ':published.vaultFactory.managers.manager0.vaults.vault1', + ); + t.is(vault1.vaultState, 'closed'); + t.is(vault1.locked.value, '0'); + t.is(vault1.debtSnapshot.debt.value, '0'); + + const vault2 = await agoric.follow( + '-lF', + ':published.vaultFactory.managers.manager0.vaults.vault2', + ); + t.is(vault2.vaultState, 'closed'); + t.is(vault2.locked.value, '0'); + t.is(vault2.debtSnapshot.debt.value, '0'); +}); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre.test.js new file mode 100644 index 00000000000..9ce5aed434f --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre.test.js @@ -0,0 +1,216 @@ +import test from 'ava'; + +import { promises as fs } from 'fs'; + +import { waitForBlock, getUser } from './upgradeHelpers.mjs'; +import { agd, agoric, agops } from '../cliHelper.mjs'; + +import { + GOV1ADDR, + GOV2ADDR, + GOV3ADDR, + BOOTSTRAP_MODE, + PSM_PAIR, +} from '../constants.mjs'; + +import { openVault } from './actions.mjs'; + +test.before(async () => { + console.log('Wait for upgrade to settle'); + + await waitForBlock(20); +}); + +test(`Ensure there's only uist`, async t => { + const result = await agd.query( + 'bank', + 'balances', + 'agoric1megzytg65cyrgzs6fvzxgrcqvwwl7ugpt62346', + ); + + t.is(result.balances.length, 1); + t.is(result.balances[0].denom, 'uist'); +}); + +test('Ensure gov1 provisioned', async t => { + const result = await agd.query( + 'vstorage', + 'data', + `published.wallet.${GOV1ADDR}`, + ); + + t.not(result.value.length, 0); +}); + +test('Ensure gov2 provisioned', async t => { + const result = await agd.query( + 'vstorage', + 'data', + `published.wallet.${GOV2ADDR}`, + ); + + t.not(result.value.length, 0); +}); + +test('Ensure gov3 provisioned', async t => { + const result = await agd.query( + 'vstorage', + 'data', + `published.wallet.${GOV3ADDR}`, + ); + + t.not(result.value.length, 0); +}); + +test('Ensure user2 not provisioned', async t => { + try { + await getUser('user2'); + t.fail(); + } catch (error) { + t.pass(); + } +}); + +test('Ensure no vaults exist', async t => { + const result = await agd.query( + 'vstorage', + 'data', + `published.vaultFactory.manager0.vaults.vault0`, + ); + + t.is(result.value, ''); +}); + +test(`Provision pool has right balance`, async t => { + const result = await agd.query( + 'bank', + 'balances', + 'agoric1megzytg65cyrgzs6fvzxgrcqvwwl7ugpt62346', + ); + + t.is(result.balances[0].amount, '19000000'); +}); + +test('Validate PSM denoms', async t => { + const psmISTChildren = await agd.query( + 'vstorage', + 'children', + 'published.psm.IST', + ); + + t.not(psmISTChildren.children.legnth, 0); + + let denoms = ['USDC_axl', 'DAI_axl', 'DAI_grv']; + if (BOOTSTRAP_MODE === 'main') { + denoms = [...denoms, 'USDC_grv', 'USDT_axl', 'USDT_grv']; + } else { + denoms = [...denoms, 'ToyUSD']; + } + + for (const denom of denoms) { + t.truthy(psmISTChildren.children.includes(denom)); + } +}); + +test('PSM gov params were preserved', async t => { + const toyUSDGovernance = await agoric.follow( + '-lF', + `:published.psm.${PSM_PAIR}.governance`, + ); + + const psmGovernanceData = await fs.readFile( + '/root/.agoric/psm_governance.json', + 'binary', + ); + + const psmGovernance = JSON.parse(psmGovernanceData); + + t.not(toyUSDGovernance.current.MintLimit.value.value, '0'); + t.is( + toyUSDGovernance.current.MintLimit.value.value, + psmGovernance.current.MintLimit.value.value, + ); + t.is(toyUSDGovernance.current.GiveMintedFee.value.numerator.value, '0'); + t.is( + toyUSDGovernance.current.GiveMintedFee.value.denominator.value, + psmGovernance.current.GiveMintedFee.value.denominator.value, + ); + t.is(toyUSDGovernance.current.WantMintedFee.value.numerator.value, '0'); + t.is( + toyUSDGovernance.current.WantMintedFee.value.denominator.value, + psmGovernance.current.WantMintedFee.value.denominator.value, + ); +}); + +test('PSM metric params were preserved', async t => { + const toyUSDMetrics = await agoric.follow( + '-lF', + `:published.psm.${PSM_PAIR}.metrics`, + ); + + const psmMetricsData = await fs.readFile( + '/root/.agoric/psm_metrics.json', + 'binary', + ); + + const psmMetrics = JSON.parse(psmMetricsData); + + t.is( + toyUSDMetrics.anchorPoolBalance.value, + psmMetrics.anchorPoolBalance.value, + ); + t.is(toyUSDMetrics.feePoolBalance.value, psmMetrics.feePoolBalance.value); + t.is( + toyUSDMetrics.mintedPoolBalance.value, + psmMetrics.mintedPoolBalance.value, + ); + t.is( + toyUSDMetrics.totalMintedProvided.value, + psmMetrics.totalMintedProvided.value, + ); +}); + +test('Provision pool metrics are retained across vaults upgrade', async t => { + const provisionPoolMetrics = await agoric.follow( + '-lF', + ':published.provisionPool.metrics', + ); + + const provisionPoolMetricsData = await fs.readFile( + '/root/.agoric/provision_pool_metrics.json', + 'binary', + ); + + const testProvisionPoolMetrics = JSON.parse(provisionPoolMetricsData); + + t.is( + provisionPoolMetrics.totalMintedConverted.value, + testProvisionPoolMetrics.totalMintedConverted.value, + ); + t.is( + provisionPoolMetrics.totalMintedProvided.value, + testProvisionPoolMetrics.totalMintedProvided.value, + ); + t.is( + provisionPoolMetrics.walletsProvisioned, + testProvisionPoolMetrics.walletsProvisioned, + ); +}); + +test('Pre Vault tests', async t => { + try { + await openVault(GOV1ADDR, 5, 9); + t.fail(); + } catch (error) { + t.truthy( + error.message.includes( + "'Error: maxDebtFor called before a collateral quote was available'", + ), + ); + } +}); + +test('Gov1 has no vaults', async t => { + const vaults = await agops.vaults('list', '--from', GOV1ADDR); + t.is(vaults.length, 0); +}); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre_test.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre_test.sh deleted file mode 100644 index 7730fe7af67..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre_test.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/bash - -. ./upgrade-test-scripts/env_setup.sh - -echo Wait for upgrade to settle -waitForBlock 20 - -# ensure there's only uist -test_val "$(agd q bank balances agoric1megzytg65cyrgzs6fvzxgrcqvwwl7ugpt62346 -o json | jq -r '.balances | length')" "1" -test_val "$(agd q bank balances agoric1megzytg65cyrgzs6fvzxgrcqvwwl7ugpt62346 -o json | jq -r '.balances[0].denom')" "uist" - -# test wallets are provisioned -test_not_val "$(agd q vstorage data published.wallet.$GOV1ADDR -o json | jq -r .value)" "" "ensure gov1 provisioned" -test_not_val "$(agd q vstorage data published.wallet.$GOV2ADDR -o json | jq -r .value)" "" "ensure gov2 provisioned" -test_not_val "$(agd q vstorage data published.wallet.$GOV3ADDR -o json | jq -r .value)" "" "ensure gov3 provisioned" - -# test user2 not provisioned -test_val "$(agd q vstorage data published.wallet.$USER2ADDR -o json | jq -r .value)" "" "ensure user2 not provisioned" - -# test that we have no vaults -test_val "$(agd q vstorage data published.vaultFactory.manager0.vaults.vault0 -o json | jq -r .value)" "" "ensure no vaults exist" - -# provision pool has right balance -test_val "$(agd query bank balances agoric1megzytg65cyrgzs6fvzxgrcqvwwl7ugpt62346 -o json | jq -r '.balances | first | .amount ')" "19000000" - -# we should have more denoms in governance -psmISTChildren="$(agd q vstorage children published.psm.IST -o jsonlines)" -test_not_val "$(echo "$psmISTChildren" | jq -r '.children | length')" "1" "more than one PSM denoms" - -# emerynet started with ToyUSD; gov proposals added USDC_axl, DAI_axl, DAI_grv -# main started with USDC, USDT x axl, grv and a gov proposal added DAI x axl, grv -if [[ "$BOOTSTRAP_MODE" == "test" ]]; then - test_not_val "$(echo "$psmISTChildren" | jq -r '.children[] | select (. == "ToyUSD")')" "" "ToyUSD in IST" -else - test_not_val "$(echo "$psmISTChildren" | jq -r '.children[] | select (. == "USDC_grv")')" "" "USDC_grv in IST" - test_not_val "$(echo "$psmISTChildren" | jq -r '.children[] | select (. == "USDT_axl")')" "" "USDT_axl in IST" - test_not_val "$(echo "$psmISTChildren" | jq -r '.children[] | select (. == "USDT_grv")')" "" "USDT_grv in IST" -fi - test_not_val "$(echo "$psmISTChildren" | jq -r '.children[] | select (. == "USDC_axl")')" "" "USDC_axl in IST" - test_not_val "$(echo "$psmISTChildren" | jq -r '.children[] | select (. == "DAI_axl")')" "" "DAI_axl in IST" - test_not_val "$(echo "$psmISTChildren" | jq -r '.children[] | select (. == "DAI_grv")')" "" "DAI_grv in IST" - -## testing state from pismoC was preserved post bulldozer upgrade - -# test that the PSM gov params were preserved -toyUSDGovernance="$(agoric follow -lF :published.psm.${PSM_PAIR}.governance -o jsonlines)" -test_not_val "$(echo "$toyUSDGovernance" | jq -r '.current.MintLimit.value.value')" "0" "PSM MintLimit non-zero" -test_val "$(echo "$toyUSDGovernance" | jq -r '.current.MintLimit.value.value')" "$(cat /root/.agoric/psm_governance.json | jq -r '.current.MintLimit.value.value')" "PSM MintLimit preserved" -test_val "$(echo "$toyUSDGovernance" | jq -r '.current.GiveMintedFee.value.numerator.value')" "0" "GiveMintedFee numerator == 0" -test_val "$(echo "$toyUSDGovernance" | jq -r '.current.GiveMintedFee.value.denominator.value')" "$(cat /root/.agoric/psm_governance.json | jq -r '.current.GiveMintedFee.value.denominator.value')" "GiveMintedFee denominator == 10000" -test_val "$(echo "$toyUSDGovernance" | jq -r '.current.WantMintedFee.value.numerator.value')" "0" "WantMintedFee numerator == 0" -test_val "$(echo "$toyUSDGovernance" | jq -r '.current.WantMintedFee.value.denominator.value')" "$(cat /root/.agoric/psm_governance.json | jq -r '.current.WantMintedFee.value.denominator.value')" "WantMintedFee denominator == 10000" - -toyUSDMetrics="$(agoric follow -lF :published.psm.${PSM_PAIR}.metrics -o jsonlines)" -test_val "$(echo "$toyUSDMetrics" | jq -r '.anchorPoolBalance.value')" "$(cat /root/.agoric/psm_metrics.json | jq -r '.anchorPoolBalance.value')" "anchorPoolBalance preserved" -test_val "$(echo "$toyUSDMetrics" | jq -r '.feePoolBalance.value')" "$(cat /root/.agoric/psm_metrics.json | jq -r '.feePoolBalance.value')" "feePoolBalance preserved" -test_val "$(echo "$toyUSDMetrics" | jq -r '.mintedPoolBalance.value')" "$(cat /root/.agoric/psm_metrics.json | jq -r '.mintedPoolBalance.value')" "mintedPoolBalance preserved" -test_val "$(echo "$toyUSDMetrics" | jq -r '.totalAnchorProvided.value')" "$(cat /root/.agoric/psm_metrics.json | jq -r '.totalAnchorProvided.value')" "totalAnchorProvided preserved" -test_val "$(echo "$toyUSDMetrics" | jq -r '.totalMintedProvided.value')" "$(cat /root/.agoric/psm_metrics.json | jq -r '.totalMintedProvided.value')" "totalMintedProvided preserved" - -# test that provision pool metrics are retained across vaults upgrade -provisionPoolMetrics="$(agoric follow -lF :published.provisionPool.metrics -o jsonlines)" -test_val "$(echo "$provisionPoolMetrics" | jq -r '.totalMintedConverted.value')" "$(cat /root/.agoric/provision_pool_metrics.json | jq -r '.totalMintedConverted.value')" "totalMintedConverted preserved" -test_val "$(echo "$provisionPoolMetrics" | jq -r '.totalMintedProvided.value')" "$(cat /root/.agoric/provision_pool_metrics.json | jq -r '.totalMintedProvided.value')" "totalMintedProvided preserved" -test_val "$(echo "$provisionPoolMetrics" | jq -r '.walletsProvisioned')" "$(cat /root/.agoric/provision_pool_metrics.json | jq -r '.walletsProvisioned')" "walletsProvisioned preserved" - -# vaults pre-tests - -# attempt to open a vault on main -# these should fail due to debt limit starting at 0 -if [[ "$BOOTSTRAP_MODE" == "main" ]]; then - test_val "$(agoric follow -lF :published.vaultFactory.managers.manager0.governance -o jsonlines | jq -r '.current.DebtLimit.value.value')" "0" "boostrap(main) DebtLimit starts at 0" - - OFFER=$(mktemp -t agops.XXX) - agops vaults open --wantMinted 5.00 --giveCollateral 9 >|"$OFFER" - agoric wallet print --file "$OFFER" - agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$OFFER" --keyring-backend=test || true -fi - -test_val "$(agops vaults list --from $GOV1ADDR)" "" "gov1 has no vaults" diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/test.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/test.sh deleted file mode 100644 index 633716f5b4a..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/test.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -. ./upgrade-test-scripts/env_setup.sh - -# DeliverInbound from un-provisioned account is discarded -# Note: sending to a provisioned account resulted in an .outbox of -# [[1,"1:1:resolve:fulfill:rp+44:ro-20;#\"$0.Alleged: notifier\""]] -test_val $(agd query swingset mailbox $USER1ADDR -o json | jq '.value |fromjson |.outbox') '[]' "DeliverInbound (getConfiguration) is discarded" - -# provision pool has right balance -test_val $(agd query bank balances agoric1megzytg65cyrgzs6fvzxgrcqvwwl7ugpt62346 -o json | jq -r '.balances | first | .amount ') "18750000" - -test_wallet_state "$USER1ADDR" upgraded "user1 wallet is upgraded" -test_wallet_state "$GOV1ADDR" revived "gov1 wallet is revived" -test_wallet_state "$GOV2ADDR" revived "gov2 wallet is revived" -test_wallet_state "$GOV3ADDR" revived "gov3 wallet is revived" - -test_val $(agd q vstorage children published.vaultFactory.managers.manager0.vaults -o json | jq -r '.children | length') 3 "we have three vaults" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.metrics -o jsonlines | jq -r '.numActiveVaults') 1 "only one vault is active" - -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.metrics -o jsonlines | jq -r '.totalDebt.value') "6030000" "totalDebt is correct" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.metrics -o jsonlines | jq -r '.totalCollateral.value') "8000000" "totalCollateral is correct" - -# gov1 vault0 -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault0 -o jsonlines | jq -r '.vaultState') "active" "vault0 is open" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault0 -o jsonlines | jq -r '.locked.value') "8000000" "vault0 contains 8 ATOM collateral" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault0 -o jsonlines | jq -r '.debtSnapshot.debt.value') "6030000" "vault0 debt is 6.03 IST" - -# gov1 vault1 -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault1 -o jsonlines | jq -r '.vaultState') "closed" "vault1 is closed" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault1 -o jsonlines | jq -r '.locked.value') "0" "vault1 contains no collateral" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault1 -o jsonlines | jq -r '.debtSnapshot.debt.value') "0" "vault1 has no debt" - -# user2 vault2 -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault2 -o jsonlines | jq -r '.vaultState') "closed" "vault2 is closed" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault2 -o jsonlines | jq -r '.locked.value') "0" "vault2 contains no collateral" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault2 -o jsonlines | jq -r '.debtSnapshot.debt.value') "0" "vault2 has no debt" - -# verify state-sync would be broken -killAgd -EXPORT_DIR=$(mktemp -t -d swing-store-export-upgrade-10-XXX) -make_swing_store_snapshot $EXPORT_DIR || fail "Couldn't make swing-store snapshot" -test_val "$(compare_swing_store_export_data $EXPORT_DIR)" "mismatch" "swing-store broken state-sync" -rm -rf $EXPORT_DIR -startAgd \ No newline at end of file diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/upgradeHelpers.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/upgradeHelpers.mjs new file mode 100644 index 00000000000..3768d5603ee --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/upgradeHelpers.mjs @@ -0,0 +1,76 @@ +/* eslint-disable @jessie.js/safe-await-separator */ +import { $ } from 'execa'; + +import { + GOV1ADDR, + GOV2ADDR, + GOV3ADDR, + VALIDATORADDR, + USER1ADDR, + CHAINID, + HOME, +} from '../constants.mjs'; + +import { agd, agops } from '../cliHelper.mjs'; + +export * from '../coreUpgradeHelpers.mjs'; + +export const getUser = async user => { + return agd.keys('show', user, '-a', '--keyring-backend=test'); +}; + +export const printKeys = async () => { + console.log('========== GOVERNANCE KEYS =========='); + + console.log(`gov1: ${GOV1ADDR}`); + const gov1Key = await $`cat /root/.agoric/gov1.key`; + console.log(gov1Key.stdout); + + console.log(`gov2: ${GOV2ADDR}`); + const gov2Key = await $`cat /root/.agoric/gov2.key`; + console.log(gov2Key.stdout); + + console.log(`gov3: ${GOV3ADDR}`); + const gov3Key = await $`cat /root/.agoric/gov3.key`; + console.log(gov3Key.stdout); + + console.log(`validator: ${VALIDATORADDR}`); + const validatorKey = await $`cat /root/.agoric/validator.key`; + console.log(validatorKey.stdout); + + console.log(`user1: ${USER1ADDR}`); + const user1Key = await $`cat /root/.agoric/user1.key`; + console.log(user1Key.stdout); + + const user2Address = await getUser('user2'); + + console.log(`user2: ${user2Address}`); + const user2Key = await $`cat /root/.agoric/user1.key`; + console.log(user2Key.stdout); +}; + +// submit a DeliverInbound transaction +// +// see {agoric.swingset.MsgDeliverInbound} in swingset/msgs.proto +// https://github.com/Agoric/agoric-sdk/blob/5cc5ec8836dcd0c6e11b10799966b6e74601295d/golang/cosmos/proto/agoric/swingset/msgs.proto#L23 +export const submitDeliverInbound = async sender => { + // ag-solo is a client that sends DeliverInbound transactions using a golang client + // @see {connectToChain} in chain-cosmos-sdk.js + // runHelper + // https://github.com/Agoric/agoric-sdk/blob/5cc5ec8836dcd0c6e11b10799966b6e74601295d/packages/solo/src/chain-cosmos-sdk.js + + // The payload is JSON.stringify([messages, highestAck]) + // https://github.com/Agoric/agoric-sdk/blob/5cc5ec8836dcd0c6e11b10799966b6e74601295d/packages/solo/src/chain-cosmos-sdk.js#L625 + // for example, this json was captured from a running `agoric start local-solo` + const json = `[[[1,"1:0:deliver:ro+1:rp-44;#[\\"getConfiguration\\",[]]"]],0]`; + await agd.tx( + 'swingset', + 'deliver', + `'${json}'`, + `--chain-id="${CHAINID}"`, + '--yes', + `--from="${sender}"`, + '--keyring-backend=test', + '-b block', + ); +}; diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/cliHelper.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/cliHelper.mjs new file mode 100644 index 00000000000..29d08401e01 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/cliHelper.mjs @@ -0,0 +1,110 @@ +/* eslint-disable @jessie.js/safe-await-separator */ +import { $, execaCommand } from 'execa'; +import { BINARY } from './constants.mjs'; + +export const executeCommand = async (command, params, options = {}) => { + const { stdout } = await execaCommand( + `${command} ${params.join(' ')}`, + options, + ); + return stdout; +}; + +export const agd = { + query: async (...params) => { + const newParams = ['query', ...params, '-o json']; + const data = await executeCommand(BINARY, newParams); + return JSON.parse(data); + }, + tx: async (...params) => { + const newParams = ['tx', ...params, '-o json']; + const data = await executeCommand(BINARY, newParams, { shell: true }); + return JSON.parse(data); + }, + keys: async (...params) => { + let newParams = ['keys', ...params]; + let shouldParse = true; + + if (params.includes('show')) { + if (params.includes('-a') || params.includes('-address')) { + shouldParse = false; + } + } + + if (shouldParse) { + newParams = [...newParams, '--output json']; + } + + const data = await executeCommand(BINARY, newParams, { input: 'Y' }); + if (!shouldParse) { + return data; + } + + return JSON.parse(data); + }, + export: async (...params) => { + const newParams = ['export', ...params]; + const data = await executeCommand(BINARY, newParams); + return JSON.parse(data); + }, +}; + +export const agoric = { + follow: async (...params) => { + let newParams = ['follow', ...params]; + let parseJson = false; + + if (!params.includes('-o')) { + newParams = [...newParams, '-o json']; + parseJson = true; + } + const data = await executeCommand('agoric', newParams); + + if (parseJson) { + return JSON.parse(data); + } + + return data; + }, + wallet: async (...params) => { + const newParams = ['wallet', ...params]; + return executeCommand('agoric', newParams); + }, +}; + +export const { stdout: agopsLocation } = await $({ + shell: true, + cwd: '/usr/src/agoric-sdk', +})`yarn bin agops`; + +export const agops = { + vaults: async (...params) => { + const newParams = ['vaults', ...params]; + + const result = await executeCommand(agopsLocation, newParams); + + if (params[0] === 'list') { + if (result === '') return []; + + return result.split('\n'); + } + + return result; + }, + ec: async (...params) => { + const newParams = ['ec', ...params]; + return executeCommand(agopsLocation, newParams); + }, + oracle: async (...params) => { + const newParams = ['oracle', ...params]; + return executeCommand(agopsLocation, newParams); + }, + perf: async (...params) => { + const newParams = ['perf', ...params]; + return executeCommand(agopsLocation, newParams); + }, + auctioneer: async (...params) => { + const newParams = ['auctioneer', ...params]; + return executeCommand(agopsLocation, newParams); + }, +}; diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/constants.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/constants.mjs new file mode 100644 index 00000000000..1dc1d7cea27 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/constants.mjs @@ -0,0 +1,14 @@ +export const BINARY = process.env.binary; + +export const GOV1ADDR = process.env.GOV1ADDR; +export const GOV2ADDR = process.env.GOV2ADDR; +export const GOV3ADDR = process.env.GOV3ADDR; +export const USER1ADDR = process.env.USER1ADDR; +export const VALIDATORADDR = process.env.VALIDATORADDR; + +export const BOOTSTRAP_MODE = process.env.BOOTSTRAP_MODE; +export const PSM_PAIR = process.env.PSM_PAIR; +export const ATOM_DENOM = process.env.ATOM_DENOM; + +export const CHAINID = process.env.CHAINID; +export const HOME = process.env.HOME; diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/coreUpgradeHelpers.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/coreUpgradeHelpers.mjs new file mode 100644 index 00000000000..f85ebfdce34 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/coreUpgradeHelpers.mjs @@ -0,0 +1,133 @@ +/* eslint-disable @jessie.js/safe-await-separator */ +import { $ } from 'execa'; +import { promises as fs } from 'fs'; +import { agd, agoric, agops } from './cliHelper.mjs'; +import { CHAINID } from './constants.mjs'; + +const waitForBootstrap = async () => { + const endpoint = 'localhost'; + while (true) { + const { stdout: json } = await $({ + reject: false, + })`curl -s --fail -m 15 ${`${endpoint}:26657/status`}`; + + if (json.length === 0) { + continue; + } + + const data = JSON.parse(json); + + if (data.jsonrpc !== '2.0') { + continue; + } + + const lastHeight = data.result.sync_info.latest_block_height; + + if (lastHeight !== '1') { + return lastHeight; + } + + await new Promise(r => setTimeout(r, 2000)); + } +}; + +export const waitForBlock = async (times = 1) => { + console.log(times); + let time = 0; + while (time < times) { + const block1 = await waitForBootstrap(); + while (true) { + const block2 = await waitForBootstrap(); + + if (block1 !== block2) { + console.log('block produced'); + break; + } + + await new Promise(r => setTimeout(r, 1000)); + } + time += 1; + } +}; + +export const provisionSmartWallet = async (address, amount) => { + console.log(`funding ${address}`); + await agd.tx( + 'bank', + 'send', + 'validator', + address, + amount, + '-y', + '--keyring-backend=test', + `--chain-id="${CHAINID}"`, + ); + await waitForBlock(); + + console.log(`provisioning ${address}`); + await agd.tx( + 'swingset', + 'provision-one', + 'my-wallet', + address, + 'SMART_WALLET', + '--keyring-backend=test', + '-y', + `--chain-id="${CHAINID}"`, + `--from="${address}"`, + ); + + await waitForBlock(2); + console.log(await agoric.wallet('show', `--from ${address}`)); +}; + +export const newOfferId = async () => { + const { stdout: date } = await $`date +${'%s%3M'}`; + await new Promise(r => setTimeout(r, 1000)); + + return date; +}; + +export const mkTemp = async (template, asDirectory = false) => { + const { stdout: data } = await $({ + shell: true, + })`mktemp -t ${template}`; + return data; +}; + +export const calculateWalletState = async addr => { + const result = await agoric.follow( + '-lF', + `:published.wallet.${addr}`, + '-o', + 'text', + ); + + const body = JSON.parse(result).body; + let state = body; + + if (body.includes('@qclass')) { + state = 'old'; + } else if (body.includes('#{}')) { + state = 'upgraded'; + } else if (body.includes('#')) { + state = 'revived'; + } + + return state; +}; + +export const executeOffer = async (address, offerPromise) => { + const offerPath = await mkTemp('agops.XXX'); + const offer = await offerPromise; + await fs.writeFile(offerPath, offer); + + await agops.perf( + 'satisfaction', + '--from', + address, + '--executeOffer', + offerPath, + '--keyring-backend=test', + ); +}; diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/env_setup.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/env_setup.sh old mode 100644 new mode 100755 diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/package.json b/packages/deployment/upgrade-test/upgrade-test-scripts/package.json new file mode 100644 index 00000000000..acfa7c6f8ad --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/package.json @@ -0,0 +1,20 @@ +{ + "type": "module", + "devDependencies": { + "ava": "^5.3.1" + }, + "dependencies": { + "execa": "^7.2.0" + }, + "scripts": { + "upgrade-tests": "ava --serial agoric-upgrade*/**/pre.test.js agoric-upgrade*/**/actions.test.js agoric-upgrade*/**/post.test.js" + }, + "ava": { + "files": [ + "*/**/pre.test.js", + "*/**/actions.test.js", + "*/**/post.test.js" + ], + "timeout": "30m" + } +} diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/start_to_to.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/start_to_to.sh index 2ba2d2a8e13..72ad19d0539 100644 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/start_to_to.sh +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/start_to_to.sh @@ -17,9 +17,18 @@ fi startAgd if ! test -f "$HOME/.agoric/runActions-${THIS_NAME}"; then - runActions "pre_test" - runActions "actions" - runActions "test" + if [[ "${USE_JS}" == "1" ]]; then + pushd upgrade-test-scripts + yarn + yarn upgrade-tests || exit 1 + popd + runActions "legacy" + else + runActions "pre_test" + runActions "actions" + runActions "test" + fi + touch "$HOME/.agoric/runActions-${THIS_NAME}" fi From c01198b42a68c66e1b17d5158b40507479156393 Mon Sep 17 00:00:00 2001 From: Mathieu Hofman Date: Thu, 31 Aug 2023 03:03:20 +0000 Subject: [PATCH 05/35] chore(deployment): add test of core proposal execution --- packages/deployment/upgrade-test/Dockerfile | 4 +--- .../upgrade-test-scripts/agoric-upgrade-12/pre_test.sh | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/deployment/upgrade-test/Dockerfile b/packages/deployment/upgrade-test/Dockerfile index baf82069a07..79f69a502e9 100644 --- a/packages/deployment/upgrade-test/Dockerfile +++ b/packages/deployment/upgrade-test/Dockerfile @@ -93,9 +93,7 @@ ARG DEST_IMAGE #this is agoric-upgrade-10 upgrading to 11 #it's a separate target because agoric-upgrade-10 takes so long to test FROM ghcr.io/agoric/agoric-sdk:35 as propose-agoric-upgrade-11 -# This default UPGRADE_INFO_11 is to test core proposals like the network vat. -# TODO: Maybe replace with a Zoe core proposal, or remove when other paths test it. -ARG BOOTSTRAP_MODE UPGRADE_INFO_11='{"coreProposals":["@agoric/vats/scripts/init-network.js"]}' +ARG BOOTSTRAP_MODE UPGRADE_INFO_11 ENV THIS_NAME=propose-agoric-upgrade-11 UPGRADE_TO=agoric-upgrade-11 UPGRADE_INFO=${UPGRADE_INFO_11} BOOTSTRAP_MODE=${BOOTSTRAP_MODE} WORKDIR /usr/src/agoric-sdk/ COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./upgrade-test-scripts/ diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh index 334821210f7..374810706d3 100755 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh @@ -2,12 +2,12 @@ . ./upgrade-test-scripts/env_setup.sh -echo Wait for upgrade to settle -waitForBlock 5 - # CWD is agoric-sdk upgrade12=./upgrade-test-scripts/agoric-upgrade-12 +# test that the network vat was installed (see UPGRADE_INFO_12) +test_val "$(yarn --silent node $upgrade12/tools/vat-status.mjs network)" "0" "network vat incarnation" + test_val "$(agd query vstorage children published.boardAux -o json | jq .children)" "[]" "no boardAux children yet" # zoe vat is at incarnation 0 From 9d7e8ac75972ffb87d23cfbebe7832a6117819b2 Mon Sep 17 00:00:00 2001 From: Ikenna Omekam Date: Thu, 31 Aug 2023 13:03:08 -0500 Subject: [PATCH 06/35] test: separate upgrade-12 --- golang/cosmos/app/app.go | 108 ++--------------- golang/cosmos/app/const.go | 6 - packages/deployment/upgrade-test/Dockerfile | 71 +++++++++-- packages/deployment/upgrade-test/Makefile | 16 ++- packages/deployment/upgrade-test/Readme.md | 15 +++ .../agoric-upgrade-11/actions.sh | 19 --- .../agoric-upgrade-11/pre_test.sh | 5 - .../agoric-upgrade-11/test.sh | 45 ------- .../.gitignore | 0 .../agoric-upgrade-12/actions.sh | 93 +++++++++++++++ .../agoric-upgrade-12/env_setup.sh | 3 + .../agoric-upgrade-12/pre_test.sh | 14 +++ .../agoric-upgrade-12/test.sh | 56 +++++++++ .../tools/mint-ist.sh | 0 .../tools/parseProposals.mjs | 0 .../agoric-upgrade-12/tools/vat-status.mjs | 111 ++++++++++++++++++ .../wallet-all-ertp/gen-game-offer.mjs | 0 .../wallet-all-ertp/wf-game-propose.sh | 6 +- .../wallet-all-ertp/wf-install-bundles.sh | 6 +- .../wallet-all-ertp/wf-propose.sh | 8 +- .../upgrade-test-scripts/package.json | 1 + .../.keep | 0 .../propose-agoric-upgrade-12/.keep | 0 23 files changed, 383 insertions(+), 200 deletions(-) delete mode 100644 golang/cosmos/app/const.go rename packages/deployment/upgrade-test/upgrade-test-scripts/{agoric-upgrade-11 => agoric-upgrade-12}/.gitignore (100%) create mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.sh create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/env_setup.sh create mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh create mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/test.sh rename packages/deployment/upgrade-test/upgrade-test-scripts/{agoric-upgrade-11 => agoric-upgrade-12}/tools/mint-ist.sh (100%) rename packages/deployment/upgrade-test/upgrade-test-scripts/{agoric-upgrade-11 => agoric-upgrade-12}/tools/parseProposals.mjs (100%) create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/vat-status.mjs rename packages/deployment/upgrade-test/upgrade-test-scripts/{agoric-upgrade-11 => agoric-upgrade-12}/wallet-all-ertp/gen-game-offer.mjs (100%) rename packages/deployment/upgrade-test/upgrade-test-scripts/{agoric-upgrade-11 => agoric-upgrade-12}/wallet-all-ertp/wf-game-propose.sh (87%) rename packages/deployment/upgrade-test/upgrade-test-scripts/{agoric-upgrade-11 => agoric-upgrade-12}/wallet-all-ertp/wf-install-bundles.sh (83%) rename packages/deployment/upgrade-test/upgrade-test-scripts/{agoric-upgrade-11 => agoric-upgrade-12}/wallet-all-ertp/wf-propose.sh (86%) rename packages/deployment/upgrade-test/upgrade-test-scripts/{agoric-upgrade-10-to-11 => propose-agoric-upgrade-11}/.keep (100%) create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/propose-agoric-upgrade-12/.keep diff --git a/golang/cosmos/app/app.go b/golang/cosmos/app/app.go index f5932d90c95..2caf9b410c8 100644 --- a/golang/cosmos/app/app.go +++ b/golang/cosmos/app/app.go @@ -790,13 +790,18 @@ func NewAgoricApp( app.SetBeginBlocker(app.BeginBlocker) app.SetEndBlocker(app.EndBlocker) + const ( + upgradeName = "agoric-upgrade-12" + upgradeNameTest = "agorictest-upgrade-12" + ) + app.UpgradeKeeper.SetUpgradeHandler( upgradeName, - upgrade11Handler(app, upgradeName), + upgrade12Handler(app, upgradeName), ) app.UpgradeKeeper.SetUpgradeHandler( upgradeNameTest, - upgrade11Handler(app, upgradeNameTest), + upgrade12Handler(app, upgradeNameTest), ) if loadLatest { @@ -819,108 +824,13 @@ func NewAgoricApp( return app } -type swingStoreMigrationEventHandler struct { - swingStore sdk.KVStore -} - -func (eventHandler swingStoreMigrationEventHandler) OnExportStarted(height uint64, retrieveSwingStoreExport func() error) error { - return retrieveSwingStoreExport() -} - -func (eventHandler swingStoreMigrationEventHandler) OnExportRetrieved(provider swingsetkeeper.SwingStoreExportProvider) (err error) { - exportDataReader, err := provider.GetExportDataReader() - if err != nil { - return err - } - defer exportDataReader.Close() - - var hasExportData bool - - for { - entry, err := exportDataReader.Read() - if err == io.EOF { - break - } else if err != nil { - return err - } - hasExportData = true - if !entry.HasValue() { - return fmt.Errorf("no value for export data key %s", entry.Key()) - } - eventHandler.swingStore.Set([]byte(entry.Key()), []byte(entry.StringValue())) - } - if !hasExportData { - return fmt.Errorf("export data had no entries") - } - return nil -} - -// upgrade11Handler performs standard upgrade actions plus custom actions for upgrade-11. -func upgrade11Handler(app *GaiaApp, targetUpgrade string) func(sdk.Context, upgradetypes.Plan, module.VersionMap) (module.VersionMap, error) { +// upgrade12Handler performs standard upgrade actions plus custom actions for upgrade-12. +func upgrade12Handler(app *GaiaApp, targetUpgrade string) func(sdk.Context, upgradetypes.Plan, module.VersionMap) (module.VersionMap, error) { return func(ctx sdk.Context, plan upgradetypes.Plan, fromVm module.VersionMap) (module.VersionMap, error) { app.CheckControllerInited(false) // Record the plan to send to SwingSet app.upgradePlan = &plan - // Perform swing-store migrations. We do this in the app upgrade handler - // since it involves multiple modules (x/vstorage and x/swingset) which - // don't strictly have a version change on their own. - - // We are at the begining of the upgrade block, so all stores are commited - // as of the end of the previous block - savedBlockHeight := uint64(ctx.BlockHeight() - 1) - - // First, repair swing-store metadata in case this node was previously - // initialized from a state-sync snapshot. This is done with a check on the - // block height to catch early any hangover related mismatch. - // Only entries related to missing historical metadata are imported, but we - // don't know what these look like here, so we provide it all. - getSwingStoreExportDataFromVstorage := func() (reader agorictypes.KVEntryReader, err error) { - return agorictypes.NewVstorageDataEntriesReader( - app.VstorageKeeper.ExportStorageFromPrefix(ctx, swingsetkeeper.StoragePathSwingStore), - ), nil - } - - // We're not restoring any artifact to swing-store, nor have any to provide - readNoArtifact := func() (artifact swingsettypes.SwingStoreArtifact, err error) { - return artifact, io.EOF - } - - err := app.SwingStoreExportsHandler.RestoreExport( - swingsetkeeper.SwingStoreExportProvider{ - BlockHeight: savedBlockHeight, - GetExportDataReader: getSwingStoreExportDataFromVstorage, - ReadNextArtifact: readNoArtifact, - }, - swingsetkeeper.SwingStoreRestoreOptions{ - ArtifactMode: swingsetkeeper.SwingStoreArtifactModeNone, - ExportDataMode: swingsetkeeper.SwingStoreExportDataModeRepairMetadata, - }, - ) - if err != nil { - return nil, err - } - - // Then migrate the swing-store shadow copy: - // 1. Remove the swing-store "export data" shadow-copy entries from vstorage. - // 2. Export swing-store "export-data" (as of the previous block) through a - // handler that writes every entry into the swingset module's new Store. - app.VstorageKeeper.RemoveEntriesWithPrefix(ctx, swingsetkeeper.StoragePathSwingStore) - err = app.SwingStoreExportsHandler.InitiateExport( - savedBlockHeight, - swingStoreMigrationEventHandler{swingStore: app.SwingSetKeeper.GetSwingStore(ctx)}, - swingsetkeeper.SwingStoreExportOptions{ - ArtifactMode: swingsetkeeper.SwingStoreArtifactModeNone, - ExportDataMode: swingsetkeeper.SwingStoreExportDataModeAll, - }, - ) - if err == nil { - err = swingsetkeeper.WaitUntilSwingStoreExportDone() - } - if err != nil { - return nil, err - } - // Always run module migrations mvm, err := app.mm.RunMigrations(ctx, app.configurator, fromVm) if err != nil { diff --git a/golang/cosmos/app/const.go b/golang/cosmos/app/const.go deleted file mode 100644 index 2e7f4a2f391..00000000000 --- a/golang/cosmos/app/const.go +++ /dev/null @@ -1,6 +0,0 @@ -package gaia - -const ( - upgradeName = "agoric-upgrade-11" - upgradeNameTest = "agorictest-upgrade-11" -) diff --git a/packages/deployment/upgrade-test/Dockerfile b/packages/deployment/upgrade-test/Dockerfile index ed8eb49b131..baf82069a07 100644 --- a/packages/deployment/upgrade-test/Dockerfile +++ b/packages/deployment/upgrade-test/Dockerfile @@ -1,5 +1,18 @@ +# Defaults ARG DEST_IMAGE=ghcr.io/agoric/agoric-sdk:dev ARG BOOTSTRAP_MODE=main + +# TODO different naming scheme for upgrade handler (in app.go) and the image name + +### +# Kinds of layers: +# START ag0, start of the chain +# UPGRADE+TEST legacy layer type in which the chain upgrade and its tests are comingled +# UPGRADE layer that only runs the upgrade handler +# TEST layer that only tests a previous upgrade +# DEST the final layer this build is producing, opening an interactive shell + +## START # on agoric-uprade-7-2, with upgrade to agoric-upgrade-8 FROM ghcr.io/agoric/ag0:agoric-upgrade-7-2 as agoric-upgrade-7-2 ARG BOOTSTRAP_MODE @@ -11,27 +24,31 @@ WORKDIR /usr/src/agoric-sdk/ COPY ./start_ag0.sh ./upgrade-test-scripts/ COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./upgrade-test-scripts/ SHELL ["/bin/bash", "-c"] +# this is the only layer that starts ag0 RUN . ./upgrade-test-scripts/start_ag0.sh +## UPGRADE+TEST ## this is agoric-upgrade-8 aka pismoA FROM ghcr.io/agoric/agoric-sdk:29 as agoric-upgrade-8 ARG BOOTSTRAP_MODE ENV THIS_NAME=agoric-upgrade-8 BOOTSTRAP_MODE=${BOOTSTRAP_MODE} -WORKDIR /usr/src/agoric-sdk/ +# copy from previous build +COPY --from=agoric-upgrade-7-2 /root/.agoric /root/.agoric +# boilerplate to copy scripts for this upgrade +WORKDIR /usr/src/agoric-sdk/ COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./upgrade-test-scripts/ COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ -COPY --from=agoric-upgrade-7-2 /root/.agoric /root/.agoric RUN chmod +x ./upgrade-test-scripts/*.sh SHELL ["/bin/bash", "-c"] RUN . ./upgrade-test-scripts/start_to_to.sh +## UPGRADE+TEST ARG DEST_IMAGE #this is agoric-upgrade-8-1 aka pismoB FROM ghcr.io/agoric/agoric-sdk:30 as agoric-upgrade-8-1 ARG BOOTSTRAP_MODE UPGRADE_INFO_9 ENV THIS_NAME=agoric-upgrade-8-1 UPGRADE_TO=agoric-upgrade-9 UPGRADE_INFO=${UPGRADE_INFO_9} BOOTSTRAP_MODE=${BOOTSTRAP_MODE} - WORKDIR /usr/src/agoric-sdk/ COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./upgrade-test-scripts/ COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ @@ -40,6 +57,7 @@ RUN chmod +x ./upgrade-test-scripts/*.sh SHELL ["/bin/bash", "-c"] RUN . ./upgrade-test-scripts/start_to_to.sh +# UPGRADE+TEST ARG DEST_IMAGE # this is agoric-upgrade-9 / pismoC with upgrade to agoric-upgrade-10 FROM ghcr.io/agoric/agoric-sdk:31 as agoric-upgrade-9 @@ -55,7 +73,7 @@ RUN chmod +x ./upgrade-test-scripts/*.sh SHELL ["/bin/bash", "-c"] RUN . ./upgrade-test-scripts/start_to_to.sh - +# UPGRADE+TEST ARG DEST_IMAGE #this is agoric-upgrade-10 / vaults FROM ghcr.io/agoric/agoric-sdk:35 as agoric-upgrade-10 @@ -70,15 +88,15 @@ RUN chmod +x ./upgrade-test-scripts/*.sh SHELL ["/bin/bash", "-c"] RUN . ./upgrade-test-scripts/start_to_to.sh +# UPGRADE ARG DEST_IMAGE #this is agoric-upgrade-10 upgrading to 11 #it's a separate target because agoric-upgrade-10 takes so long to test -FROM ghcr.io/agoric/agoric-sdk:35 as agoric-upgrade-10-to-11 +FROM ghcr.io/agoric/agoric-sdk:35 as propose-agoric-upgrade-11 # This default UPGRADE_INFO_11 is to test core proposals like the network vat. # TODO: Maybe replace with a Zoe core proposal, or remove when other paths test it. ARG BOOTSTRAP_MODE UPGRADE_INFO_11='{"coreProposals":["@agoric/vats/scripts/init-network.js"]}' -ENV THIS_NAME=agoric-upgrade-10-to-11 UPGRADE_TO=agoric-upgrade-11 UPGRADE_INFO=${UPGRADE_INFO_11} BOOTSTRAP_MODE=${BOOTSTRAP_MODE} - +ENV THIS_NAME=propose-agoric-upgrade-11 UPGRADE_TO=agoric-upgrade-11 UPGRADE_INFO=${UPGRADE_INFO_11} BOOTSTRAP_MODE=${BOOTSTRAP_MODE} WORKDIR /usr/src/agoric-sdk/ COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./upgrade-test-scripts/ COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ @@ -87,18 +105,49 @@ RUN chmod +x ./upgrade-test-scripts/*.sh SHELL ["/bin/bash", "-c"] RUN . ./upgrade-test-scripts/start_to_to.sh -ARG DEST_IMAGE +# TEST #this is agoric-upgrade-11 / vaults+1 -FROM ${DEST_IMAGE} as agoric-upgrade-11 +ARG DEST_IMAGE +FROM ghcr.io/agoric/agoric-sdk:36 as agoric-upgrade-11 ARG BOOTSTRAP_MODE ENV THIS_NAME=agoric-upgrade-11 BOOTSTRAP_MODE=${BOOTSTRAP_MODE} -# this boot doesn't need an upgrade +# start-chain boilerplate +WORKDIR /usr/src/agoric-sdk/ +COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./upgrade-test-scripts/ +COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ +COPY --from=propose-agoric-upgrade-11 /root/.agoric /root/.agoric +RUN chmod +x ./upgrade-test-scripts/*.sh +SHELL ["/bin/bash", "-c"] +RUN . ./upgrade-test-scripts/start_to_to.sh +# UPGRADE +ARG DEST_IMAGE +FROM ghcr.io/agoric/agoric-sdk:36 as propose-agoric-upgrade-12 +# TODO: Replace with actual Zoe core proposal for upgrade 12 (MCS, Kread, Zoe, restart-contracts, etc) +ARG BOOTSTRAP_MODE UPGRADE_INFO_12='{"coreProposals":["@agoric/builders/scripts/vats/init-network.js"]}' +ENV THIS_NAME=propose-agoric-upgrade-12 UPGRADE_TO=agoric-upgrade-12 UPGRADE_INFO=${UPGRADE_INFO_12} BOOTSTRAP_MODE=${BOOTSTRAP_MODE} +COPY --from=agoric-upgrade-11 /root/.agoric /root/.agoric +# start-chain boilerplate WORKDIR /usr/src/agoric-sdk/ COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./upgrade-test-scripts/ COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ -COPY --from=agoric-upgrade-10-to-11 /root/.agoric /root/.agoric +RUN chmod +x ./upgrade-test-scripts/*.sh +SHELL ["/bin/bash", "-c"] +RUN . ./upgrade-test-scripts/start_to_to.sh + +# DEST (TEST) +#this is agoric-upgrade-12 / multi-collateral, etc. +ARG DEST_IMAGE +FROM ${DEST_IMAGE} as agoric-upgrade-12 +ARG BOOTSTRAP_MODE +ENV THIS_NAME=agoric-upgrade-12 BOOTSTRAP_MODE=${BOOTSTRAP_MODE} +COPY --from=propose-agoric-upgrade-12 /root/.agoric /root/.agoric +# start-chain boilerplate +WORKDIR /usr/src/agoric-sdk/ +COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./package.json ./*.mjs ./upgrade-test-scripts/ +COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ RUN apt install -y tmux SHELL ["/bin/bash", "-c"] RUN chmod +x ./upgrade-test-scripts/*.sh +# enter image in interactive shell ENTRYPOINT /usr/src/agoric-sdk/upgrade-test-scripts/start_to_to.sh diff --git a/packages/deployment/upgrade-test/Makefile b/packages/deployment/upgrade-test/Makefile index 8514195248f..5d3829c89ba 100644 --- a/packages/deployment/upgrade-test/Makefile +++ b/packages/deployment/upgrade-test/Makefile @@ -2,7 +2,7 @@ REPOSITORY = agoric/upgrade-test # use :dev (latest prerelease image) unless we build local sdk DEST_IMAGE ?= $(if $(findstring local_sdk,$(MAKECMDGOALS)),ghcr.io/agoric/agoric-sdk:latest,ghcr.io/agoric/agoric-sdk:dev) BOOTSTRAP_MODE?=main -TARGET?=agoric-upgrade-11 +TARGET?=agoric-upgrade-12 dockerLabel?=$(TARGET) ifdef TMUX_CC tmuxCC=1 @@ -33,12 +33,18 @@ agoric-upgrade-9: agoric-upgrade-8-1 agoric-upgrade-10: agoric-upgrade-9 $(BUILD) --target agoric-upgrade-10 -t $(REPOSITORY):agoric-upgrade-10 -agoric-upgrade-10-to-11: agoric-upgrade-10 - $(BUILD) --target agoric-upgrade-10-to-11 -t $(REPOSITORY):agoric-upgrade-10-to-11 +propose-agoric-upgrade-11: agoric-upgrade-10 + $(BUILD) --target propose-agoric-upgrade-11 -t $(REPOSITORY):propose-agoric-upgrade-11 -agoric-upgrade-11: agoric-upgrade-10-to-11 +agoric-upgrade-11: propose-agoric-upgrade-11 $(BUILD) --target agoric-upgrade-11 -t $(REPOSITORY):agoric-upgrade-11 +propose-agoric-upgrade-12: agoric-upgrade-11 + $(BUILD) --target propose-agoric-upgrade-12 -t $(REPOSITORY):propose-agoric-upgrade-12$(TAG_SUFFIX) + +agoric-upgrade-12: propose-agoric-upgrade-12 + $(BUILD) --target agoric-upgrade-12 -t $(REPOSITORY):agoric-upgrade-12$(TAG_SUFFIX) + # build main bootstrap build: $(TARGET) @@ -57,4 +63,4 @@ run: --entrypoint /usr/src/agoric-sdk/upgrade-test-scripts/start_to_to.sh \ $(REPOSITORY):$(dockerLabel) -.PHONY: local_sdk agoric-upgrade-7-2 agoric-upgrade-8 agoric-upgrade-8-1 agoric-upgrade-9 agoric-upgrade-10 agoric-upgrade-11 build build_test run +.PHONY: local_sdk agoric-upgrade-7-2 agoric-upgrade-8 agoric-upgrade-8-1 agoric-upgrade-9 agoric-upgrade-10 agoric-upgrade-11 agoric-upgrade-12 build build_test run diff --git a/packages/deployment/upgrade-test/Readme.md b/packages/deployment/upgrade-test/Readme.md index 3b3e233ecb4..44a6ce44268 100644 --- a/packages/deployment/upgrade-test/Readme.md +++ b/packages/deployment/upgrade-test/Readme.md @@ -102,6 +102,21 @@ docker exec -it sweet_edison bash To make the wallet ui talk to your local chain, set the network config to `https://local.agoric.net/network-config` +## To add an upgrade + +1. Update the upgrade handler in app.go +2. Duplicate the last pair of UPGRADE and TEST blocks +3. Update their number from the UPGRADE / DEST block at the end +4. Make directory for tests (e.g. `agoric-upgrade-12`) +4. Make directory for ugprade (e.g. `propose-agoric-upgrade-12` with a `.keep`) +5. Update the UPGRADE/DEST pair to be your new upgrade (THIS_NAME matching the upgrade handler string in app.go) +6. Update the `Makefile` + - the two targets to `Makefile` (e.g. `propose-agoric-upgrade-12` and `agoric-upgrade-12`) + - set the default TARGET (e.g. `agoric-upgrade-12`) + - add the DEST target to the `.phony` in `Makefile` +7. Test with `make local_sdk build run` + + ## Development You can iterate on a particular upgrade by targeting. When you exit and run again, it will be a fresh state. 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 index cad2ee8fb01..fb6e66db7e5 100755 --- 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 @@ -46,22 +46,3 @@ agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$OFFER" --keyring-bac test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault3 -o jsonlines | jq -r '.vaultState') "closed" "vault3 is closed" test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault3 -o jsonlines | jq -r '.locked.value') "0" "vault3 contains no collateral" test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault3 -o jsonlines | jq -r '.debtSnapshot.debt.value') "0" "vault3 has no debt" - -upgrade11=$SDK/upgrade-test-scripts/agoric-upgrade-11 -cd $upgrade11 - -## build proposal and install bundles -./tools/mint-ist.sh -./wallet-all-ertp/wf-install-bundles.sh - -## upgrade wallet factory -./wallet-all-ertp/wf-propose.sh - -## start game1 -./wallet-all-ertp/wf-game-propose.sh - -# Pay 0.25IST join the game and get some places -node ./wallet-all-ertp/gen-game-offer.mjs Shire Mordor >/tmp/,join.json -agops perf satisfaction --from $GOV1ADDR --executeOffer /tmp/,join.json --keyring-backend=test - -cd $SDK diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre_test.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre_test.sh index ac0f8f4ecc6..05eca38550c 100755 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre_test.sh +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre_test.sh @@ -5,11 +5,6 @@ echo Wait for upgrade to settle waitForBlock 5 -# CWD is agoric-sdk -upgrade11=./upgrade-test-scripts/agoric-upgrade-11 - -test_val "$(agd query vstorage children published.boardAux -o json | jq .children)" "[]" "no boardAux children yet" - # validate agoric-upgrade-10 metrics after update test_val $(agd q vstorage children published.vaultFactory.managers.manager0.vaults -o json | jq -r '.children | length') 3 "we have three vaults" diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/test.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/test.sh index 53d04c4beed..73c816c6fae 100755 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/test.sh +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/test.sh @@ -5,9 +5,6 @@ echo Wait for actions to settle waitForBlock 2 -# CWD is agoric-sdk -upgrade11=./upgrade-test-scripts/agoric-upgrade-11 - # verify swing-store export-data is consistent and perform genesis style "upgrade" killAgd EXPORT_DIR=$(mktemp -t -d swing-store-export-upgrade-11-XXX) @@ -23,45 +20,3 @@ mv $TMP_GENESIS_DIR/priv_validator_state.json $HOME/.agoric/data mv $TMP_GENESIS_DIR/* $HOME/.agoric/config/ rm -rf $EXPORT_DIR startAgd - -testMinChildren() { - path=$1 - min=$2 - line="$(agd query vstorage children $path -o jsonlines)" - ok=$(echo $line | jq ".children | length | . > $min") - test_val "$ok" "true" "$path: more than $min children" -} - -# Check brand aux data for more than just vbank assets -testMinChildren published.boardAux 3 - -testDisplayInfo() { - name=$1 - expected=$2 - - line="$(agoric follow -lF :published.agoricNames.brand -o text)" - # find brand by name, then corresponding slot - id=$(echo $line | jq --arg name "$name" -r '.slots as $slots | .body | gsub("^#";"") | fromjson | .[] | select(.[0] == $name) | .[1] | capture("^[$](?0|[1-9][0-9]*)") | .slot | $slots[. | tonumber]') - echo $name Id: $id - - line="$(agoric follow -lF :published.boardAux.$id -o jsonlines)" - displayInfo="$(echo $line | jq -c .displayInfo)" - test_val "$displayInfo" "$expected" "$name displayInfo from boardAux" -} - -testDisplayInfo IST '{"assetKind":"nat","decimalPlaces":6}' - -testPurseValuePayload() { - addr=$1 - wkAsset=$2 - expected=$3 - - line="$(agoric follow -lF :published.wallet.$addr.current -o jsonlines)" - # HACK: selecting brand by allegedName - payload=$(echo $line | jq --arg name "$wkAsset" -c '.purses[] | select(.brand | contains($name)) | .balance.value.payload') - test_val "$payload" "$expected" "$wkAsset purse for $addr" -} - -# Smart wallet handles game Place assets? -testDisplayInfo Place '{"assetKind":"copyBag"}' -testPurseValuePayload $GOV1ADDR Place '[["Shire","1"],["Mordor","1"]]' diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/.gitignore b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/.gitignore similarity index 100% rename from packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/.gitignore rename to packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/.gitignore diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.sh new file mode 100755 index 00000000000..62efb399d07 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +# Dockerfile in upgrade-test sets: +# WORKDIR /usr/src/agoric-sdk/ +# Overriding it during development has occasionally been useful. +SDK=${SDK:-/usr/src/agoric-sdk} +. $SDK/upgrade-test-scripts/env_setup.sh + +# Enable debugging +set -x + +AGUP=$SDK/upgrade-test-scripts/agoric-upgrade-12 +cd $AGUP + +## build proposal and install bundles +waitForBlock 2 +./tools/mint-ist.sh +./wallet-all-ertp/wf-install-bundles.sh + +## upgrade wallet factory +./wallet-all-ertp/wf-propose.sh + +## start game1 +./wallet-all-ertp/wf-game-propose.sh + +# Pay 0.25IST join the game and get some places +node ./wallet-all-ertp/gen-game-offer.mjs Shire Mordor >/tmp/,join.json +agops perf satisfaction --from $GOV1ADDR --executeOffer /tmp/,join.json --keyring-backend=test + +cd $SDK + +###################################################################### +# FIXME: remove this line when these tests don't hardcode bundle hashes. +echo 1>&2 "FIXME: skipping zoe-full-upgrade tests"; return 0 + +# Pre-steps: +# * fill Wallets +# * build and install bundles +# * create instance of prober contract and run expecting no atomicRearrange +# +# Action: +# * upgrade Zoe and ZCF +# +# Finish +# * create instance of prober contract and run expecting to see atomicRearrange + +yarn --silent bundle-source --cache-json /tmp packages/zoe/src/contractFacet/vatRoot.js Zcf-upgrade +yarn --silent bundle-source --cache-json /tmp packages/vats/src/vat-zoe.js Zoe-upgrade +yarn --silent bundle-source --cache-json /tmp packages/boot/test/bootstrapTests/zcfProbe.js prober-contract + +echo +++ checking Zoe/Zcf hashes +++ +ZCF_HASH=`jq -r .endoZipBase64Sha512 /tmp/bundle-Zcf-upgrade.json` +ZOE_HASH=`jq -r .endoZipBase64Sha512 /tmp/bundle-Zoe-upgrade.json` +echo bundle-Zcf-upgrade.json $ZCF_HASH +grep $ZCF_HASH $AGUP/zoe-full-upgrade/zcf-upgrade-script.js || exit 1 +echo bundle-Zoe-upgrade.json $ZOE_HASH +grep $ZOE_HASH $AGUP/zoe-full-upgrade/zcf-upgrade-script.js || exit 1 + +echo +++ prober hash +++ +PROBER_HASH=`jq -r .endoZipBase64Sha512 /tmp/bundle-prober-contract.json` +echo bundle-prober-contract.json $PROBER_HASH +grep $PROBER_HASH $AGUP/zoe-full-upgrade/run-prober-script.js || exit 1 + +echo +++++ fill wallet +++++ +agd tx bank send validator $GOV1ADDR 12340000000${ATOM_DENOM} --from validator --chain-id agoriclocal --keyring-backend test --yes +agops vaults open --wantMinted 10000 --giveCollateral 2000 > wantIST +agops perf satisfaction --executeOffer wantIST --from gov1 --keyring-backend test + + +echo +++++ install bundles +++++ +for f in /tmp/bundle-{Z*-upgrade,prober-contract}.json; do + echo installing $f + agd tx swingset install-bundle "@$f" \ + --from gov1 --keyring-backend=test --gas=auto \ + --chain-id=agoriclocal -bblock --yes +done + + +echo +++++ Run prober first time +++++ +$AGUP/zoe-full-upgrade/run-prober.sh +test_val "$(agd query vstorage data published.prober-asid9a -o jsonlines | jq -r '.value' | jq -r '.values[0]')" "false" "Prober calling zcf.atomicReallocate()" + + +# upgrade zoe to a version that can change which ZCF is installed; tell Zoe to +# use a new version of ZCF. THIS MATCHES THE UPGRADE OF THE LIVE CHAIN +echo +++++ upgrade Zoe and ZCF +++++ +$AGUP/zoe-full-upgrade/zcf-upgrade-driver.sh + + +echo +++++ Run prober second time +++++ +# Re-run prober test and expect internal atomicRearrange. +$AGUP/zoe-full-upgrade/run-prober.sh +test_val "$(agd query vstorage data published.prober-asid9a -o jsonlines | jq -r '.value' | jq -r '.values[0]')" "true" "Prober called zcf.atomicReallocate()" diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/env_setup.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/env_setup.sh new file mode 100644 index 00000000000..c221fd9a60f --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/env_setup.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +# agoric-upgrade-12 specific env here... diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh new file mode 100755 index 00000000000..334821210f7 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +. ./upgrade-test-scripts/env_setup.sh + +echo Wait for upgrade to settle +waitForBlock 5 + +# CWD is agoric-sdk +upgrade12=./upgrade-test-scripts/agoric-upgrade-12 + +test_val "$(agd query vstorage children published.boardAux -o json | jq .children)" "[]" "no boardAux children yet" + +# zoe vat is at incarnation 0 +test_val "$(yarn --silent node $upgrade12/tools/vat-status.mjs zoe)" "0" "zoe vat incarnation" diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/test.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/test.sh new file mode 100755 index 00000000000..ad007522b6a --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/test.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +. ./upgrade-test-scripts/env_setup.sh + +echo Wait for actions to settle +waitForBlock 2 + +# CWD is agoric-sdk +upgrade12=./upgrade-test-scripts/agoric-upgrade-12 + + +testMinChildren() { + path=$1 + min=$2 + line="$(agd query vstorage children $path -o jsonlines)" + ok=$(echo $line | jq ".children | length | . > $min") + test_val "$ok" "true" "$path: more than $min children" +} + +# Check brand aux data for more than just vbank assets +testMinChildren published.boardAux 3 + +testDisplayInfo() { + name=$1 + expected=$2 + + line="$(agoric follow -lF :published.agoricNames.brand -o text)" + # find brand by name, then corresponding slot + id=$(echo $line | jq --arg name "$name" -r '.slots as $slots | .body | gsub("^#";"") | fromjson | .[] | select(.[0] == $name) | .[1] | capture("^[$](?0|[1-9][0-9]*)") | .slot | $slots[. | tonumber]') + echo $name Id: $id + + line="$(agoric follow -lF :published.boardAux.$id -o jsonlines)" + displayInfo="$(echo $line | jq -c .displayInfo)" + test_val "$displayInfo" "$expected" "$name displayInfo from boardAux" +} + +testDisplayInfo IST '{"assetKind":"nat","decimalPlaces":6}' + +testPurseValuePayload() { + addr=$1 + wkAsset=$2 + expected=$3 + + line="$(agoric follow -lF :published.wallet.$addr.current -o jsonlines)" + # HACK: selecting brand by allegedName + payload=$(echo $line | jq --arg name "$wkAsset" -c '.purses[] | select(.brand | contains($name)) | .balance.value.payload') + test_val "$payload" "$expected" "$wkAsset purse for $addr" +} + +# Smart wallet handles game Place assets? +testDisplayInfo Place '{"assetKind":"copyBag"}' +testPurseValuePayload $GOV1ADDR Place '[["Shire","1"],["Mordor","1"]]' + +# zoe vat is at incarnation 1 +echo "FIXME: bypassed zoe-full-upgrade validation"; return 0 +test_val "$(yarn --silent node $upgrade12/tools/vat-status.mjs zoe)" "1" "zoe vat incarnation" diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/tools/mint-ist.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/mint-ist.sh similarity index 100% rename from packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/tools/mint-ist.sh rename to packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/mint-ist.sh diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/tools/parseProposals.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/parseProposals.mjs similarity index 100% rename from packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/tools/parseProposals.mjs rename to packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/parseProposals.mjs diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/vat-status.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/vat-status.mjs new file mode 100644 index 00000000000..63b0fe53a16 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/vat-status.mjs @@ -0,0 +1,111 @@ +// @ts-check +import processAmbient from 'process'; +import dbOpenAmbient from 'better-sqlite3'; + +/** + * @file look up vat incarnation from kernel DB + * @see {main} + */ + +const swingstorePath = '~/.agoric/data/agoric/swingstore.sqlite'; + +/** + * SQL short-hand + * + * @param {import('better-sqlite3').Database} db + */ +const dbTool = db => { + const prepare = (strings, ...params) => { + const dml = strings.join('?'); + return { stmt: db.prepare(dml), params }; + }; + const sql = (strings, ...args) => { + const { stmt, params } = prepare(strings, ...args); + return stmt.all(...params); + }; + sql.get = (strings, ...args) => { + const { stmt, params } = prepare(strings, ...args); + return stmt.get(...params); + }; + return sql; +}; + +/** + * @param {import('better-sqlite3').Database} db + */ +const makeSwingstore = db => { + const sql = dbTool(db); + + /** @param {string} key */ + const kvGet = key => sql.get`select * from kvStore where key = ${key}`.value; + /** @param {string} key */ + const kvGetJSON = key => JSON.parse(kvGet(key)); + + /** @param {string} vatID */ + const lookupVat = vatID => { + return Object.freeze({ + source: () => kvGetJSON(`${vatID}.source`), + options: () => kvGetJSON(`${vatID}.options`), + currentSpan: () => + sql.get`select * from transcriptSpans where isCurrent = 1 and vatID = ${vatID}`, + }); + }; + + return Object.freeze({ + /** @param {string} vatName */ + findVat: vatName => { + /** @type {string[]} */ + const dynamicIDs = kvGetJSON('vat.dynamicIDs'); + const targetVat = dynamicIDs.find( + vatID => lookupVat(vatID).options().name === vatName, + ); + if (!targetVat) throw Error(vatName); + return targetVat; + }, + lookupVat, + }); +}; + +/** @type {(val: T | undefined) => T} */ +const NonNullish = val => { + if (!val) throw Error('required'); + return val; +}; + +/** + * @param {string[]} argv + * @param {{ dbOpen: typeof import('better-sqlite3'), HOME?: string }} io + */ +const main = async (argv, { dbOpen, HOME }) => { + const [_node, _script, vatName] = argv; + if (!vatName) throw Error('vatName required'); + + const fullPath = swingstorePath.replace(/^~/, NonNullish(HOME)); + const kStore = makeSwingstore(dbOpen(fullPath, { readonly: true })); + + const vatID = kStore.findVat(vatName); + const vatInfo = kStore.lookupVat(vatID); + + const source = vatInfo.source(); + const { incarnation } = vatInfo.currentSpan(); + + // misc info to stderr + console.error(JSON.stringify({ vatName, vatID, incarnation, ...source })); + + // incarnation to stdout + console.log(incarnation); +}; + +processAmbient.exitCode = 1; +main(processAmbient.argv, { + dbOpen: dbOpenAmbient, + HOME: processAmbient.env.HOME, +}).then( + () => { + processAmbient.exitCode = 0; + }, + err => { + console.error('Failed with', err); + processAmbient.exit(processAmbient.exitCode || 1); + }, +); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/gen-game-offer.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/wallet-all-ertp/gen-game-offer.mjs similarity index 100% rename from packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/gen-game-offer.mjs rename to packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/wallet-all-ertp/gen-game-offer.mjs 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-12/wallet-all-ertp/wf-game-propose.sh similarity index 87% rename from packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/wf-game-propose.sh rename to packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/wallet-all-ertp/wf-game-propose.sh index 80b1e1d41b1..80c5e417eec 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-12/wallet-all-ertp/wf-game-propose.sh @@ -3,13 +3,13 @@ # Propose and carry out starting game contract SDK=${SDK:-/usr/src/agoric-sdk} -UP11=${UP11:-$SDK/upgrade-test-scripts/agoric-upgrade-11} -WFUP=${WFUP:-$UP11/wallet-all-ertp} +UP12=${UP12:-$SDK/upgrade-test-scripts/agoric-upgrade-12} +WFUP=${WFUP:-$UP12/wallet-all-ertp} cd $WFUP . $SDK/upgrade-test-scripts/env_setup.sh -. $UP11/env_setup.sh +. $UP12/env_setup.sh TITLE="Start Game1 Contract" 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-12/wallet-all-ertp/wf-install-bundles.sh similarity index 83% rename from packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/wallet-all-ertp/wf-install-bundles.sh rename to packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/wallet-all-ertp/wf-install-bundles.sh index 7b58aa16539..a7fa36fdcfe 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-12/wallet-all-ertp/wf-install-bundles.sh @@ -5,15 +5,15 @@ set -e SDK=${SDK:-/usr/src/agoric-sdk} -UP11=${UP11:-$SDK/upgrade-test-scripts/agoric-upgrade-11} +UP12=${UP12:-$SDK/upgrade-test-scripts/agoric-upgrade-12} -cd $UP11/wallet-all-ertp +cd $UP12/wallet-all-ertp echo +++ run walletFactory, game upgrade proposal builders +++ (agoric run $SDK/packages/vats/scripts/build-walletFactory-upgrade.js; \ agoric run $SDK/packages/vats/scripts/build-game1-start.js )>/tmp/,run.log -bundles=$($UP11/tools/parseProposals.mjs Date: Mon, 18 Sep 2023 13:35:36 -0400 Subject: [PATCH 07/35] fix(vstorage)!: Enforce path validation Fixes #8337 --- golang/cosmos/x/vstorage/types/path_keys.go | 32 ++++--- .../cosmos/x/vstorage/types/path_keys_test.go | 90 ++++++++++++++++--- packages/internal/src/lib-chainStorage.js | 1 + 3 files changed, 101 insertions(+), 22 deletions(-) diff --git a/golang/cosmos/x/vstorage/types/path_keys.go b/golang/cosmos/x/vstorage/types/path_keys.go index 297022a903e..60703798c5d 100644 --- a/golang/cosmos/x/vstorage/types/path_keys.go +++ b/golang/cosmos/x/vstorage/types/path_keys.go @@ -7,9 +7,17 @@ import ( "strings" ) -// - A "path" is a sequence of zero or more dot-separated nonempty strings of -// 7-bit non-nul, non-dot ASCII characters. So `""`, `"foo"`, and -// `"foo.bar.baz"` are paths but `"."`, "foo.", and "fo\0o" are not. +// - A "path" is a sequence of zero or more dot-separated nonempty segments +// using a restricted alphabet of ASCII alphanumerics plus underscore and dash, +// consistent with packages/internal/src/lib-chainStorage.js but not currently +// enforcing a length restriction on path segments. +// So `""`, `"foo"`, and `"foo.bar__baz.qux--quux"` are paths but `"."`, +// `"foo/bar"`, `"fo\to"`, and `"foö"` are not. +// This alphabet might be expanded in the future, but such expansion SHOULD NOT +// include control characters (including those that are not ASCII, such as +// U+202E RIGHT-TO-LEFT OVERRIDE), slash `/` (which separates ABCI request path +// segments in e.g. `custom/vstorage/data/foo`), or backslash `\` (which should +// be reserved for adding escape sequences). // // - An encoded key for a path is the path prefixed with its length (in ASCII // digits), separated by nul, followed by the path with dots replaced with nul. @@ -42,22 +50,26 @@ func EncodedKeyToPath(key []byte) string { return string(pathBytes) } -var pathPattern = regexp.MustCompile(`[-a-zA-Z0-9_` + PathSeparator + `]*`) +var pathSegmentPattern = `[a-zA-Z0-9_-]+` +var pathSeparatorPattern = `\` + PathSeparator +var pathPattern = fmt.Sprintf(`^$|^%[1]s(%[2]s%[1]s)*$`, pathSegmentPattern, pathSeparatorPattern) +var pathMatcher = regexp.MustCompile(pathPattern) func ValidatePath(path string) error { - if !pathPattern.MatchString(path) { - return fmt.Errorf("path %q contains invalid characters", path) - } - if strings.Contains(path, PathSeparator+PathSeparator) { - return fmt.Errorf("path %q contains doubled separators", path) + if pathMatcher.MatchString(path) { + return nil } + // Rescan the string to give a useful error message. if strings.HasPrefix(path, PathSeparator) { return fmt.Errorf("path %q starts with separator", path) } if strings.HasSuffix(path, PathSeparator) { return fmt.Errorf("path %q ends with separator", path) } - return nil + if strings.Contains(path, PathSeparator+PathSeparator) { + return fmt.Errorf("path %q contains doubled separators", path) + } + return fmt.Errorf("path %q contains invalid characters", path) } // PathToEncodedKey converts a path to a byte slice key diff --git a/golang/cosmos/x/vstorage/types/path_keys_test.go b/golang/cosmos/x/vstorage/types/path_keys_test.go index e56eb5dfb23..4ad23f6edb5 100644 --- a/golang/cosmos/x/vstorage/types/path_keys_test.go +++ b/golang/cosmos/x/vstorage/types/path_keys_test.go @@ -2,40 +2,106 @@ package types import ( "bytes" + "fmt" + "strings" "testing" ) func Test_Key_Encoding(t *testing.T) { tests := []struct { - name string - childStr string - key []byte + name string + childStr string + key []byte + errContains string }{ { - name: "empty key is prefixed", + name: "empty path", childStr: "", key: []byte("0\x00"), }, { - name: "some key string", + name: "single-segment path", childStr: "some", key: []byte("1\x00some"), }, { - name: "dot-separated", + name: "multi-segment path", childStr: "some.child.grandchild", key: []byte("3\x00some\x00child\x00grandchild"), }, + { + name: "non-letters", + childStr: "-_0_-", + key: []byte("1\x00-_0_-"), + }, + { + name: "lone dot", + childStr: ".", + errContains: "starts with separator", + }, + { + name: "starts with dot", + childStr: ".foo", + errContains: "starts with separator", + }, + { + name: "ends with dot", + childStr: "foo.", + errContains: "ends with separator", + }, + { + name: "empty path segment", + childStr: "foo..bar", + errContains: "doubled separators", + }, + { + name: "invalid path character U+0000 NUL", + childStr: "foo\x00bar", + errContains: "invalid character", + }, + { + name: "invalid path character U+002F SOLIDUS", + childStr: "foo/bar", + errContains: "invalid character", + }, + { + name: "invalid path character U+005C REVERSE SOLIDUS", + childStr: "foo\\bar", + errContains: "invalid character", + }, + { + name: "invalid path character U+007C VERTICAL LINE", + childStr: "foo|bar", + errContains: "invalid character", + }, } for _, tt := range tests { + if tt.key != nil { + t.Run(tt.name, func(t *testing.T) { + if key := PathToEncodedKey(tt.childStr); !bytes.Equal(key, tt.key) { + t.Errorf("pathToKey(%q) = %v, want %v", tt.childStr, key, tt.key) + } + if childStr := EncodedKeyToPath(tt.key); childStr != tt.childStr { + t.Errorf("keyToString(%v) = %q, want %q", tt.key, childStr, tt.childStr) + } + }) + continue + } + expect := tt.errContains t.Run(tt.name, func(t *testing.T) { - if key := PathToEncodedKey(tt.childStr); !bytes.Equal(key, tt.key) { - t.Errorf("pathToKey(%q) = %v, want %v", tt.childStr, key, tt.key) - } - if childStr := EncodedKeyToPath(tt.key); childStr != tt.childStr { - t.Errorf("keyToString(%v) = %q, want %q", tt.key, childStr, tt.childStr) - } + var key []byte + defer func() { + if err := recover(); err != nil { + errStr := fmt.Sprintf("%v", err) + if !strings.Contains(errStr, expect) { + t.Errorf("pathToKey(%q) = error %q, want error %v", tt.childStr, errStr, expect) + } + } else { + t.Errorf("pathToKey(%q) = []byte(%q), want error %v", tt.childStr, key, expect) + } + }() + key = PathToEncodedKey(tt.childStr) }) } } diff --git a/packages/internal/src/lib-chainStorage.js b/packages/internal/src/lib-chainStorage.js index 5e55cf3f1f7..e47d7403c50 100644 --- a/packages/internal/src/lib-chainStorage.js +++ b/packages/internal/src/lib-chainStorage.js @@ -126,6 +126,7 @@ harden(unmarshalFromVstorage); // Must be nonempty and disallow (unescaped) `.`, and for simplicity // (and future possibility of e.g. escaping) we currently limit to // ASCII alphanumeric plus underscore and dash. +// Should remain consistent with golang/cosmos/x/vstorage/types/path_keys.go const pathSegmentPattern = /^[a-zA-Z0-9_-]{1,100}$/; /** @type {(name: string) => void} */ From b366faa62677a8bda60525f2069d5bd7aa0654d6 Mon Sep 17 00:00:00 2001 From: Mathieu Hofman Date: Thu, 31 Aug 2023 03:04:29 +0000 Subject: [PATCH 08/35] chore(deployment): shortcut to run upgrade test non-interactive --- packages/deployment/upgrade-test/Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/deployment/upgrade-test/Makefile b/packages/deployment/upgrade-test/Makefile index 5d3829c89ba..c6164ea53ea 100644 --- a/packages/deployment/upgrade-test/Makefile +++ b/packages/deployment/upgrade-test/Makefile @@ -56,11 +56,14 @@ DEBUG ?= SwingSet:ls,SwingSet:vat RUN = docker run --rm -it \ -p 26656:26656 -p 26657:26657 -p 1317:1317 \ -v "$${PWD}:/workspace" \ - -e "DEST=1" -e "DEBUG=$(DEBUG)" + -e "DEBUG=$(DEBUG)" run: - $(RUN) -e "TMUX_USE_CC=$(tmuxCC)" \ + $(RUN) -e "DEST=1" -e "TMUX_USE_CC=$(tmuxCC)" \ --entrypoint /usr/src/agoric-sdk/upgrade-test-scripts/start_to_to.sh \ $(REPOSITORY):$(dockerLabel) +run_test: + $(RUN) -e "DEST=0" $(REPOSITORY):$(dockerLabel) + .PHONY: local_sdk agoric-upgrade-7-2 agoric-upgrade-8 agoric-upgrade-8-1 agoric-upgrade-9 agoric-upgrade-10 agoric-upgrade-11 agoric-upgrade-12 build build_test run From 645f1e386788707ce23ccf1fee9b4b70adcf5f0c Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 18 Sep 2023 13:43:31 -0400 Subject: [PATCH 09/35] chore(vstorage): Improve path/key testing --- .../cosmos/x/vstorage/types/path_keys_test.go | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/golang/cosmos/x/vstorage/types/path_keys_test.go b/golang/cosmos/x/vstorage/types/path_keys_test.go index 4ad23f6edb5..0d9972e0907 100644 --- a/golang/cosmos/x/vstorage/types/path_keys_test.go +++ b/golang/cosmos/x/vstorage/types/path_keys_test.go @@ -10,68 +10,68 @@ import ( func Test_Key_Encoding(t *testing.T) { tests := []struct { name string - childStr string + path string key []byte errContains string }{ { - name: "empty path", - childStr: "", - key: []byte("0\x00"), + name: "empty path", + path: "", + key: []byte("0\x00"), }, { - name: "single-segment path", - childStr: "some", - key: []byte("1\x00some"), + name: "single-segment path", + path: "some", + key: []byte("1\x00some"), }, { - name: "multi-segment path", - childStr: "some.child.grandchild", - key: []byte("3\x00some\x00child\x00grandchild"), + name: "multi-segment path", + path: "some.child.grandchild", + key: []byte("3\x00some\x00child\x00grandchild"), }, { - name: "non-letters", - childStr: "-_0_-", - key: []byte("1\x00-_0_-"), + name: "non-letters", + path: "-_0_-", + key: []byte("1\x00-_0_-"), }, { name: "lone dot", - childStr: ".", + path: ".", errContains: "starts with separator", }, { name: "starts with dot", - childStr: ".foo", + path: ".foo", errContains: "starts with separator", }, { name: "ends with dot", - childStr: "foo.", + path: "foo.", errContains: "ends with separator", }, { name: "empty path segment", - childStr: "foo..bar", + path: "foo..bar", errContains: "doubled separators", }, { name: "invalid path character U+0000 NUL", - childStr: "foo\x00bar", + path: "foo\x00bar", errContains: "invalid character", }, { name: "invalid path character U+002F SOLIDUS", - childStr: "foo/bar", + path: "foo/bar", errContains: "invalid character", }, { name: "invalid path character U+005C REVERSE SOLIDUS", - childStr: "foo\\bar", + path: "foo\\bar", errContains: "invalid character", }, { name: "invalid path character U+007C VERTICAL LINE", - childStr: "foo|bar", + path: "foo|bar", errContains: "invalid character", }, } @@ -79,11 +79,11 @@ func Test_Key_Encoding(t *testing.T) { for _, tt := range tests { if tt.key != nil { t.Run(tt.name, func(t *testing.T) { - if key := PathToEncodedKey(tt.childStr); !bytes.Equal(key, tt.key) { - t.Errorf("pathToKey(%q) = %v, want %v", tt.childStr, key, tt.key) + if key := PathToEncodedKey(tt.path); !bytes.Equal(key, tt.key) { + t.Errorf("pathToKey(%q) = []byte(%q), want []byte(%q)", tt.path, key, tt.key) } - if childStr := EncodedKeyToPath(tt.key); childStr != tt.childStr { - t.Errorf("keyToString(%v) = %q, want %q", tt.key, childStr, tt.childStr) + if path := EncodedKeyToPath(tt.key); path != tt.path { + t.Errorf("keyToPath([]byte(%q)) = %q, want %q", tt.key, path, tt.path) } }) continue @@ -95,13 +95,13 @@ func Test_Key_Encoding(t *testing.T) { if err := recover(); err != nil { errStr := fmt.Sprintf("%v", err) if !strings.Contains(errStr, expect) { - t.Errorf("pathToKey(%q) = error %q, want error %v", tt.childStr, errStr, expect) + t.Errorf("pathToKey(%q) = error %q, want error %v", tt.path, errStr, expect) } } else { - t.Errorf("pathToKey(%q) = []byte(%q), want error %v", tt.childStr, key, expect) + t.Errorf("pathToKey(%q) = []byte(%q), want error %v", tt.path, key, expect) } }() - key = PathToEncodedKey(tt.childStr) + key = PathToEncodedKey(tt.path) }) } } From 0a3ac9a42527f5b9f097b0a8a946ab12479d2b2b Mon Sep 17 00:00:00 2001 From: Ikenna Omekam Date: Thu, 7 Sep 2023 17:35:37 -0400 Subject: [PATCH 10/35] test: move ag11 and ag12 to JS --- packages/deployment/upgrade-test/Dockerfile | 23 +- .../{actions.mjs => actions.js} | 68 +---- .../agoric-upgrade-10/actions.test.js | 18 +- .../agoric-upgrade-10/post.test.js | 6 +- .../agoric-upgrade-10/pre.test.js | 9 +- .../{upgradeHelpers.mjs => upgradeHelpers.js} | 12 +- .../agoric-upgrade-11/.keep | 0 .../agoric-upgrade-11/actions.sh | 48 --- .../agoric-upgrade-11/actions.test.js | 23 ++ .../agoric-upgrade-11/env_setup.sh | 153 ---------- .../agoric-upgrade-11/legacy.sh | 104 +++++++ .../agoric-upgrade-11/post.test.js | 5 + .../agoric-upgrade-11/pre.test.js | 53 ++++ .../agoric-upgrade-11/pre_test.sh | 27 -- .../agoric-upgrade-11/test.sh | 22 -- .../agoric-upgrade-12/actions.js | 133 +++++++++ .../agoric-upgrade-12/actions.sh | 93 ------ .../agoric-upgrade-12/actions.test.js | 74 +++++ .../agoric-upgrade-12/env_setup.sh | 3 - .../agoric-upgrade-12/post.test.js | 7 + .../agoric-upgrade-12/pre.test.js | 20 ++ .../agoric-upgrade-12/pre_test.sh | 14 - .../agoric-upgrade-12/test.sh | 56 ---- .../agoric-upgrade-12/tools/mint-ist.sh | 16 - .../tools/parseProposals.mjs | 41 --- .../tools/{vat-status.mjs => vat-status.js} | 31 +- .../wallet-all-ertp/gen-game-offer.mjs | 116 -------- .../wallet-all-ertp/wf-game-propose.sh | 32 -- .../wallet-all-ertp/wf-install-bundles.sh | 34 --- .../wallet-all-ertp/wf-propose.sh | 37 --- .../{cliHelper.mjs => cliHelper.js} | 23 +- .../commonUpgradeHelpers.js | 278 ++++++++++++++++++ .../{constants.mjs => constants.js} | 2 + .../coreUpgradeHelpers.mjs | 133 --------- .../upgrade-test-scripts/econHelpers.js | 73 +++++ .../upgrade-test-scripts/package.json | 6 +- .../upgrade-test-scripts/start_to_to.sh | 1 - 37 files changed, 846 insertions(+), 948 deletions(-) rename packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/{actions.mjs => actions.js} (84%) rename packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/{upgradeHelpers.mjs => upgradeHelpers.js} (90%) delete mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/.keep delete mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/actions.sh create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/actions.test.js delete mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/env_setup.sh create mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/legacy.sh create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/post.test.js create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre.test.js delete mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre_test.sh delete mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/test.sh create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.js delete mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.sh create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.test.js delete mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/env_setup.sh create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/post.test.js create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre.test.js delete mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh delete mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/test.sh delete mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/mint-ist.sh delete mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/parseProposals.mjs rename packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/{vat-status.mjs => vat-status.js} (75%) delete mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/wallet-all-ertp/gen-game-offer.mjs delete mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/wallet-all-ertp/wf-game-propose.sh delete mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/wallet-all-ertp/wf-install-bundles.sh delete mode 100755 packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/wallet-all-ertp/wf-propose.sh rename packages/deployment/upgrade-test/upgrade-test-scripts/{cliHelper.mjs => cliHelper.js} (80%) create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/commonUpgradeHelpers.js rename packages/deployment/upgrade-test/upgrade-test-scripts/{constants.mjs => constants.js} (91%) delete mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/coreUpgradeHelpers.mjs create mode 100644 packages/deployment/upgrade-test/upgrade-test-scripts/econHelpers.js diff --git a/packages/deployment/upgrade-test/Dockerfile b/packages/deployment/upgrade-test/Dockerfile index 79f69a502e9..d2e55164d68 100644 --- a/packages/deployment/upgrade-test/Dockerfile +++ b/packages/deployment/upgrade-test/Dockerfile @@ -81,7 +81,10 @@ ARG BOOTSTRAP_MODE ENV THIS_NAME=agoric-upgrade-10 USE_JS=1 BOOTSTRAP_MODE=${BOOTSTRAP_MODE} WORKDIR /usr/src/agoric-sdk/ -COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./package.json ./*.mjs ./upgrade-test-scripts/ +COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./package.json ./*.js ./upgrade-test-scripts/ +RUN cd upgrade-test-scripts && yarn +RUN echo '. /usr/src/agoric-sdk/upgrade-test-scripts/env_setup.sh' >> ~/.bashrc + COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ COPY --from=agoric-upgrade-9 /root/.agoric /root/.agoric RUN chmod +x ./upgrade-test-scripts/*.sh @@ -97,6 +100,9 @@ ARG BOOTSTRAP_MODE UPGRADE_INFO_11 ENV THIS_NAME=propose-agoric-upgrade-11 UPGRADE_TO=agoric-upgrade-11 UPGRADE_INFO=${UPGRADE_INFO_11} BOOTSTRAP_MODE=${BOOTSTRAP_MODE} WORKDIR /usr/src/agoric-sdk/ COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./upgrade-test-scripts/ +RUN cd upgrade-test-scripts && yarn +RUN echo '. /usr/src/agoric-sdk/upgrade-test-scripts/env_setup.sh' >> ~/.bashrc + COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ COPY --from=agoric-upgrade-10 /root/.agoric /root/.agoric RUN chmod +x ./upgrade-test-scripts/*.sh @@ -108,10 +114,13 @@ RUN . ./upgrade-test-scripts/start_to_to.sh ARG DEST_IMAGE FROM ghcr.io/agoric/agoric-sdk:36 as agoric-upgrade-11 ARG BOOTSTRAP_MODE -ENV THIS_NAME=agoric-upgrade-11 BOOTSTRAP_MODE=${BOOTSTRAP_MODE} +ENV THIS_NAME=agoric-upgrade-11 BOOTSTRAP_MODE=${BOOTSTRAP_MODE} USE_JS=1 # start-chain boilerplate WORKDIR /usr/src/agoric-sdk/ -COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./upgrade-test-scripts/ +COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./package.json ./*.js ./upgrade-test-scripts/ +RUN cd upgrade-test-scripts && yarn +RUN echo '. /usr/src/agoric-sdk/upgrade-test-scripts/env_setup.sh' >> ~/.bashrc + COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ COPY --from=propose-agoric-upgrade-11 /root/.agoric /root/.agoric RUN chmod +x ./upgrade-test-scripts/*.sh @@ -128,6 +137,9 @@ COPY --from=agoric-upgrade-11 /root/.agoric /root/.agoric # start-chain boilerplate WORKDIR /usr/src/agoric-sdk/ COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./upgrade-test-scripts/ +RUN cd upgrade-test-scripts && yarn +RUN echo '. /usr/src/agoric-sdk/upgrade-test-scripts/env_setup.sh' >> ~/.bashrc + COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ RUN chmod +x ./upgrade-test-scripts/*.sh SHELL ["/bin/bash", "-c"] @@ -142,7 +154,10 @@ ENV THIS_NAME=agoric-upgrade-12 BOOTSTRAP_MODE=${BOOTSTRAP_MODE} COPY --from=propose-agoric-upgrade-12 /root/.agoric /root/.agoric # start-chain boilerplate WORKDIR /usr/src/agoric-sdk/ -COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./package.json ./*.mjs ./upgrade-test-scripts/ +COPY ./bash_entrypoint.sh ./env_setup.sh ./start_to_to.sh ./package.json ./*.js ./upgrade-test-scripts/ +RUN cd upgrade-test-scripts && yarn +RUN echo '. /usr/src/agoric-sdk/upgrade-test-scripts/env_setup.sh' >> ~/.bashrc + COPY ./${THIS_NAME} ./upgrade-test-scripts/${THIS_NAME}/ RUN apt install -y tmux SHELL ["/bin/bash", "-c"] diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.js similarity index 84% rename from packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.mjs rename to packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.js index 2d0c654da28..569fdde2286 100644 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.mjs +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.js @@ -1,26 +1,26 @@ import { promises as fs } from 'fs'; import assert from 'assert'; -import { - waitForBlock, - provisionSmartWallet, - getUser, - executeOffer, -} from './upgradeHelpers.mjs'; import { agd, agoric, agops, agopsLocation, executeCommand, -} from '../cliHelper.mjs'; +} from '../cliHelper.js'; import { HOME, ATOM_DENOM, GOV1ADDR, GOV2ADDR, GOV3ADDR, -} from '../constants.mjs'; +} from '../constants.js'; +import { + waitForBlock, + executeOffer, + getUser, + provisionSmartWallet, +} from '../commonUpgradeHelpers.js'; const govAccounts = [GOV1ADDR, GOV2ADDR, GOV3ADDR]; @@ -265,58 +265,6 @@ export const raiseDebtCeiling = async address => { await new Promise(r => setTimeout(r, 65000)); }; -export const openVault = (address, mint, collateral) => { - return executeOffer( - address, - agops.vaults('open', '--wantMinted', mint, '--giveCollateral', collateral), - ); -}; - -export const adjustVault = (address, vaultId, vaultParams) => { - let params = [ - 'adjust', - '--vaultId', - vaultId, - '--from', - address, - ' --keyring-backend=test', - ]; - - if ('wantCollateral' in vaultParams) { - params = [...params, '--wantCollateral', vaultParams.wantCollateral]; - } - - if ('wantMinted' in vaultParams) { - params = [...params, '--wantMinted', vaultParams.wantMinted]; - } - - if ('giveCollateral' in vaultParams) { - params = [...params, '--giveCollateral', vaultParams.giveCollateral]; - } - - if ('giveMinted' in vaultParams) { - params = [...params, '--giveMinted', vaultParams.giveMinted]; - } - - return executeOffer(address, agops.vaults(...params)); -}; - -export const closeVault = (address, vaultId, mint) => { - return executeOffer( - address, - agops.vaults( - 'close', - '--vaultId', - vaultId, - '--giveMinted', - mint, - '--from', - address, - '--keyring-backend=test', - ), - ); -}; - export const pushPrice = (oracles, price = 10.0) => { console.log(`ACTIONS pushPrice ${price}`); const promiseArray = []; diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.test.js index 2fcec2ab6ed..a11e28ff4e4 100644 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.test.js +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/actions.test.js @@ -1,22 +1,16 @@ import test from 'ava'; -import { - waitForBlock, - submitDeliverInbound, - getUser, - newOfferId, -} from './upgradeHelpers.mjs'; import { provisionWallet, implementNewAuctionParams, raiseDebtCeiling, - openVault, - adjustVault, - closeVault, pushPrice, -} from './actions.mjs'; -import { agd, agoric, agops } from '../cliHelper.mjs'; -import { GOV1ADDR, GOV2ADDR } from '../constants.mjs'; +} from './actions.js'; +import { agd, agoric, agops } from '../cliHelper.js'; +import { GOV1ADDR, GOV2ADDR } from '../constants.js'; +import { getUser, newOfferId, waitForBlock } from '../commonUpgradeHelpers.js'; +import { submitDeliverInbound } from './upgradeHelpers.js'; +import { openVault, adjustVault, closeVault } from '../econHelpers.js'; const START_FREQUENCY = 600; // StartFrequency: 600s (auction runs every 10m) const CLOCK_STEP = 20; // ClockStep: 20s (ensures auction completes in time) diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/post.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/post.test.js index 30ac69ca947..9e6ac511c38 100644 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/post.test.js +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/post.test.js @@ -1,8 +1,8 @@ import test from 'ava'; -import { agd, agoric } from '../cliHelper.mjs'; -import { GOV1ADDR, GOV2ADDR, GOV3ADDR, USER1ADDR } from '../constants.mjs'; -import { calculateWalletState } from './upgradeHelpers.mjs'; +import { agd, agoric } from '../cliHelper.js'; +import { GOV1ADDR, GOV2ADDR, GOV3ADDR, USER1ADDR } from '../constants.js'; +import { calculateWalletState } from '../commonUpgradeHelpers.js'; test('DeliverInbound from un-provisioned account is discarded', async t => { const result = await agd.query('swingset', 'mailbox', USER1ADDR); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre.test.js index 9ce5aed434f..57acca70dc8 100644 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre.test.js +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/pre.test.js @@ -2,8 +2,7 @@ import test from 'ava'; import { promises as fs } from 'fs'; -import { waitForBlock, getUser } from './upgradeHelpers.mjs'; -import { agd, agoric, agops } from '../cliHelper.mjs'; +import { agd, agoric, agops } from '../cliHelper.js'; import { GOV1ADDR, @@ -11,9 +10,9 @@ import { GOV3ADDR, BOOTSTRAP_MODE, PSM_PAIR, -} from '../constants.mjs'; - -import { openVault } from './actions.mjs'; +} from '../constants.js'; +import { openVault } from '../econHelpers.js'; +import { getUser, waitForBlock } from '../commonUpgradeHelpers.js'; test.before(async () => { console.log('Wait for upgrade to settle'); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/upgradeHelpers.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/upgradeHelpers.js similarity index 90% rename from packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/upgradeHelpers.mjs rename to packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/upgradeHelpers.js index 3768d5603ee..5a81b731d55 100644 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/upgradeHelpers.mjs +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-10/upgradeHelpers.js @@ -8,16 +8,10 @@ import { VALIDATORADDR, USER1ADDR, CHAINID, - HOME, -} from '../constants.mjs'; +} from '../constants.js'; -import { agd, agops } from '../cliHelper.mjs'; - -export * from '../coreUpgradeHelpers.mjs'; - -export const getUser = async user => { - return agd.keys('show', user, '-a', '--keyring-backend=test'); -}; +import { agd } from '../cliHelper.js'; +import { getUser } from '../commonUpgradeHelpers.js'; export const printKeys = async () => { console.log('========== GOVERNANCE KEYS =========='); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/.keep b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/.keep deleted file mode 100644 index e69de29bb2d..00000000000 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 deleted file mode 100755 index fb6e66db7e5..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/actions.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -# Dockerfile in upgrade-test sets: -# WORKDIR /usr/src/agoric-sdk/ -# Overriding it during development has occasionally been useful. -SDK=${SDK:-/usr/src/agoric-sdk} -. $SDK/upgrade-test-scripts/env_setup.sh - -# Enable debugging -set -x - -# hacky restore of pruned artifacts -killAgd -EXPORT_DIR=$(mktemp -t -d swing-store-export-upgrade-11-XXX) -WITHOUT_GENESIS_EXPORT=1 make_swing_store_snapshot $EXPORT_DIR --artifact-mode debug || fail "Couldn't make swing-store snapshot" -HISTORICAL_ARTIFACTS="$(cd $HOME/.agoric/data/agoric/swing-store-historical-artifacts/; for i in *; do echo -n "[\"$i\",\"$i\"],"; done)" -mv -n $HOME/.agoric/data/agoric/swing-store-historical-artifacts/* $EXPORT_DIR || fail "some historical artifacts not pruned" -mv $EXPORT_DIR/export-manifest.json $EXPORT_DIR/export-manifest-original.json -cat $EXPORT_DIR/export-manifest-original.json | jq -r ".artifacts = .artifacts + [${HISTORICAL_ARTIFACTS%%,}] | del(.artifactMode)" > $EXPORT_DIR/export-manifest.json -restore_swing_store_snapshot $EXPORT_DIR || fail "Couldn't restore swing-store snapshot" -rm -rf $EXPORT_DIR -startAgd - -test_not_val "$(agops vaults list --from $GOV1ADDR)" "" "gov1 has no vaults" - -# open up a vault -OFFER=$(mktemp -t agops.XXX) -agops vaults open --wantMinted 7.00 --giveCollateral 11.0 >|"$OFFER" -agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$OFFER" --keyring-backend=test - -# put some IST in -OFFER=$(mktemp -t agops.XXX) -agops vaults adjust --vaultId vault3 --giveMinted 1.5 --from $GOV1ADDR --keyring-backend=test >|"$OFFER" -agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$OFFER" --keyring-backend=test - -# add some collateral -OFFER=$(mktemp -t agops.XXX) -agops vaults adjust --vaultId vault3 --giveCollateral 2.0 --from $GOV1ADDR --keyring-backend="test" >|"$OFFER" -agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$OFFER" --keyring-backend=test - -# close out -OFFER=$(mktemp -t agops.XXX) -agops vaults close --vaultId vault3 --giveMinted 5.75 --from $GOV1ADDR --keyring-backend="test" >|"$OFFER" -agops perf satisfaction --from "$GOV1ADDR" --executeOffer "$OFFER" --keyring-backend=test - -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault3 -o jsonlines | jq -r '.vaultState') "closed" "vault3 is closed" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault3 -o jsonlines | jq -r '.locked.value') "0" "vault3 contains no collateral" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault3 -o jsonlines | jq -r '.debtSnapshot.debt.value') "0" "vault3 has no debt" diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/actions.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/actions.test.js new file mode 100644 index 00000000000..58063c1cf2e --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/actions.test.js @@ -0,0 +1,23 @@ +import test from 'ava'; + +import { agoric, agops } from '../cliHelper.js'; +import { GOV1ADDR } from '../constants.js'; +import { openVault, adjustVault, closeVault } from '../econHelpers.js'; + +test.serial('Open Vaults', async t => { + const currentVaults = await agops.vaults('list', '--from', GOV1ADDR); + t.is(currentVaults.length, 2); + + await openVault(GOV1ADDR, 7, 11); + await adjustVault(GOV1ADDR, 'vault3', { giveMinted: 1.5 }); + await adjustVault(GOV1ADDR, 'vault3', { giveCollateral: 2.0 }); + await closeVault(GOV1ADDR, 'vault3', 5.75); + + const vault3 = await agoric.follow( + '-lF', + ':published.vaultFactory.managers.manager0.vaults.vault3', + ); + t.is(vault3.vaultState, 'closed'); + t.is(vault3.locked.value, '0'); + t.is(vault3.debtSnapshot.debt.value, '0'); +}); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/env_setup.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/env_setup.sh deleted file mode 100644 index 3a9537719f1..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/env_setup.sh +++ /dev/null @@ -1,153 +0,0 @@ -#!/bin/bash - -# agoric-upgrade-11 specific env here... -export USER2ADDR=$($binary keys show user2 -a --keyring-backend="test" 2> /dev/null) - -printKeys() { - echo "========== GOVERNANCE KEYS ==========" - echo "gov1: $GOV1ADDR" - cat ~/.agoric/gov1.key || true - echo "gov2: $GOV2ADDR" - cat ~/.agoric/gov2.key || true - echo "gov3: $GOV3ADDR" - cat ~/.agoric/gov3.key || true - echo "validator: $VALIDATORADDR" - cat ~/.agoric/validator.key || true - echo "user1: $USER1ADDR" - cat ~/.agoric/user1.key || true - echo "user2: $USER2ADDR" - cat ~/.agoric/user2.key || true - echo "========== GOVERNANCE KEYS ==========" -} - -pushPrice () { - echo ACTIONS pushPrice $1 - newPrice="${1:-10.00}" - for oracleNum in {1..2}; do - if [[ ! -e "$HOME/.agoric/lastOracle" ]]; then - echo "$GOV1ADDR" > "$HOME/.agoric/lastOracle" - fi - - lastOracle=$(cat "$HOME/.agoric/lastOracle") - nextOracle="$GOV1ADDR" - if [[ "$lastOracle" == "$GOV1ADDR" ]]; then - nextOracle="$GOV2ADDR" - fi - echo "Pushing Price from oracle $nextOracle" - - oid="${nextOracle}_ORACLE" - offer=$(mktemp -t pushPrice.XXX) - agops oracle pushPriceRound --price "$newPrice" --oracleAdminAcceptOfferId "${!oid}" >|"$offer" - sleep 1 - timeout --preserve-status 15 yarn run --silent agops perf satisfaction --from $nextOracle --executeOffer "$offer" --keyring-backend test - if [ $? -ne 0 ]; then - echo "WARNING: pushPrice for $nextOracle failed!" - fi - echo "$nextOracle" > "$HOME/.agoric/lastOracle" - done -} - - -# variant of pushPrice() that figures out which oracle to send from -# WIP because it doesn't always work -pushPriceOnce () { - echo ACTIONS pushPrice $1 - newPrice="${1:-10.00}" - timeout 3 agoric follow -lF :published.priceFeed.ATOM-USD_price_feed.latestRound -ojson > "$HOME/.agoric/latestRound-ATOM.json" - - lastStartedBy=$(jq -r .startedBy "$HOME/.agoric/latestRound-ATOM.json" || echo null) - echo lastStartedBy $lastStartedBy - nextOracle="ERROR" - # cycle to next among oracles (first of the two governance accounts) - case $lastStartedBy in - "$GOV1ADDR") nextOracle=$GOV2ADDR;; - "$GOV2ADDR") nextOracle=$GOV1ADDR;; - *) - echo last price was pushed by a different account, using GOV1 - nextOracle=$GOV1ADDR - ;; - esac - echo nextOracle $nextOracle - - adminOfferId="${nextOracle}_ORACLE" - - echo "Pushing Price from oracle $nextOracle with offer $adminOfferId" - - offer=$(mktemp -t pushPrice.XXX) - agops oracle pushPriceRound --price "$newPrice" --oracleAdminAcceptOfferId "${adminOfferId}" >|"$offer" - cat "$offer" - sleep 1 - timeout --preserve-status 15 yarn run --silent agops perf satisfaction --from $nextOracle --executeOffer "$offer" --keyring-backend test - if [ $? -eq 0 ]; then - echo SUCCESS - else - echo "ERROR: pushPrice failed (using $nextOracle)" - fi -} - -export_genesis() { - GENESIS_EXPORT_DIR="$1" - shift - GENESIS_HEIGHT_ARG= - - if [ -n "$1" ]; then - GENESIS_HEIGHT_ARG="--height $1" - shift - fi - - agd export --export-dir "$GENESIS_EXPORT_DIR" $GENESIS_HEIGHT_ARG "$@" -} - -make_swing_store_snapshot() {( set -euo pipefail - EXPORT_DIR="$1" - shift - /usr/src/agoric-sdk/packages/cosmic-swingset/src/export-kernel-db.js --home "$HOME/.agoric" --export-dir "$EXPORT_DIR" --verbose --artifact-mode replay --export-data-mode all "$@" - - EXPORT_MANIFEST_FILE="$EXPORT_DIR/export-manifest.json" - EXPORT_HEIGHT=$(cat "$EXPORT_MANIFEST_FILE" | jq -r .blockHeight) - - [ "x${WITHOUT_GENESIS_EXPORT:-0}" = "x1" ] || { - EXPORT_DATA_FILE="$EXPORT_DIR/$(cat "$EXPORT_MANIFEST_FILE" | jq -r .data)" - EXPORT_DATA_UNTRUSTED_FILE="${EXPORT_DATA_FILE%.*}-untrusted.jsonl" - EXPORT_MANIFEST="$(cat $EXPORT_MANIFEST_FILE)" - - mv "$EXPORT_DATA_FILE" "$EXPORT_DATA_UNTRUSTED_FILE" - export_genesis "$EXPORT_DIR/genesis-export" $EXPORT_HEIGHT - cat $EXPORT_DIR/genesis-export/genesis.json | jq -cr '.app_state.swingset.swing_store_export_data[] | [.key,.value]' > "$EXPORT_DATA_FILE" - - jq -n "$EXPORT_MANIFEST | .untrustedData=\"$(basename -- "$EXPORT_DATA_UNTRUSTED_FILE")\"" > "$EXPORT_MANIFEST_FILE" - } - - echo "Successful swing-store export for block $EXPORT_HEIGHT" -)} - -restore_swing_store_snapshot() {( set -euo pipefail - rm -f $HOME/.agoric/data/agoric/swingstore.sqlite - EXPORT_DIR="$1" - shift - - /usr/src/agoric-sdk/packages/cosmic-swingset/src/import-kernel-db.js --home "$HOME/.agoric" --export-dir "$EXPORT_DIR" --verbose --artifact-mode replay --export-data-mode all "$@" -)} - -compare_swing_store_export_data() { - EXPORT_DIR="$1" - EXPORT_MANIFEST_FILE="$EXPORT_DIR/export-manifest.json" - EXPORT_DATA_FILE="$(cat "$EXPORT_MANIFEST_FILE" | jq -r .data)" - EXPORT_DATA_UNTRUSTED_FILE="$(cat "$EXPORT_MANIFEST_FILE" | jq -r .untrustedData)" - - if [ -z "$EXPORT_DATA_FILE" ]; then - echo "missing-export-data" - return - fi - - if [ -z "$EXPORT_DATA_UNTRUSTED_FILE" ]; then - echo "missing-untrusted-export-data" - return - fi - - diff <(cat "$EXPORT_DIR/$EXPORT_DATA_FILE" | sort) <(cat "$EXPORT_DIR/$EXPORT_DATA_UNTRUSTED_FILE" | sort) >&2 && { - echo "match" - } || { - echo "mismatch" - } -} diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/legacy.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/legacy.sh new file mode 100755 index 00000000000..bb785bf2c97 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/legacy.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +. ./upgrade-test-scripts/env_setup.sh + +# Enable debugging +set -x + +export_genesis() { + GENESIS_EXPORT_DIR="$1" + shift + GENESIS_HEIGHT_ARG= + + if [ -n "$1" ]; then + GENESIS_HEIGHT_ARG="--height $1" + shift + fi + + agd export --export-dir "$GENESIS_EXPORT_DIR" $GENESIS_HEIGHT_ARG "$@" +} + +make_swing_store_snapshot() {( set -euo pipefail + EXPORT_DIR="$1" + shift + /usr/src/agoric-sdk/packages/cosmic-swingset/src/export-kernel-db.js --home "$HOME/.agoric" --export-dir "$EXPORT_DIR" --verbose --artifact-mode replay --export-data-mode all "$@" + + EXPORT_MANIFEST_FILE="$EXPORT_DIR/export-manifest.json" + EXPORT_HEIGHT=$(cat "$EXPORT_MANIFEST_FILE" | jq -r .blockHeight) + + [ "x${WITHOUT_GENESIS_EXPORT:-0}" = "x1" ] || { + EXPORT_DATA_FILE="$EXPORT_DIR/$(cat "$EXPORT_MANIFEST_FILE" | jq -r .data)" + EXPORT_DATA_UNTRUSTED_FILE="${EXPORT_DATA_FILE%.*}-untrusted.jsonl" + EXPORT_MANIFEST="$(cat $EXPORT_MANIFEST_FILE)" + + mv "$EXPORT_DATA_FILE" "$EXPORT_DATA_UNTRUSTED_FILE" + export_genesis "$EXPORT_DIR/genesis-export" $EXPORT_HEIGHT + cat $EXPORT_DIR/genesis-export/genesis.json | jq -cr '.app_state.swingset.swing_store_export_data[] | [.key,.value]' > "$EXPORT_DATA_FILE" + + jq -n "$EXPORT_MANIFEST | .untrustedData=\"$(basename -- "$EXPORT_DATA_UNTRUSTED_FILE")\"" > "$EXPORT_MANIFEST_FILE" + } + + echo "Successful swing-store export for block $EXPORT_HEIGHT" +)} + +restore_swing_store_snapshot() {( set -euo pipefail + rm -f $HOME/.agoric/data/agoric/swingstore.sqlite + EXPORT_DIR="$1" + shift + + /usr/src/agoric-sdk/packages/cosmic-swingset/src/import-kernel-db.js --home "$HOME/.agoric" --export-dir "$EXPORT_DIR" --verbose --artifact-mode replay --export-data-mode all "$@" +)} + +compare_swing_store_export_data() { + EXPORT_DIR="$1" + EXPORT_MANIFEST_FILE="$EXPORT_DIR/export-manifest.json" + EXPORT_DATA_FILE="$(cat "$EXPORT_MANIFEST_FILE" | jq -r .data)" + EXPORT_DATA_UNTRUSTED_FILE="$(cat "$EXPORT_MANIFEST_FILE" | jq -r .untrustedData)" + + if [ -z "$EXPORT_DATA_FILE" ]; then + echo "missing-export-data" + return + fi + + if [ -z "$EXPORT_DATA_UNTRUSTED_FILE" ]; then + echo "missing-untrusted-export-data" + return + fi + + sort $EXPORT_DIR/$EXPORT_DATA_FILE > "${EXPORT_DIR}/sorted_${EXPORT_DATA_FILE}" + sort $EXPORT_DIR/$EXPORT_DATA_UNTRUSTED_FILE > "${EXPORT_DIR}/sorted_${EXPORT_DATA_UNTRUSTED_FILE}" + + diff "${EXPORT_DIR}/sorted_${EXPORT_DATA_FILE}" "${EXPORT_DIR}/sorted_${EXPORT_DATA_UNTRUSTED_FILE}" >&2 && { + echo "match" + } || { + echo "mismatch" + } +} + +# hacky restore of pruned artifacts +killAgd +EXPORT_DIR=$(mktemp -t -d swing-store-export-upgrade-11-XXX) +WITHOUT_GENESIS_EXPORT=1 make_swing_store_snapshot $EXPORT_DIR --artifact-mode debug || fail "Couldn't make swing-store snapshot" +HISTORICAL_ARTIFACTS="$(cd $HOME/.agoric/data/agoric/swing-store-historical-artifacts/; for i in *; do echo -n "[\"$i\",\"$i\"],"; done)" +mv -n $HOME/.agoric/data/agoric/swing-store-historical-artifacts/* $EXPORT_DIR || fail "some historical artifacts not pruned" +mv $EXPORT_DIR/export-manifest.json $EXPORT_DIR/export-manifest-original.json +cat $EXPORT_DIR/export-manifest-original.json | jq -r ".artifacts = .artifacts + [${HISTORICAL_ARTIFACTS%%,}] | del(.artifactMode)" > $EXPORT_DIR/export-manifest.json +restore_swing_store_snapshot $EXPORT_DIR || fail "Couldn't restore swing-store snapshot" +startAgd +rm -rf $EXPORT_DIR + +# verify swing-store export-data is consistent and perform genesis style "upgrade" +killAgd +EXPORT_DIR=$(mktemp -t -d swing-store-export-upgrade-11-XXX) +make_swing_store_snapshot $EXPORT_DIR --artifact-mode none || fail "Couldn't make swing-store snapshot" +test_val "$(compare_swing_store_export_data $EXPORT_DIR)" "match" "swing-store consistent cosmos kvstore" + +TMP_GENESIS_DIR=$EXPORT_DIR/genesis-export +cp $HOME/.agoric/config/genesis.json $TMP_GENESIS_DIR/old_genesis.json +cp $HOME/.agoric/data/priv_validator_state.json $TMP_GENESIS_DIR/priv_validator_state.json +rm -rf $HOME/.agoric/data +mkdir $HOME/.agoric/data +mv $TMP_GENESIS_DIR/priv_validator_state.json $HOME/.agoric/data +mv $TMP_GENESIS_DIR/* $HOME/.agoric/config/ +startAgd +rm -rf $EXPORT_DIR \ No newline at end of file diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/post.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/post.test.js new file mode 100644 index 00000000000..2ce3d640c13 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/post.test.js @@ -0,0 +1,5 @@ +import test from 'ava'; + +test(`replace with the walletFactory work when it's complete`, t => { + t.pass(); +}); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre.test.js new file mode 100644 index 00000000000..818a0ea5b4f --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre.test.js @@ -0,0 +1,53 @@ +import test from 'ava'; + +import { agd, agoric } from '../cliHelper.js'; +import { waitForBlock } from '../commonUpgradeHelpers.js'; + +test.before(async () => { + console.log('Wait for upgrade to settle'); + + await waitForBlock(5); +}); + +test('Validate vaults', async t => { + const vaults = await agd.query( + 'vstorage', + 'children', + 'published.vaultFactory.managers.manager0.vaults', + ); + + t.is(vaults.children.length, 3); + + const metrics = await agoric.follow( + '-lF', + ':published.vaultFactory.managers.manager0.metrics', + ); + + t.is(metrics.numActiveVaults, 1); + t.is(metrics.totalDebt.value, '6030000'); + t.is(metrics.totalCollateral.value, '8000000'); + + const vault0 = await agoric.follow( + '-lF', + ':published.vaultFactory.managers.manager0.vaults.vault0', + ); + t.is(vault0.vaultState, 'active'); + t.is(vault0.locked.value, '8000000'); + t.is(vault0.debtSnapshot.debt.value, '6030000'); + + const vault1 = await agoric.follow( + '-lF', + ':published.vaultFactory.managers.manager0.vaults.vault1', + ); + t.is(vault1.vaultState, 'closed'); + t.is(vault1.locked.value, '0'); + t.is(vault1.debtSnapshot.debt.value, '0'); + + const vault2 = await agoric.follow( + '-lF', + ':published.vaultFactory.managers.manager0.vaults.vault2', + ); + t.is(vault2.vaultState, 'closed'); + t.is(vault2.locked.value, '0'); + t.is(vault2.debtSnapshot.debt.value, '0'); +}); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre_test.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre_test.sh deleted file mode 100755 index 05eca38550c..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/pre_test.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -. ./upgrade-test-scripts/env_setup.sh - -echo Wait for upgrade to settle -waitForBlock 5 - -# validate agoric-upgrade-10 metrics after update - -test_val $(agd q vstorage children published.vaultFactory.managers.manager0.vaults -o json | jq -r '.children | length') 3 "we have three vaults" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.metrics -o jsonlines | jq -r '.numActiveVaults') 1 "only one vault is active" - -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.metrics -o jsonlines | jq -r '.totalDebt.value') "6030000" "totalDebt is correct" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.metrics -o jsonlines | jq -r '.totalCollateral.value') "8000000" "totalCollateral is correct" - -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault0 -o jsonlines | jq -r '.vaultState') "active" "vault0 is open" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault0 -o jsonlines | jq -r '.locked.value') "8000000" "vault0 contains 8 ATOM collateral" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault0 -o jsonlines | jq -r '.debtSnapshot.debt.value') "6030000" "vault0 debt is 6.03 IST" - -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault1 -o jsonlines | jq -r '.vaultState') "closed" "vault1 is closed" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault1 -o jsonlines | jq -r '.locked.value') "0" "vault1 contains no collateral" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault1 -o jsonlines | jq -r '.debtSnapshot.debt.value') "0" "vault1 has no debt" - -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault2 -o jsonlines | jq -r '.vaultState') "closed" "vault2 is closed" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault2 -o jsonlines | jq -r '.locked.value') "0" "vault2 contains no collateral" -test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault2 -o jsonlines | jq -r '.debtSnapshot.debt.value') "0" "vault2 has no debt" - diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/test.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/test.sh deleted file mode 100755 index 73c816c6fae..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/test.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -. ./upgrade-test-scripts/env_setup.sh - -echo Wait for actions to settle -waitForBlock 2 - -# verify swing-store export-data is consistent and perform genesis style "upgrade" -killAgd -EXPORT_DIR=$(mktemp -t -d swing-store-export-upgrade-11-XXX) -make_swing_store_snapshot $EXPORT_DIR --artifact-mode none || fail "Couldn't make swing-store snapshot" -test_val "$(compare_swing_store_export_data $EXPORT_DIR)" "match" "swing-store consistent cosmos kvstore" - -TMP_GENESIS_DIR=$EXPORT_DIR/genesis-export -cp $HOME/.agoric/config/genesis.json $TMP_GENESIS_DIR/old_genesis.json -cp $HOME/.agoric/data/priv_validator_state.json $TMP_GENESIS_DIR/priv_validator_state.json -rm -rf $HOME/.agoric/data -mkdir $HOME/.agoric/data -mv $TMP_GENESIS_DIR/priv_validator_state.json $HOME/.agoric/data -mv $TMP_GENESIS_DIR/* $HOME/.agoric/config/ -rm -rf $EXPORT_DIR -startAgd diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.js new file mode 100644 index 00000000000..6ce8bbfc182 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.js @@ -0,0 +1,133 @@ +import { promises as fs } from 'fs'; +import * as path from 'path'; +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; +import { voteLatestProposalAndWait } from '../commonUpgradeHelpers.js'; +import { CHAINID, GOV1ADDR, VALIDATORADDR } from '../constants.js'; +import { agd, bundleSource } from '../cliHelper.js'; + +const directoryName = dirname(fileURLToPath(import.meta.url)); + +export const installBundles = async bundlesData => { + const bundleIds = {}; + + for (const bundleData of bundlesData) { + const bundleFilePath = await bundleSource( + bundleData.filePath, + bundleData.name, + ); + + const bundleJSONData = await fs.readFile(bundleFilePath, 'binary'); + + const bundle = JSON.parse(bundleJSONData); + bundleIds[bundleData.name] = bundle.endoZipBase64Sha512; + + await agd.tx( + 'swingset', + 'install-bundle', + `@${bundleFilePath}`, + '--from', + GOV1ADDR, + '--keyring-backend=test', + '--gas=auto', + '--chain-id', + CHAINID, + '-bblock', + '--yes', + ); + } + + return bundleIds; +}; + +export const prepForCoreEval = async (filePath, constants) => { + let sourceFileData = await fs.readFile(filePath, 'binary'); + + for (const constant in constants) { + if (Object.prototype.hasOwnProperty.call(constants, constant)) { + sourceFileData = sourceFileData.replace( + `##${constant}##`, + constants[constant], + ); + } + } + + const newFilePath = `/tmp/${path.basename(filePath)}`; + await fs.writeFile(newFilePath, sourceFileData); + return newFilePath; +}; + +export const runProber = async bundleId => { + const proberScriptPath = path.join( + directoryName, + 'zoe-full-upgrade', + 'run-prober-script.js', + ); + const proberUpgradePermitPath = path.join( + directoryName, + 'zoe-full-upgrade', + 'zcf-upgrade-permit.json', + ); + const filePath = await prepForCoreEval(proberScriptPath, { + PROBER_BUNDLE_ID: `b1-${bundleId}`, + }); + await agd.tx( + 'gov', + 'submit-proposal', + 'swingset-core-eval', + proberUpgradePermitPath, + filePath, + `--title="Run Prober"`, + `--description="run prober"`, + '--deposit=10000000ubld', + '--from', + VALIDATORADDR, + '--keyring-backend=test', + '--gas=auto', + '--gas-adjustment=1.2', + '--chain-id', + CHAINID, + '-bblock', + '--yes', + ); + + await voteLatestProposalAndWait(); +}; + +export const runZcfUpgrade = async (zcfBundleId, zoeBundleId) => { + const zcfScriptPath = path.join( + directoryName, + 'zoe-full-upgrade', + 'zcf-upgrade-script.js', + ); + const zcfUpgradePermitPath = path.join( + directoryName, + 'zoe-full-upgrade', + 'zcf-upgrade-permit.json', + ); + const filePath = await prepForCoreEval(zcfScriptPath, { + ZCF_BUNDLE_ID: `b1-${zcfBundleId}`, + ZOE_BUNDLE_ID: `b1-${zoeBundleId}`, + }); + await agd.tx( + 'gov', + 'submit-proposal', + 'swingset-core-eval', + zcfUpgradePermitPath, + filePath, + `--title="Run Prober"`, + `--description="run prober"`, + '--deposit=10000000ubld', + '--from', + VALIDATORADDR, + '--keyring-backend=test', + '--gas=auto', + '--gas-adjustment=1.2', + '--chain-id', + CHAINID, + '-bblock', + '--yes', + ); + + return voteLatestProposalAndWait(); +}; diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.sh deleted file mode 100755 index 62efb399d07..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/bash - -# Dockerfile in upgrade-test sets: -# WORKDIR /usr/src/agoric-sdk/ -# Overriding it during development has occasionally been useful. -SDK=${SDK:-/usr/src/agoric-sdk} -. $SDK/upgrade-test-scripts/env_setup.sh - -# Enable debugging -set -x - -AGUP=$SDK/upgrade-test-scripts/agoric-upgrade-12 -cd $AGUP - -## build proposal and install bundles -waitForBlock 2 -./tools/mint-ist.sh -./wallet-all-ertp/wf-install-bundles.sh - -## upgrade wallet factory -./wallet-all-ertp/wf-propose.sh - -## start game1 -./wallet-all-ertp/wf-game-propose.sh - -# Pay 0.25IST join the game and get some places -node ./wallet-all-ertp/gen-game-offer.mjs Shire Mordor >/tmp/,join.json -agops perf satisfaction --from $GOV1ADDR --executeOffer /tmp/,join.json --keyring-backend=test - -cd $SDK - -###################################################################### -# FIXME: remove this line when these tests don't hardcode bundle hashes. -echo 1>&2 "FIXME: skipping zoe-full-upgrade tests"; return 0 - -# Pre-steps: -# * fill Wallets -# * build and install bundles -# * create instance of prober contract and run expecting no atomicRearrange -# -# Action: -# * upgrade Zoe and ZCF -# -# Finish -# * create instance of prober contract and run expecting to see atomicRearrange - -yarn --silent bundle-source --cache-json /tmp packages/zoe/src/contractFacet/vatRoot.js Zcf-upgrade -yarn --silent bundle-source --cache-json /tmp packages/vats/src/vat-zoe.js Zoe-upgrade -yarn --silent bundle-source --cache-json /tmp packages/boot/test/bootstrapTests/zcfProbe.js prober-contract - -echo +++ checking Zoe/Zcf hashes +++ -ZCF_HASH=`jq -r .endoZipBase64Sha512 /tmp/bundle-Zcf-upgrade.json` -ZOE_HASH=`jq -r .endoZipBase64Sha512 /tmp/bundle-Zoe-upgrade.json` -echo bundle-Zcf-upgrade.json $ZCF_HASH -grep $ZCF_HASH $AGUP/zoe-full-upgrade/zcf-upgrade-script.js || exit 1 -echo bundle-Zoe-upgrade.json $ZOE_HASH -grep $ZOE_HASH $AGUP/zoe-full-upgrade/zcf-upgrade-script.js || exit 1 - -echo +++ prober hash +++ -PROBER_HASH=`jq -r .endoZipBase64Sha512 /tmp/bundle-prober-contract.json` -echo bundle-prober-contract.json $PROBER_HASH -grep $PROBER_HASH $AGUP/zoe-full-upgrade/run-prober-script.js || exit 1 - -echo +++++ fill wallet +++++ -agd tx bank send validator $GOV1ADDR 12340000000${ATOM_DENOM} --from validator --chain-id agoriclocal --keyring-backend test --yes -agops vaults open --wantMinted 10000 --giveCollateral 2000 > wantIST -agops perf satisfaction --executeOffer wantIST --from gov1 --keyring-backend test - - -echo +++++ install bundles +++++ -for f in /tmp/bundle-{Z*-upgrade,prober-contract}.json; do - echo installing $f - agd tx swingset install-bundle "@$f" \ - --from gov1 --keyring-backend=test --gas=auto \ - --chain-id=agoriclocal -bblock --yes -done - - -echo +++++ Run prober first time +++++ -$AGUP/zoe-full-upgrade/run-prober.sh -test_val "$(agd query vstorage data published.prober-asid9a -o jsonlines | jq -r '.value' | jq -r '.values[0]')" "false" "Prober calling zcf.atomicReallocate()" - - -# upgrade zoe to a version that can change which ZCF is installed; tell Zoe to -# use a new version of ZCF. THIS MATCHES THE UPGRADE OF THE LIVE CHAIN -echo +++++ upgrade Zoe and ZCF +++++ -$AGUP/zoe-full-upgrade/zcf-upgrade-driver.sh - - -echo +++++ Run prober second time +++++ -# Re-run prober test and expect internal atomicRearrange. -$AGUP/zoe-full-upgrade/run-prober.sh -test_val "$(agd query vstorage data published.prober-asid9a -o jsonlines | jq -r '.value' | jq -r '.values[0]')" "true" "Prober called zcf.atomicReallocate()" diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.test.js new file mode 100644 index 00000000000..aa985cf68c6 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/actions.test.js @@ -0,0 +1,74 @@ +import test from 'ava'; + +import { agd, agoric, agops } from '../cliHelper.js'; +import { GOV1ADDR, SDK_ROOT } from '../constants.js'; +import { installBundles, runZcfUpgrade, runProber } from './actions.js'; +import { adjustVault, closeVault, mintIST, openVault } from '../econHelpers.js'; + +test.before(async t => { + await mintIST(GOV1ADDR, 12340000000, 10000, 2000); + + const bundlesData = [ + { + name: 'Zcf-upgrade', + filePath: `${SDK_ROOT}/packages/zoe/src/contractFacet/vatRoot.js`, + }, + { + name: 'Zoe-upgrade', + filePath: `${SDK_ROOT}/packages/vats/src/vat-zoe.js`, + }, + { + name: 'prober-contract', + filePath: `${SDK_ROOT}/packages/boot/test/bootstrapTests/zcfProbe.js`, + }, + ]; + + // @ts-expect-error + t.context.bundleIds = await installBundles(bundlesData); +}); + +test.serial('Open Vaults', async t => { + const currentVaults = await agops.vaults('list', '--from', GOV1ADDR); + t.is(currentVaults.length, 4); + + await openVault(GOV1ADDR, 7, 11); + await adjustVault(GOV1ADDR, 'vault5', { giveMinted: 1.5 }); + await adjustVault(GOV1ADDR, 'vault5', { giveCollateral: 2.0 }); + await closeVault(GOV1ADDR, 'vault5', 5.75); + + const vault5 = await agoric.follow( + '-lF', + ':published.vaultFactory.managers.manager0.vaults.vault5', + ); + t.is(vault5.vaultState, 'closed'); + t.is(vault5.locked.value, '0'); + t.is(vault5.debtSnapshot.debt.value, '0'); +}); + +test.serial('Run Prober (first time)', async t => { + // @ts-expect-error + await runProber(t.context.bundleIds['prober-contract']); + const data = await agd.query('vstorage', 'data', 'published.prober-asid9a'); + const value = JSON.parse(data.value); + t.is(value.values[0], 'false'); +}); + +test.serial('Upgrade Zoe and ZCF', async t => { + await runZcfUpgrade( + // @ts-expect-error + t.context.bundleIds['Zcf-upgrade'], + // @ts-expect-error + t.context.bundleIds['Zoe-upgrade'], + ); + + t.pass(); +}); + +test.serial('Run Prober (second time)', async t => { + // @ts-expect-error + await runProber(t.context.bundleIds['prober-contract']); + + const data = await agd.query('vstorage', 'data', 'published.prober-asid9a'); + const value = JSON.parse(data.value); + t.is(value.values[0], 'true'); +}); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/env_setup.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/env_setup.sh deleted file mode 100644 index c221fd9a60f..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/env_setup.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -# agoric-upgrade-12 specific env here... diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/post.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/post.test.js new file mode 100644 index 00000000000..3ac4cd614da --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/post.test.js @@ -0,0 +1,7 @@ +import test from 'ava'; +import { getIncarnation } from './tools/vat-status.js'; + +test(`verify Zoe vat incarnation`, async t => { + const incarantion = await getIncarnation('zoe'); + t.is(incarantion, 1); +}); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre.test.js b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre.test.js new file mode 100644 index 00000000000..2e93afd24a7 --- /dev/null +++ b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre.test.js @@ -0,0 +1,20 @@ +import test from 'ava'; + +import { waitForBlock } from '../commonUpgradeHelpers.js'; +import { getIncarnation } from './tools/vat-status.js'; + +test.before(async () => { + console.log('Wait for upgrade to settle'); + + await waitForBlock(5); +}); + +test(`Ensure Zoe Vat is at 0`, async t => { + const incarnation = await getIncarnation('zoe'); + t.is(incarnation, 0); +}); + +test('Ensure Network Vat is at 0', async t => { + const incarnation = await getIncarnation('network'); + t.is(incarnation, 0); +}); diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh deleted file mode 100755 index 374810706d3..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/pre_test.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -. ./upgrade-test-scripts/env_setup.sh - -# CWD is agoric-sdk -upgrade12=./upgrade-test-scripts/agoric-upgrade-12 - -# test that the network vat was installed (see UPGRADE_INFO_12) -test_val "$(yarn --silent node $upgrade12/tools/vat-status.mjs network)" "0" "network vat incarnation" - -test_val "$(agd query vstorage children published.boardAux -o json | jq .children)" "[]" "no boardAux children yet" - -# zoe vat is at incarnation 0 -test_val "$(yarn --silent node $upgrade12/tools/vat-status.mjs zoe)" "0" "zoe vat incarnation" diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/test.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/test.sh deleted file mode 100755 index ad007522b6a..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/test.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -. ./upgrade-test-scripts/env_setup.sh - -echo Wait for actions to settle -waitForBlock 2 - -# CWD is agoric-sdk -upgrade12=./upgrade-test-scripts/agoric-upgrade-12 - - -testMinChildren() { - path=$1 - min=$2 - line="$(agd query vstorage children $path -o jsonlines)" - ok=$(echo $line | jq ".children | length | . > $min") - test_val "$ok" "true" "$path: more than $min children" -} - -# Check brand aux data for more than just vbank assets -testMinChildren published.boardAux 3 - -testDisplayInfo() { - name=$1 - expected=$2 - - line="$(agoric follow -lF :published.agoricNames.brand -o text)" - # find brand by name, then corresponding slot - id=$(echo $line | jq --arg name "$name" -r '.slots as $slots | .body | gsub("^#";"") | fromjson | .[] | select(.[0] == $name) | .[1] | capture("^[$](?0|[1-9][0-9]*)") | .slot | $slots[. | tonumber]') - echo $name Id: $id - - line="$(agoric follow -lF :published.boardAux.$id -o jsonlines)" - displayInfo="$(echo $line | jq -c .displayInfo)" - test_val "$displayInfo" "$expected" "$name displayInfo from boardAux" -} - -testDisplayInfo IST '{"assetKind":"nat","decimalPlaces":6}' - -testPurseValuePayload() { - addr=$1 - wkAsset=$2 - expected=$3 - - line="$(agoric follow -lF :published.wallet.$addr.current -o jsonlines)" - # HACK: selecting brand by allegedName - payload=$(echo $line | jq --arg name "$wkAsset" -c '.purses[] | select(.brand | contains($name)) | .balance.value.payload') - test_val "$payload" "$expected" "$wkAsset purse for $addr" -} - -# Smart wallet handles game Place assets? -testDisplayInfo Place '{"assetKind":"copyBag"}' -testPurseValuePayload $GOV1ADDR Place '[["Shire","1"],["Mordor","1"]]' - -# zoe vat is at incarnation 1 -echo "FIXME: bypassed zoe-full-upgrade validation"; return 0 -test_val "$(yarn --silent node $upgrade12/tools/vat-status.mjs zoe)" "1" "zoe vat incarnation" diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/mint-ist.sh b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/mint-ist.sh deleted file mode 100755 index 7c43a5b46d5..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/mint-ist.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -if [ -z "$GOV1ADDR" ]; then - echo run env_setup.sh to set GOV1ADDR - exit 1 -fi - -micro=000000 - -# send some collateral to gov1 -agd tx bank send validator $GOV1ADDR 20123$micro${ATOM_DENOM} \ - --keyring-backend=test --chain-id=agoriclocal --yes -bblock -o json - -export PATH=/usr/src/agoric-sdk/packages/agoric-cli/bin:$PATH -agops vaults open --giveCollateral 5000 --wantMinted 20000 > /tmp/offer.json -agops perf satisfaction --executeOffer /tmp/offer.json --from gov1 --keyring-backend=test diff --git a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/parseProposals.mjs b/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/parseProposals.mjs deleted file mode 100755 index daab1be3636..00000000000 --- a/packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-12/tools/parseProposals.mjs +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env node - -import fs from 'fs'; - -const Fail = (template, ...args) => { - throw Error(String.raw(template, ...args.map(val => String(val)))); -}; - -/** - * Parse output of `agoric run proposal-builder.js` - * - * @param {string} txt - * - * adapted from packages/boot/test/bootstrapTests/supports.js - */ -const parseProposalParts = txt => { - const evals = [ - ...txt.matchAll(/swingset-core-eval (?\S+) (?