Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LSM Migration for v14 #910

Merged
merged 16 commits into from
Aug 27, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions app/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,17 @@ func (app *StrideApp) setupUpgradeHandlers(appOpts servertypes.AppOptions) {
v14.UpgradeName,
v14.CreateUpgradeHandler(
app.mm,
app.VestingKeeper,
app.StakingKeeper,
app.BankKeeper,
app.AccountKeeper,
app.configurator,
app.StakeibcKeeper,
&app.ConsumerKeeper,
app.appCodec,
app.AccountKeeper,
app.BankKeeper,
app.ClaimKeeper,
&app.ConsumerKeeper,
app.InterchainqueryKeeper,
app.StakeibcKeeper,
app.StakingKeeper,
app.VestingKeeper,
app.keys[stakeibctypes.StoreKey],
),
)

Expand Down
102 changes: 84 additions & 18 deletions app/upgrades/v14/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,38 @@ import (
"time"

errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/module"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
sdkvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
ccvconsumerkeeper "github.com/cosmos/interchain-security/v3/x/ccv/consumer/keeper"

stakeibctypes "github.com/Stride-Labs/stride/v13/x/stakeibc/types"

claimkeeper "github.com/Stride-Labs/stride/v13/x/claim/keeper"
claimtypes "github.com/Stride-Labs/stride/v13/x/claim/types"
stakeibckeeper "github.com/Stride-Labs/stride/v13/x/stakeibc/keeper"

// evmosvestingclient "github.com/evmos/vesting/x/vesting/client"
sdkvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
evmosvestingkeeper "github.com/evmos/vesting/x/vesting/keeper"
"github.com/evmos/vesting/x/vesting/types"
evmosvestingtypes "github.com/evmos/vesting/x/vesting/types"

// "github.com/cosmos/cosmos-sdk/x/auth/vesting"
vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
"github.com/Stride-Labs/stride/v13/utils"
claimkeeper "github.com/Stride-Labs/stride/v13/x/claim/keeper"
claimtypes "github.com/Stride-Labs/stride/v13/x/claim/types"
icqkeeper "github.com/Stride-Labs/stride/v13/x/interchainquery/keeper"
stakeibckeeper "github.com/Stride-Labs/stride/v13/x/stakeibc/keeper"
stakeibcmigration "github.com/Stride-Labs/stride/v13/x/stakeibc/migrations/v3"
stakeibctypes "github.com/Stride-Labs/stride/v13/x/stakeibc/types"
)

