diff --git a/golang/cosmos/app/app.go b/golang/cosmos/app/app.go index 52eb932eaa0..736f877e628 100644 --- a/golang/cosmos/app/app.go +++ b/golang/cosmos/app/app.go @@ -873,7 +873,7 @@ func NewAgoricApp( app.SetBeginBlocker(app.BeginBlocker) app.SetEndBlocker(app.EndBlocker) - for _, name := range upgradeNamesOfThisVersion { + for name := range upgradeNamesOfThisVersion { app.UpgradeKeeper.SetUpgradeHandler( name, unreleasedUpgradeHandler(app, name), @@ -889,7 +889,10 @@ func NewAgoricApp( // Store migrations can only run once, so we use a notion of "primary upgrade // name" to trigger them. Testnets may end up upgrading from one rc to // another, which shouldn't re-run store upgrades. - if isPrimaryUpgradeName(upgradeInfo.Name) && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + if upgradeInfo.Name != "" && + isPrimaryUpgradeName(upgradeInfo.Name) && + !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + storeUpgrades := storetypes.StoreUpgrades{ Added: []string{}, Deleted: []string{}, diff --git a/golang/cosmos/app/upgrade.go b/golang/cosmos/app/upgrade.go index 12cd6eb4a77..43b46253323 100644 --- a/golang/cosmos/app/upgrade.go +++ b/golang/cosmos/app/upgrade.go @@ -10,61 +10,37 @@ import ( upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) -var upgradeNamesOfThisVersion = []string{ - "UNRELEASED_BASIC", // no-frills - "UNRELEASED_A3P_INTEGRATION", - "UNRELEASED_main", - "UNRELEASED_devnet", - "UNRELEASED_REAPPLY", +// upgradeNamesOfThisVersion documents the current upgrade names and whether +// each is "primary" (used to trigger store migrations, which can only run +// once). An actual release should have exactly one primary upgrade name and any +// number of non-primary upgrade names (each of the latter being associated with +// a release candidate iteration after the first RC and used only for +// pre-production chains), but for testing purposes, the master branch has +// multiple primary upgrade names. +var upgradeNamesOfThisVersion = map[string]bool{ + "UNRELEASED_BASIC": true, + "UNRELEASED_A3P_INTEGRATION": true, + "UNRELEASED_main": true, + "UNRELEASED_devnet": true, + "UNRELEASED_REAPPLY": false, } -// isUpgradeNameOfThisVersion returns whether the provided plan name is a -// known upgrade name of this software version -func isUpgradeNameOfThisVersion(name string) bool { - for _, upgradeName := range upgradeNamesOfThisVersion { - if upgradeName == name { - return true - } - } - return false -} - -// validUpgradeName is an identity function that asserts the provided name -// is an upgrade name of this software version. It can be used as a sort of -// dynamic enum check. -func validUpgradeName(name string) string { - if !isUpgradeNameOfThisVersion(name) { - panic(fmt.Errorf("invalid upgrade name: %s", name)) - } - return name -} - -// isPrimaryUpgradeName returns wether the provided plan name is considered a +// isPrimaryUpgradeName returns whether the provided plan name is considered a // primary for the purpose of applying store migrations for the first upgrade // of this version. -// It is expected that only primary plan names are used for non testing chains. +// It is expected that only primary plan names are used for production chains. func isPrimaryUpgradeName(name string) bool { - if name == "" { - // An empty upgrade name can happen if there are no upgrade in progress - return false - } - switch name { - case validUpgradeName("UNRELEASED_BASIC"), - validUpgradeName("UNRELEASED_A3P_INTEGRATION"), - validUpgradeName("UNRELEASED_main"), - validUpgradeName("UNRELEASED_devnet"): - return true - case validUpgradeName("UNRELEASED_REAPPLY"): - return false - default: - panic(fmt.Errorf("unexpected upgrade name %s", validUpgradeName(name))) + isPrimary, found := upgradeNamesOfThisVersion[name] + if !found { + panic(fmt.Errorf("invalid upgrade name: %q", name)) } + return isPrimary } // isFirstTimeUpgradeOfThisVersion looks up in the upgrade store whether no // upgrade plan name of this version have previously been applied. func isFirstTimeUpgradeOfThisVersion(app *GaiaApp, ctx sdk.Context) bool { - for _, name := range upgradeNamesOfThisVersion { + for name := range upgradeNamesOfThisVersion { if app.UpgradeKeeper.GetDoneHeight(ctx, name) != 0 { return false } @@ -82,11 +58,11 @@ func unreleasedUpgradeHandler(app *GaiaApp, targetUpgrade string) func(sdk.Conte // These CoreProposalSteps are not idempotent and should only be executed // as part of the first upgrade using this handler on any given chain. if isFirstTimeUpgradeOfThisVersion(app, ctx) { - // The storeUpgrades defined in app.go only execute for the primary upgrade name - // If we got here and this first upgrade of this version does not use the - // primary upgrade name, stores have not been initialized correctly. + // The storeUpgrades defined in app.go only execute for primary upgrade names. + // If this first upgrade is *not* primary, then stores have not been + // initialized correctly. if !isPrimaryUpgradeName(plan.Name) { - return module.VersionMap{}, fmt.Errorf("cannot run %s as first upgrade", plan.Name) + return module.VersionMap{}, fmt.Errorf("cannot run %q as first upgrade", plan.Name) } // Each CoreProposalStep runs sequentially, and can be constructed from