diff --git a/app/app.go b/app/app.go index c0ac68fa..0976b785 100644 --- a/app/app.go +++ b/app/app.go @@ -59,7 +59,7 @@ import ( atomoneante "github.com/atomone-hub/atomone/ante" "github.com/atomone-hub/atomone/app/keepers" "github.com/atomone-hub/atomone/app/upgrades" - v4 "github.com/atomone-hub/atomone/app/upgrades/v4" + v41 "github.com/atomone-hub/atomone/app/upgrades/v4_1" "github.com/atomone-hub/atomone/client/docs" atomonepost "github.com/atomone-hub/atomone/post" ) @@ -68,7 +68,7 @@ var ( // DefaultNodeHome default home directories for the application daemon DefaultNodeHome string - Upgrades = []upgrades.Upgrade{v4.Upgrade} + Upgrades = []upgrades.Upgrade{v41.Upgrade} ) var ( diff --git a/app/upgrades/v4_1/constants.go b/app/upgrades/v4_1/constants.go new file mode 100644 index 00000000..bd812c43 --- /dev/null +++ b/app/upgrades/v4_1/constants.go @@ -0,0 +1,20 @@ +package v4_1 + +import ( + store "cosmossdk.io/store/types" + + "github.com/atomone-hub/atomone/app/upgrades" +) + +const ( + // UpgradeName is the on-chain name of the testnet-only v4.1 upgrade. + UpgradeName = "v4.1" +) + +var Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, + CreateUpgradeHandler: CreateUpgradeHandler, + // No store changes: this upgrade only initializes the staking + // KeyRotationFee param missed by the testnet's v4 run. + StoreUpgrades: store.StoreUpgrades{}, +} diff --git a/app/upgrades/v4_1/upgrades.go b/app/upgrades/v4_1/upgrades.go new file mode 100644 index 00000000..d0a96175 --- /dev/null +++ b/app/upgrades/v4_1/upgrades.go @@ -0,0 +1,55 @@ +package v4_1 + +import ( + "context" + + "cosmossdk.io/math" + upgradetypes "cosmossdk.io/x/upgrade/types" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + + "github.com/atomone-hub/atomone/app/keepers" +) + +// CreateUpgradeHandler returns the upgrade handler for AtomOne v4.1. +// +// This is a testnet-only upgrade. The testnet ran the v4 upgrade with a binary +// (v4.0.0-rc) that predated the consensus pubkey rotation feature, so its v4 +// handler never initialized the staking KeyRotationFee param. Mainnet is +// unaffected: it runs the v4.0.0 binary whose MigrateStakingParams sets the +// param during the v4 upgrade. After this upgrade the testnet reaches the same +// post-v4 state as mainnet. +// +// No module consensus version changed between the two binaries, so there are no +// pending module migrations and RunMigrations is intentionally not called. +func CreateUpgradeHandler( + _ *module.Manager, + _ codec.Codec, + _ module.Configurator, + keepers *keepers.AppKeepers, +) upgradetypes.UpgradeHandler { + return func(ctx context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + if err := InitKeyRotationFee(ctx, keepers.StakingKeeper); err != nil { + return vm, err + } + return vm, nil + } +} + +// InitKeyRotationFee initializes the staking KeyRotationFee param to 100 ATONE, +// mirroring the value set by v4.MigrateStakingParams so the testnet converges to +// the same state as mainnet. +func InitKeyRotationFee(ctx context.Context, stakingKeeper *stakingkeeper.Keeper) error { + params, err := stakingKeeper.GetParams(ctx) + if err != nil { + return err + } + + // Initialize the consensus pubkey rotation fee to 100 ATONEs + params.KeyRotationFee = sdk.NewCoin(params.BondDenom, math.NewInt(100_000000)) + + return stakingKeeper.SetParams(ctx, params) +} diff --git a/app/upgrades/v4_1/upgrades_test.go b/app/upgrades/v4_1/upgrades_test.go new file mode 100644 index 00000000..590ca945 --- /dev/null +++ b/app/upgrades/v4_1/upgrades_test.go @@ -0,0 +1,29 @@ +package v4_1_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/atomone-hub/atomone/app/helpers" + v4_1 "github.com/atomone-hub/atomone/app/upgrades/v4_1" +) + +func TestInitKeyRotationFee(t *testing.T) { + app := helpers.Setup(t) + ctx := app.NewUncachedContext(false, cmtproto.Header{}) + sk := app.StakingKeeper + + require.NoError(t, v4_1.InitKeyRotationFee(ctx, sk)) + + got, err := sk.GetParams(ctx) + require.NoError(t, err) + require.NoError(t, got.Validate()) + require.Equal(t, sdk.NewCoin(got.BondDenom, math.NewInt(100_000000)), got.KeyRotationFee) +}