From 32a01da4563b52df6167929f3535d111ad18a1b7 Mon Sep 17 00:00:00 2001 From: Alex Peters Date: Thu, 5 Oct 2023 09:28:43 +0200 Subject: [PATCH] Better upgrade structure an minor updates --- app/upgrades.go | 74 ++++++++++++++++++++--------------- app/upgrades/types.go | 25 ++++++++++++ app/upgrades/v043/upgrades.go | 31 +++++++++++++++ cmd/wasmd/testnet.go | 2 +- tests/system/cli.go | 4 +- tests/system/main_test.go | 4 +- tests/system/system.go | 10 ++--- tests/system/upgrade_test.go | 8 +++- 8 files changed, 114 insertions(+), 44 deletions(-) create mode 100644 app/upgrades/types.go create mode 100644 app/upgrades/v043/upgrades.go diff --git a/app/upgrades.go b/app/upgrades.go index 82872ea750..1b7a68a991 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -1,6 +1,10 @@ package app import ( + "fmt" + "github.com/CosmWasm/wasmd/app/upgrades" + v043 "github.com/CosmWasm/wasmd/app/upgrades/v043" + paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" icacontrollertypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/types" icahosttypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/types" ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" @@ -8,26 +12,53 @@ import ( ibcconnectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" - storetypes "github.com/cosmos/cosmos-sdk/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" ) -// UpgradeName defines the on-chain upgrade name for the sample SimApp upgrade -// from v046 to v047. -// -// NOTE: This upgrade defines a reference implementation of what an upgrade -// could look like when an application is migrating from Cosmos SDK version -// v0.46.x to v0.47.x. -const UpgradeName = "v0.43.x" +// Upgrades list of chain upgrades +var Upgrades = []upgrades.Upgrade{v043.Upgrade} +// RegisterUpgradeHandlers registers the chain upgrade handlers func (app WasmApp) RegisterUpgradeHandlers() { + setupLegacyKeyTables(app.ParamsKeeper) + + keepers := upgrades.AppKeepers{AccountKeeper: app.AccountKeeper} + // register all upgrade handlers + for _, upgrade := range Upgrades { + app.UpgradeKeeper.SetUpgradeHandler( + upgrade.UpgradeName, + upgrade.CreateUpgradeHandler( + app.ModuleManager, + app.configurator, + &keepers, + ), + ) + } + + upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk() + if err != nil { + panic(fmt.Sprintf("failed to read upgrade info from disk %s", err)) + } + + if app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + return + } + + // register store loader for current upgrade + for _, upgrade := range Upgrades { + if upgradeInfo.Name == upgrade.UpgradeName { + app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &upgrade.StoreUpgrades)) + break + } + } +} + +func setupLegacyKeyTables(k paramskeeper.Keeper) { // Set param key table for params module migration - for _, subspace := range app.ParamsKeeper.GetSubspaces() { + for _, subspace := range k.GetSubspaces() { subspace := subspace var keyTable paramstypes.KeyTable @@ -53,25 +84,4 @@ func (app WasmApp) RegisterUpgradeHandlers() { subspace.WithKeyTable(keyTable) } } - - app.UpgradeKeeper.SetUpgradeHandler( - UpgradeName, - func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { - return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM) - }, - ) - - upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk() - if err != nil { - panic(err) - } - - if upgradeInfo.Name == UpgradeName && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { - storeUpgrades := storetypes.StoreUpgrades{ - Added: []string{}, - } - - // configure store loader that checks if version == upgradeHeight and applies store upgrades - app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades)) - } } diff --git a/app/upgrades/types.go b/app/upgrades/types.go new file mode 100644 index 0000000000..5cfce557f5 --- /dev/null +++ b/app/upgrades/types.go @@ -0,0 +1,25 @@ +package upgrades + +import ( + store "github.com/cosmos/cosmos-sdk/store/types" + "github.com/cosmos/cosmos-sdk/types/module" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" +) + +type AppKeepers struct { + authkeeper.AccountKeeper +} + +// Upgrade defines a struct containing necessary fields that a SoftwareUpgradeProposal +// must have written, in order for the state migration to go smoothly. +// An upgrade must implement this struct, and then set it in the app.go. +// The app.go will then define the handler. +type Upgrade struct { + // Upgrade version name, for the upgrade handler, e.g. `v7` + UpgradeName string + + // CreateUpgradeHandler defines the function that creates an upgrade handler + CreateUpgradeHandler func(*module.Manager, module.Configurator, *AppKeepers) upgradetypes.UpgradeHandler + StoreUpgrades store.StoreUpgrades +} diff --git a/app/upgrades/v043/upgrades.go b/app/upgrades/v043/upgrades.go new file mode 100644 index 0000000000..bca64c425f --- /dev/null +++ b/app/upgrades/v043/upgrades.go @@ -0,0 +1,31 @@ +package v043 + +import ( + "github.com/CosmWasm/wasmd/app/upgrades" + store "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" +) + +// UpgradeName defines the on-chain upgrade name +const UpgradeName = "v0.43" + +var Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, + CreateUpgradeHandler: CreateUpgradeHandler, + StoreUpgrades: store.StoreUpgrades{ + Added: []string{}, + Deleted: []string{}, + }, +} + +func CreateUpgradeHandler( + mm *module.Manager, + configurator module.Configurator, + ak *upgrades.AppKeepers, +) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + return mm.RunMigrations(ctx, configurator, fromVM) + } +} diff --git a/cmd/wasmd/testnet.go b/cmd/wasmd/testnet.go index c1d8dfd0fc..4e7c973599 100644 --- a/cmd/wasmd/testnet.go +++ b/cmd/wasmd/testnet.go @@ -166,7 +166,7 @@ Example: addTestnetFlagsToCmd(cmd) cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)") - cmd.Flags().String(flagNodeDaemonHome, "wasmd", "Home directory of the node's daemon configuration") + cmd.Flags().String(flagNodeDaemonHome, version.AppName, "Home directory of the node's daemon configuration") cmd.Flags().String(flagStartingIPAddress, "192.168.0.1", "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)") cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") cmd.Flags().Duration(flagCommitTimeout, 5*time.Second, "Time to wait after a block commit before starting on the new height") diff --git a/tests/system/cli.go b/tests/system/cli.go index e0d2c0cdc5..efd95d3116 100644 --- a/tests/system/cli.go +++ b/tests/system/cli.go @@ -164,7 +164,7 @@ func (c WasmdCli) CustomCommand(args ...string) string { if !ok { return execOutput } - rsp, committed := c.awaitTxCommitted(execOutput, defaultWaitTime) + rsp, committed := c.awaitTxCommitted(execOutput, DefaultWaitTime) c.t.Logf("tx committed: %v", committed) require.Equal(c.t, c.expTXCommitted, committed, "expected tx committed: %v", c.expTXCommitted) return rsp @@ -218,7 +218,7 @@ func (c WasmdCli) runWithInput(args []string, input io.Reader) (output string, o err = fmt.Errorf("recovered from panic: %v", r) } }() - cmd := exec.Command(locateExecutable("wasmd"), args...) //nolint:gosec + cmd := exec.Command(locateExecutable(c.execBinary), args...) //nolint:gosec cmd.Dir = WorkDir cmd.Stdin = input return cmd.CombinedOutput() diff --git a/tests/system/main_test.go b/tests/system/main_test.go index 85d2e7f483..0467cc2f8f 100644 --- a/tests/system/main_test.go +++ b/tests/system/main_test.go @@ -27,7 +27,7 @@ var ( func TestMain(m *testing.M) { rebuild := flag.Bool("rebuild", false, "rebuild artifacts") - waitTime := flag.Duration("wait-time", defaultWaitTime, "time to wait for chain events") + waitTime := flag.Duration("wait-time", DefaultWaitTime, "time to wait for chain events") nodesCount := flag.Int("nodes-count", 4, "number of nodes in the cluster") blockTime := flag.Duration("block-time", 1000*time.Millisecond, "block creation time") execBinary := flag.String("binary", "wasmd", "executable binary for server/ client side") @@ -48,7 +48,7 @@ func TestMain(m *testing.M) { } initSDKConfig(*bech32Prefix) - defaultWaitTime = *waitTime + DefaultWaitTime = *waitTime if *execBinary == "" { panic("executable binary name must not be empty") } diff --git a/tests/system/system.go b/tests/system/system.go index 9a7fd26ecb..c2cf3983ed 100644 --- a/tests/system/system.go +++ b/tests/system/system.go @@ -261,7 +261,7 @@ func (s *SystemUnderTest) AwaitChainStopped() { func (s *SystemUnderTest) AwaitNodeUp(t *testing.T, rpcAddr string) { t.Helper() t.Logf("Await node is up: %s", rpcAddr) - timeout := defaultWaitTime + timeout := DefaultWaitTime ctx, done := context.WithTimeout(context.Background(), timeout) defer done() @@ -745,7 +745,7 @@ func NewEventListener(t *testing.T, rpcAddr string) *EventListener { return &EventListener{client: httpClient, t: t} } -var defaultWaitTime = 30 * time.Second +var DefaultWaitTime = 30 * time.Second type ( CleanupFn func() @@ -760,7 +760,7 @@ func (l *EventListener) Subscribe(query string, cb EventConsumer) func() { eventsChan, err := l.client.WSEvents.Subscribe(ctx, "testing", query) require.NoError(l.t, err) cleanup := func() { - ctx, _ := context.WithTimeout(ctx, defaultWaitTime) //nolint:govet + ctx, _ := context.WithTimeout(ctx, DefaultWaitTime) //nolint:govet go l.client.WSEvents.Unsubscribe(ctx, "testing", query) //nolint:errcheck done() } @@ -778,7 +778,7 @@ func (l *EventListener) Subscribe(query string, cb EventConsumer) func() { // For query syntax See https://docs.cosmos.network/master/core/events.html#subscribing-to-events func (l *EventListener) AwaitQuery(query string, optMaxWaitTime ...time.Duration) *ctypes.ResultEvent { c, result := CaptureSingleEventConsumer() - maxWaitTime := defaultWaitTime + maxWaitTime := DefaultWaitTime if len(optMaxWaitTime) != 0 { maxWaitTime = optMaxWaitTime[0] } @@ -840,7 +840,7 @@ func CaptureSingleEventConsumer() (EventConsumer, *ctypes.ResultEvent) { // // assert.Len(t, done(), 1) // then verify your assumption func CaptureAllEventsConsumer(t *testing.T, optMaxWaitTime ...time.Duration) (c EventConsumer, done func() []ctypes.ResultEvent) { - maxWaitTime := defaultWaitTime + maxWaitTime := DefaultWaitTime if len(optMaxWaitTime) != 0 { maxWaitTime = optMaxWaitTime[0] } diff --git a/tests/system/upgrade_test.go b/tests/system/upgrade_test.go index dd3d506a10..2d4c12f084 100644 --- a/tests/system/upgrade_test.go +++ b/tests/system/upgrade_test.go @@ -33,7 +33,11 @@ func TestChainUpgrade(t *testing.T) { votingPeriod := 10 * time.Second // enough time to vote sut.ModifyGenesisJSON(t, SetGovVotingPeriod(t, votingPeriod)) - const upgradeHeight int64 = 22 + const ( + upgradeHeight int64 = 22 + upgradeName = "v0.43" + ) + sut.StartChain(t, fmt.Sprintf("--halt-height=%d", upgradeHeight)) cli := NewWasmdCLI(t, sut, verbose) @@ -67,7 +71,7 @@ func TestChainUpgrade(t *testing.T) { "deposit": "100000000stake", "title": "my upgrade", "summary": "testing" -}`, "v0.43.x", upgradeHeight) +}`, upgradeName, upgradeHeight) proposalID := cli.SubmitAndVoteGovProposal(proposal) t.Logf("current_height: %d\n", sut.currentHeight) raw := cli.CustomQuery("q", "gov", "proposal", proposalID)