var (
UpgradeName = "v14"

GaiaChainId = "cosmoshub-4"

// Vesting
VestingStartTimeAccount1 = int64(1662350400) // Sept 4, 2022
VestingEndTimeAccount1 = int64(1788512452)
Expand Down Expand Up @@ -81,25 +83,46 @@ var (
// CreateUpgradeHandler creates an SDK upgrade handler for v14
func CreateUpgradeHandler(
mm *module.Manager,
evmosvestingKeeper evmosvestingkeeper.Keeper,
stakingKeeper stakingkeeper.Keeper,
bankKeeper bankkeeper.Keeper,
accountKeeper authkeeper.AccountKeeper,
configurator module.Configurator,
stakeibcKeeper stakeibckeeper.Keeper,
consumerKeeper *ccvconsumerkeeper.Keeper,
cdc codec.Codec,
accountKeeper authkeeper.AccountKeeper,
bankKeeper bankkeeper.Keeper,
claimKeeper claimkeeper.Keeper,
consumerKeeper *ccvconsumerkeeper.Keeper,
icqKeeper icqkeeper.Keeper,
stakeibcKeeper stakeibckeeper.Keeper,
stakingKeeper stakingkeeper.Keeper,
evmosvestingKeeper evmosvestingkeeper.Keeper,
stakeibcStoreKey storetypes.StoreKey,
) upgradetypes.UpgradeHandler {
return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
ctx.Logger().Info("Starting upgrade v14...")

evk := evmosvestingKeeper
sk := stakingKeeper
ak := accountKeeper
bk := bankKeeper
ck := consumerKeeper
sibc := stakeibcKeeper
currentVersions := mm.GetVersionMap()

// AIRDROP CHANGES
// Migrate the Validator and HostZone structs from stakeibc
utils.LogModuleMigration(ctx, currentVersions, stakeibctypes.ModuleName)
if err := stakeibcmigration.MigrateStore(ctx, stakeibcStoreKey, cdc); err != nil {
return vm, errorsmod.Wrapf(err, "unable to migrate stakeibc store")
}

// Update Stakeibc Params
MigrateStakeibcParams(ctx, stakeibcKeeper)

// Clear out any pending queries since the Query type updated
// There shouldn't be any queries here unless the upgrade happened right at the epoch
ClearPendingQueries(ctx, icqKeeper)

// Enable LSM for the Gaia
EnableLSMForGaia(ctx, stakeibcKeeper)

// Add airdrops for Injective, Comedex, Somm, and Umee
if err := InitAirdrops(ctx, claimKeeper); err != nil {
return vm, errorsmod.Wrapf(err, "unable to migrate airdrop")
}
Expand Down Expand Up @@ -129,6 +152,16 @@ func CreateUpgradeHandler(
return vm, errorsmod.Wrapf(err, "unable to send consumer fee pool to fee distribution")
}

// `RunMigrations` (below) checks the old consensus version of each module (found in
// the store) and compares it against the updated consensus version in the binary
// If the old and new consensus versions are not the same, it attempts to call that
// module's migration function that must be registered ahead of time
//
// Since the migrations above were executed directly (instead of being registered
// and invoked through a Migrator), we need to set the module versions in the versionMap
// to the new version, to prevent RunMigrations from attempting to re-run each migrations
vm[stakeibctypes.ModuleName] = currentVersions[stakeibctypes.ModuleName]

return mm.RunMigrations(ctx, configurator, vm)
}
}
Expand Down Expand Up @@ -252,6 +285,39 @@ func MigrateAccount1(ctx sdk.Context, evk evmosvestingkeeper.Keeper, sk stakingk
return nil
}

// Migrate the stakeibc params, specifically:
// - Remove SafetyNumValidators
// - Remove SafetyMaxSlashPercentage
// - Add ValidatorSlashQueryThreshold
//
// NOTE: If a parameter is added, the old params cannot be unmarshalled
// to the new schema. To get around this, we have to set each parameter explicitly
// Considering all mainnet stakeibc params are set to the default, we can just use that
func MigrateStakeibcParams(ctx sdk.Context, k stakeibckeeper.Keeper) {
params := stakeibctypes.DefaultParams()
k.SetParams(ctx, params)
}

// Since the Query struct was updated, it's easier to just clear out any pending
// queries rather than attempt to migrate them
func ClearPendingQueries(ctx sdk.Context, k icqkeeper.Keeper) {
for _, query := range k.AllQueries(ctx) {
k.DeleteQuery(ctx, query.Id)
}
}

// Enable LSM liquid stakes for Gaia
func EnableLSMForGaia(ctx sdk.Context, k stakeibckeeper.Keeper) error {
hostZone, found := k.GetHostZone(ctx, GaiaChainId)
if !found {
return stakeibctypes.ErrHostZoneNotFound.Wrapf(GaiaChainId)
}

hostZone.LsmLiquidStakeEnabled = true
riley-stride marked this conversation as resolved.
Show resolved Hide resolved
k.SetHostZone(ctx, hostZone)

return nil
}
func MigrateAccount2(ctx sdk.Context, ak authkeeper.AccountKeeper) error {
// Get account
account := ak.GetAccount(ctx, sdk.MustAccAddressFromBech32(Account2))
Expand Down
117 changes: 108 additions & 9 deletions app/upgrades/v14/upgrades_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ import (
"time"

sdkmath "cosmossdk.io/math"
evmosvestingtypes "github.com/evmos/vesting/x/vesting/types"

stakeibctypes "github.com/Stride-Labs/stride/v13/x/stakeibc/types"

"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/auth/vesting/types"

sdk "github.com/cosmos/cosmos-sdk/types"
evmosvestingtypes "github.com/evmos/vesting/x/vesting/types"
"github.com/stretchr/testify/suite"

claimtypes "github.com/Stride-Labs/stride/v13/x/claim/types"

"github.com/Stride-Labs/stride/v13/app"
"github.com/Stride-Labs/stride/v13/app/apptesting"
v14 "github.com/Stride-Labs/stride/v13/app/upgrades/v14"
claimtypes "github.com/Stride-Labs/stride/v13/x/claim/types"
interchainquerytypes "github.com/Stride-Labs/stride/v13/x/interchainquery/types"
oldstakeibctypes "github.com/Stride-Labs/stride/v13/x/stakeibc/migrations/v3/types"
stakeibctypes "github.com/Stride-Labs/stride/v13/x/stakeibc/types"
)

var (
Expand Down Expand Up @@ -52,6 +52,8 @@ func (s *UpgradeTestSuite) TestUpgrade() {
s.SetupVestingStoreBeforeUpgrade()
s.FundConsToSendToProviderModuleAccount()
s.SetupConsumerRewards()
checkStakeibcStoreAfterUpgrade := s.SetupOldStakeibcStore()
checkPendingQueriesRemoved := s.SetupPendingQueries()

// Upgrade
s.ConfirmUpgradeSucceededs("v14", dummyUpgradeHeight)
Expand All @@ -62,6 +64,9 @@ func (s *UpgradeTestSuite) TestUpgrade() {
s.CheckRefundAfterUpgrade()
s.CheckAirdropsInitialized()
s.VerifyConsumerRewards()
s.CheckAirdropsInitialized()
checkStakeibcStoreAfterUpgrade()
checkPendingQueriesRemoved()
}

func (s *UpgradeTestSuite) SetupConsumerRewards() {
Expand Down Expand Up @@ -169,7 +174,6 @@ func (s *UpgradeTestSuite) CheckVestingStoreAfterUpgrade() {
s.Require().Equal(expectedVestedCoins, coins.AmountOf(s.App.StakingKeeper.BondDenom(s.Ctx)).Int64())
}

// ---------------------- Utils ----------------------
func initBaseAccount(address sdk.AccAddress) *authtypes.BaseAccount {
bacc := authtypes.NewBaseAccountWithAddress(address)
return bacc
Expand Down Expand Up @@ -214,6 +218,7 @@ func (s *UpgradeTestSuite) SetupAirdrops() {
}
err := s.App.ClaimKeeper.SetParams(s.Ctx, params)
s.Require().NoError(err, "no error expected when setting claim params")

// Set vesting to 0s
claimtypes.DefaultVestingInitialPeriod, err = time.ParseDuration("0s")
s.Require().NoError(err, "no error expected when setting vesting initial period")
Expand Down Expand Up @@ -248,6 +253,7 @@ func (s *UpgradeTestSuite) CheckAirdropsInitialized() {
s.CheckAirdropAdded(afterCtx, umeeAirdrop, v14.UmeeAirdropDistributor, v14.UmeeAirdropIdentifier, v14.UmeeChainId, false)
}

// Helper function to check the attributes of the new Airdrop
func (s *UpgradeTestSuite) CheckAirdropAdded(ctx sdk.Context, airdrop *claimtypes.Airdrop, distributor string, identifier string, chainId string, autopilotEnabled bool) {
// Check that the params of the airdrop were initialized
s.Require().Equal(identifier, airdrop.AirdropIdentifier, fmt.Sprintf("%s airdrop identifier", identifier))
Expand All @@ -268,3 +274,96 @@ func (s *UpgradeTestSuite) CheckAirdropAdded(ctx sdk.Context, airdrop *claimtype
s.Require().Zero(epochInfo.CurrentEpoch, "epoch should be zero")
s.Require().Equal(epochInfo.Duration, claimtypes.DefaultEpochDuration, "epoch duration should be equal to airdrop duration")
}

// Setups up the stakeibc store with old host zones before the upgrade
// Returns a callback function that verifies the expected state after the upgrade
func (s *UpgradeTestSuite) SetupOldStakeibcStore() func() {
codec := app.MakeEncodingConfig().Marshaler
stakeibcStore := s.Ctx.KVStore(s.App.GetKey(stakeibctypes.StoreKey))
hostzoneStore := prefix.NewStore(stakeibcStore, stakeibctypes.KeyPrefix(stakeibctypes.HostZoneKey))

// Add two host zones with the old type
for i := int64(1); i <= 2; i++ {
hostZone := oldstakeibctypes.HostZone{
ChainId: fmt.Sprintf("chain-%d", i),
Address: fmt.Sprintf("address-%d", i),
UnbondingFrequency: 3,
DelegationAccount: &oldstakeibctypes.ICAAccount{
Address: fmt.Sprintf("delegation-%d", i),
},
BlacklistedValidators: []*oldstakeibctypes.Validator{
{Name: "val", Address: "address"},
},
StakedBal: sdkmath.NewInt(i),
Validators: []*oldstakeibctypes.Validator{
{
Address: fmt.Sprintf("val-%d", i),
InternalExchangeRate: &oldstakeibctypes.ValidatorExchangeRate{
InternalTokensToSharesRate: sdk.NewDec(i),
},
DelegationAmt: sdk.NewInt(i),
},
},
}

hostZoneBz := codec.MustMarshal(&hostZone)
hostzoneStore.Set([]byte(hostZone.ChainId), hostZoneBz)
}

// Add gaia host to test that LSM is enabled
hostZoneBz := codec.MustMarshal(&oldstakeibctypes.HostZone{
ChainId: v14.GaiaChainId,
})
hostzoneStore.Set([]byte(v14.GaiaChainId), hostZoneBz)

return func() {
// Confirm the host zones have been migrated properly
for i := int64(1); i <= 2; i++ {
hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, fmt.Sprintf("chain-%d", i))
s.Require().True(found)

// Check new host zone attributes
s.Require().Equal(fmt.Sprintf("chain-%d", i), hostZone.ChainId, "chain-id")
s.Require().Equal(fmt.Sprintf("address-%d", i), hostZone.DepositAddress, "deposit address")
s.Require().Equal(fmt.Sprintf("delegation-%d", i), hostZone.DelegationIcaAddress, "delegation address")
s.Require().Equal(uint64(14), hostZone.UnbondingPeriod, "unbonding period")
s.Require().Equal(sdkmath.NewInt(i), hostZone.TotalDelegations, "total delegations")
s.Require().Equal(false, hostZone.LsmLiquidStakeEnabled, "total delegations")

// Check new validator attributes
validator := hostZone.Validators[0]
s.Require().Equal(fmt.Sprintf("val-%d", i), validator.Address, "validator address")
s.Require().Equal(sdk.NewDec(i), validator.SharesToTokensRate, "validator shares to tokens rate")
s.Require().Equal(false, validator.SlashQueryInProgress, "validator slash query in progress")
s.Require().Equal(int64(0), validator.DelegationChangesInProgress, "validator delegations in progress")
s.Require().Equal(sdk.ZeroInt(), validator.SlashQueryProgressTracker, "validator delegations in progress")
}

// Confirm gaia has LSM enabled
hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, v14.GaiaChainId)
s.Require().True(found)
s.Require().True(hostZone.LsmLiquidStakeEnabled)

// Finally check that the new params were set
params := s.App.StakeibcKeeper.GetParams(s.Ctx)
s.Require().Equal(stakeibctypes.DefaultParams(), params, "new params set after upgrade")
}
}

// Setups pending queries in the store to test that the queries were removed
// Returns a callback function to verify they were removed
func (s *UpgradeTestSuite) SetupPendingQueries() func() {
for i := 0; i < 3; i++ {
s.App.InterchainqueryKeeper.SetQuery(s.Ctx, interchainquerytypes.Query{
Id: fmt.Sprintf("query-%d", i),
})
}

numQueries := len(s.App.InterchainqueryKeeper.AllQueries(s.Ctx))
s.Require().Equal(3, numQueries, "number of queres before the upgrade")

return func() {
numQueries := len(s.App.InterchainqueryKeeper.AllQueries(s.Ctx))
s.Require().Zero(numQueries, "number of queres after the upgrade")
}
}
7 changes: 7 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/types/bech32"
"github.com/cosmos/cosmos-sdk/types/module"

errorsmod "cosmossdk.io/errors"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
Expand Down Expand Up @@ -270,3 +271,9 @@ func LogHeader(s string, a ...any) string {
pad := strings.Repeat("-", (lineLength-len(header))/2)
return fmt.Sprintf("%s %s %s", pad, header, pad)
}

// Logs a module's migration info
func LogModuleMigration(ctx sdk.Context, versionMap module.VersionMap, moduleName string) {
currentVersion := versionMap[moduleName]
ctx.Logger().Info(fmt.Sprintf("migrating module %s from version %d to version %d", moduleName, currentVersion-1, currentVersion))
}
2 changes: 1 addition & 1 deletion x/records/keeper/callback_lsm_transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (

errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/gogoproto/proto"
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
"github.com/golang/protobuf/proto" //nolint:staticcheck
)

// Callback after an LSM token is IBC tranferred to the host zone
Expand Down
6 changes: 4 additions & 2 deletions x/stakeibc/keeper/host_zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,10 @@ func (k Keeper) DecrementValidatorDelegationChangesInProgress(hostZone *types.Ho
return errorsmod.Wrapf(types.ErrValidatorNotFound, "validator %s not found", validatorAddress)
}
if validator.DelegationChangesInProgress == 0 {
return errorsmod.Wrapf(types.ErrInvalidValidatorDelegationUpdates,
"cannot decrement the number of delegation updates if the validator has 0 updates in progress")
// TODO: Revert after upgrade v14
// return errorsmod.Wrapf(types.ErrInvalidValidatorDelegationUpdates,
// "cannot decrement the number of delegation updates if the validator has 0 updates in progress")
return nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand it this is the 0 floor. In theory this line should not be reachable, so imo we should emit an event here and log before returning nil, so that we can trace any issues. Then in v14 we revert.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good call, added a log

}
validator.DelegationChangesInProgress -= 1
hostZone.Validators[valIndex] = &validator
Expand Down
Loading