diff --git a/app/app.go b/app/app.go index 20d418604..de4ad490c 100644 --- a/app/app.go +++ b/app/app.go @@ -1002,6 +1002,8 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino paramsKeeper.Subspace(icacallbacksmoduletypes.ModuleName) // this line is used by starport scaffolding # stargate/app/paramSubspace + paramsKeeper.Subspace(claimtypes.ModuleName) + paramsKeeper.Subspace(authz.ModuleName) return paramsKeeper } diff --git a/app/apptesting/test_helpers.go b/app/apptesting/test_helpers.go index 985ada4b0..c2c9951fb 100644 --- a/app/apptesting/test_helpers.go +++ b/app/apptesting/test_helpers.go @@ -3,11 +3,13 @@ package apptesting import ( "strings" + abci "github.com/tendermint/tendermint/abci/types" ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" icatypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/types" transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" @@ -311,3 +313,20 @@ func (s *AppTestHelper) ICS20PacketAcknowledgement() channeltypes.Acknowledgemen ack := channeltypes.NewResultAcknowledgement(s.MarshalledICS20PacketData()) return ack } + +func (s *AppTestHelper) ConfirmUpgradeSucceededs(upgradeName string, upgradeHeight int64) { + contextBeforeUpgrade := s.Ctx().WithBlockHeight(upgradeHeight - 1) + contextAtUpgrade := s.Ctx().WithBlockHeight(upgradeHeight) + + plan := upgradetypes.Plan{Name: upgradeName, Height: upgradeHeight} + err := s.App.UpgradeKeeper.ScheduleUpgrade(contextBeforeUpgrade, plan) + s.Require().NoError(err) + + plan, exists := s.App.UpgradeKeeper.GetUpgradePlan(contextBeforeUpgrade) + s.Require().True(exists) + + s.Require().NotPanics(func() { + beginBlockRequest := abci.RequestBeginBlock{} + s.App.BeginBlocker(contextAtUpgrade, beginBlockRequest) + }) + } diff --git a/app/upgrades.go b/app/upgrades.go index 05ae2ddba..135a6823c 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -8,7 +8,9 @@ import ( v2 "github.com/Stride-Labs/stride/v3/app/upgrades/v2" v3 "github.com/Stride-Labs/stride/v3/app/upgrades/v3" + v4 "github.com/Stride-Labs/stride/v3/app/upgrades/v4" claimtypes "github.com/Stride-Labs/stride/v3/x/claim/types" + authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" ) func (app *StrideApp) setupUpgradeHandlers() { @@ -24,6 +26,12 @@ func (app *StrideApp) setupUpgradeHandlers() { v3.CreateUpgradeHandler(app.mm, app.configurator, app.ClaimKeeper), ) + // v4 upgrade handler + app.UpgradeKeeper.SetUpgradeHandler( + v4.UpgradeName, + v4.CreateUpgradeHandler(app.mm, app.configurator), + ) + upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk() if err != nil { panic(fmt.Errorf("Failed to read upgrade info from disk: %w", err)) @@ -41,6 +49,10 @@ func (app *StrideApp) setupUpgradeHandlers() { storeUpgrades = &storetypes.StoreUpgrades{ Added: []string{claimtypes.StoreKey}, } + case "v4": + storeUpgrades = &storetypes.StoreUpgrades{ + Added: []string{authzkeeper.StoreKey}, + } } if storeUpgrades != nil { diff --git a/app/upgrades/v3/upgrades_test.go b/app/upgrades/v3/upgrades_test.go new file mode 100644 index 000000000..1bcac0ad4 --- /dev/null +++ b/app/upgrades/v3/upgrades_test.go @@ -0,0 +1,64 @@ +package v3_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/Stride-Labs/stride/v3/app/apptesting" +) +var ( + airdropIdentifiers = []string{"stride", "gaia", "osmosis", "juno", "stars"} +) +const dummyUpgradeHeight = 5 + +type UpgradeTestSuite struct { + apptesting.AppTestHelper +} + +func (s *UpgradeTestSuite) SetupTest() { + s.Setup() +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(UpgradeTestSuite)) +} + +func (suite *UpgradeTestSuite) TestUpgrade() { + testCases := []struct { + msg string + preUpdate func() + update func() + postUpdate func() + expPass bool + }{ + { + "Test that upgrade does not panic", + func() { + suite.Setup() + }, + func() { + suite.ConfirmUpgradeSucceededs("v3", dummyUpgradeHeight) + + // make sure claim record was set + afterCtx := suite.Ctx().WithBlockHeight(dummyUpgradeHeight) + for _, identifier := range(airdropIdentifiers) { + claimRecords := suite.App.ClaimKeeper.GetClaimRecords(afterCtx, identifier) + suite.Require().NotEqual(0, len(claimRecords)) + } + }, + func() { + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + tc.preUpdate() + tc.update() + tc.postUpdate() + }) + } +} diff --git a/app/upgrades/v4/README.md b/app/upgrades/v4/README.md new file mode 100644 index 000000000..2e4ed796a --- /dev/null +++ b/app/upgrades/v4/README.md @@ -0,0 +1,6 @@ +# Upgrade v4 Changelog + +1. Add authz storeKey to StoreLoader +2. Add authz & claim modules to params subspaces + + diff --git a/app/upgrades/v4/upgrades.go b/app/upgrades/v4/upgrades.go new file mode 100644 index 000000000..74db27d00 --- /dev/null +++ b/app/upgrades/v4/upgrades.go @@ -0,0 +1,27 @@ +package v4 + +import ( + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" +) + +// Note: ensure these values are properly set before running upgrade +var ( + UpgradeName = "v4" +) + +// CreateUpgradeHandler creates an SDK upgrade handler for v3 +func CreateUpgradeHandler( + mm *module.Manager, + configurator module.Configurator, +) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + newVm, err := mm.RunMigrations(ctx, configurator, vm) + if err != nil { + return newVm, err + } + return newVm, nil + } +} diff --git a/app/upgrades/v4/upgrades_test.go b/app/upgrades/v4/upgrades_test.go new file mode 100644 index 000000000..bbc46bba0 --- /dev/null +++ b/app/upgrades/v4/upgrades_test.go @@ -0,0 +1,63 @@ +package v4_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/Stride-Labs/stride/v3/app/apptesting" + authz "github.com/cosmos/cosmos-sdk/x/authz" +) + +const dummyUpgradeHeight = 5 + +type UpgradeTestSuite struct { + apptesting.AppTestHelper +} + +func (s *UpgradeTestSuite) SetupTest() { + s.Setup() +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(UpgradeTestSuite)) +} + +func (suite *UpgradeTestSuite) TestUpgrade() { + testCases := []struct { + msg string + preUpdate func() + update func() + postUpdate func() + expPass bool + }{ + { + "Test that upgrade does not panic", + func() { + suite.Setup() + }, + func() { + suite.ConfirmUpgradeSucceededs("v4", dummyUpgradeHeight) + + // make sure authz module was init + afterCtx := suite.Ctx().WithBlockHeight(dummyUpgradeHeight) + actGenState := suite.App.AuthzKeeper.ExportGenesis(afterCtx) + expGenState := authz.DefaultGenesisState() + suite.Require().NotNil(actGenState) + suite.Require().Equal(&expGenState, &actGenState) + }, + func() { + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + tc.preUpdate() + tc.update() + tc.postUpdate() + }) + } +}