Skip to content

Commit

Permalink
feat: support cosmos lsm (#2909)
Browse files Browse the repository at this point in the history
* bump cosmos-sdk to v0.47.9-ics-lsm

* add migrations

* bump up ethermint

* bump up irismod

* update ValidatorLiquidStakingCap

* delete unused code

* Upgrade cosmos-sdk, patch to fix [GHSA-86h5-xcpx-cfqc](#GHSA-86h5-xcpx-cfqc) vulnerability
  • Loading branch information
Dreamer authored Mar 6, 2024
1 parent 8e788f3 commit ce91df7
Show file tree
Hide file tree
Showing 12 changed files with 394 additions and 279 deletions.
3 changes: 2 additions & 1 deletion app/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"strings"
"testing"

iristypes "github.com/irisnet/irishub/v2/types"
coinswaptypes "github.com/irisnet/irismod/modules/coinswap/types"
htlctypes "github.com/irisnet/irismod/modules/htlc/types"
mttypes "github.com/irisnet/irismod/modules/mt/types"
Expand All @@ -20,6 +19,8 @@ import (
tokentypes "github.com/irisnet/irismod/modules/token/types"
"github.com/stretchr/testify/require"

iristypes "github.com/irisnet/irishub/v2/types"

dbm "github.com/cometbft/cometbft-db"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/libs/log"
Expand Down
1 change: 1 addition & 0 deletions app/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func (app *IrisApp) appKeepers() upgrades.AppKeepers {
ReaderWriter: app,
ConsensusParamsKeeper: app.ConsensusParamsKeeper,
ParamsKeeper: app.ParamsKeeper,
StakingKeeper: app.StakingKeeper,
}
}

Expand Down
85 changes: 0 additions & 85 deletions app/upgrades/helper.go

This file was deleted.

2 changes: 2 additions & 0 deletions app/upgrades/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
consensuskeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper"

Expand Down Expand Up @@ -61,6 +62,7 @@ type AppKeepers struct {
ReaderWriter ConsensusParamsReaderWriter
ConsensusParamsKeeper consensuskeeper.Keeper
ParamsKeeper paramskeeper.Keeper
StakingKeeper *stakingkeeper.Keeper
}

type upgradeRouter struct {
Expand Down
97 changes: 57 additions & 40 deletions app/upgrades/v300/constants.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,59 @@
package v300

var allowMessages = []string{
"/cosmos.authz.v1beta1.MsgExec",
"/cosmos.authz.v1beta1.MsgGrant",
"/cosmos.authz.v1beta1.MsgRevoke",
"/cosmos.bank.v1beta1.MsgSend",
"/cosmos.bank.v1beta1.MsgMultiSend",
"/cosmos.distribution.v1beta1.MsgSetWithdrawAddress",
"/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission",
"/cosmos.distribution.v1beta1.MsgFundCommunityPool",
"/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward",
"/cosmos.feegrant.v1beta1.MsgGrantAllowance",
"/cosmos.feegrant.v1beta1.MsgRevokeAllowance",
"/cosmos.gov.v1beta1.MsgVoteWeighted",
"/cosmos.gov.v1beta1.MsgSubmitProposal",
"/cosmos.gov.v1beta1.MsgDeposit",
"/cosmos.gov.v1beta1.MsgVote",
"/cosmos.gov.v1.MsgVoteWeighted",
"/cosmos.gov.v1.MsgSubmitProposal",
"/cosmos.gov.v1.MsgDeposit",
"/cosmos.gov.v1.MsgVote",
"/cosmos.staking.v1beta1.MsgEditValidator",
"/cosmos.staking.v1beta1.MsgDelegate",
"/cosmos.staking.v1beta1.MsgUndelegate",
"/cosmos.staking.v1beta1.MsgBeginRedelegate",
"/cosmos.staking.v1beta1.MsgCreateValidator",
"/cosmos.vesting.v1beta1.MsgCreateVestingAccount",
"/ibc.applications.transfer.v1.MsgTransfer",
"/irismod.nft.MsgIssueDenom",
"/irismod.nft.MsgTransferDenom",
"/irismod.nft.MsgMintNFT",
"/irismod.nft.MsgEditNFT",
"/irismod.nft.MsgTransferNFT",
"/irismod.nft.MsgBurnNFT",
"/irismod.mt.MsgIssueDenom",
"/irismod.mt.MsgTransferDenom",
"/irismod.mt.MsgMintMT",
"/irismod.mt.MsgEditMT",
"/irismod.mt.MsgTransferMT",
"/irismod.mt.MsgBurnMT",
}
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

var (
// ValidatorBondFactor dictates the cap on the liquid shares
// for a validator - determined as a multiple to their validator bond
// (e.g. ValidatorBondShares = 1000, BondFactor = 250 -> LiquidSharesCap: 250,000)
ValidatorBondFactor = sdk.NewDec(250)
// ValidatorLiquidStakingCap represents a cap on the portion of stake that
// comes from liquid staking providers for a specific validator
ValidatorLiquidStakingCap = sdk.MustNewDecFromStr("1") // 100%
// GlobalLiquidStakingCap represents the percentage cap on
// the portion of a chain's total stake can be liquid
GlobalLiquidStakingCap = sdk.MustNewDecFromStr("0.25") // 25%

allowMessages = []string{
"/cosmos.authz.v1beta1.MsgExec",
"/cosmos.authz.v1beta1.MsgGrant",
"/cosmos.authz.v1beta1.MsgRevoke",
"/cosmos.bank.v1beta1.MsgSend",
"/cosmos.bank.v1beta1.MsgMultiSend",
"/cosmos.distribution.v1beta1.MsgSetWithdrawAddress",
"/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission",
"/cosmos.distribution.v1beta1.MsgFundCommunityPool",
"/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward",
"/cosmos.feegrant.v1beta1.MsgGrantAllowance",
"/cosmos.feegrant.v1beta1.MsgRevokeAllowance",
"/cosmos.gov.v1beta1.MsgVoteWeighted",
"/cosmos.gov.v1beta1.MsgSubmitProposal",
"/cosmos.gov.v1beta1.MsgDeposit",
"/cosmos.gov.v1beta1.MsgVote",
"/cosmos.gov.v1.MsgVoteWeighted",
"/cosmos.gov.v1.MsgSubmitProposal",
"/cosmos.gov.v1.MsgDeposit",
"/cosmos.gov.v1.MsgVote",
"/cosmos.staking.v1beta1.MsgEditValidator",
"/cosmos.staking.v1beta1.MsgDelegate",
"/cosmos.staking.v1beta1.MsgUndelegate",
"/cosmos.staking.v1beta1.MsgBeginRedelegate",
"/cosmos.staking.v1beta1.MsgCreateValidator",
"/cosmos.vesting.v1beta1.MsgCreateVestingAccount",
"/ibc.applications.transfer.v1.MsgTransfer",
"/irismod.nft.MsgIssueDenom",
"/irismod.nft.MsgTransferDenom",
"/irismod.nft.MsgMintNFT",
"/irismod.nft.MsgEditNFT",
"/irismod.nft.MsgTransferNFT",
"/irismod.nft.MsgBurnNFT",
"/irismod.mt.MsgIssueDenom",
"/irismod.mt.MsgTransferDenom",
"/irismod.mt.MsgMintMT",
"/irismod.mt.MsgEditMT",
"/irismod.mt.MsgTransferMT",
"/irismod.mt.MsgBurnMT",
}
)
135 changes: 135 additions & 0 deletions app/upgrades/v300/lsm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package v300

import (
"sort"

"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)

// keeper contains the staking keeper functions required
// for the migration
type keeper interface {
GetAllDelegations(ctx sdk.Context) []types.Delegation
GetAllValidators(ctx sdk.Context) []types.Validator
SetDelegation(ctx sdk.Context, delegation types.Delegation)
SetValidator(ctx sdk.Context, validator types.Validator)
RefreshTotalLiquidStaked(ctx sdk.Context) error
GetParams(ctx sdk.Context) (params types.Params)
SetParams(ctx sdk.Context, params types.Params) error
}

// MigrateParamsStore migrates the params store to the latest version.
//
// ctx - sdk context
// k - keeper
func MigrateParamsStore(ctx sdk.Context, k keeper) {
params := k.GetParams(ctx)
params.ValidatorBondFactor = ValidatorBondFactor
params.ValidatorLiquidStakingCap = ValidatorLiquidStakingCap
params.GlobalLiquidStakingCap = GlobalLiquidStakingCap
k.SetParams(ctx, params)
}

// MigrateValidators Set each validator's ValidatorBondShares and LiquidShares to 0
func MigrateValidators(ctx sdk.Context, k keeper) {
for _, validator := range k.GetAllValidators(ctx) {
validator.ValidatorBondShares = sdk.ZeroDec()
validator.LiquidShares = sdk.ZeroDec()
k.SetValidator(ctx, validator)
}
}

// MigrateDelegations Set each delegation's ValidatorBond field to false
func MigrateDelegations(ctx sdk.Context, k keeper) {
for _, delegation := range k.GetAllDelegations(ctx) {
delegation.ValidatorBond = false
k.SetDelegation(ctx, delegation)
}
}

// MigrateUBDEntries will remove the ubdEntries with same creation_height
// and create a new ubdEntry with updated balance and initial_balance
func MigrateUBDEntries(ctx sdk.Context, store storetypes.KVStore, cdc codec.BinaryCodec) error {
iterator := sdk.KVStorePrefixIterator(store, types.UnbondingDelegationKey)
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
ubd := types.MustUnmarshalUBD(cdc, iterator.Value())

entriesAtSameCreationHeight := make(map[int64][]types.UnbondingDelegationEntry)
for _, ubdEntry := range ubd.Entries {
entriesAtSameCreationHeight[ubdEntry.CreationHeight] = append(entriesAtSameCreationHeight[ubdEntry.CreationHeight], ubdEntry)
}

creationHeights := make([]int64, 0, len(entriesAtSameCreationHeight))
for k := range entriesAtSameCreationHeight {
creationHeights = append(creationHeights, k)
}

sort.Slice(creationHeights, func(i, j int) bool { return creationHeights[i] < creationHeights[j] })

ubd.Entries = make([]types.UnbondingDelegationEntry, 0, len(creationHeights))

for _, h := range creationHeights {
ubdEntry := types.UnbondingDelegationEntry{
Balance: sdk.ZeroInt(),
InitialBalance: sdk.ZeroInt(),
}
for _, entry := range entriesAtSameCreationHeight[h] {
ubdEntry.Balance = ubdEntry.Balance.Add(entry.Balance)
ubdEntry.InitialBalance = ubdEntry.InitialBalance.Add(entry.InitialBalance)
ubdEntry.CreationHeight = entry.CreationHeight
ubdEntry.CompletionTime = entry.CompletionTime
}
ubd.Entries = append(ubd.Entries, ubdEntry)
}

// set the new ubd to the store
setUBDToStore(ctx, store, cdc, ubd)
}
return nil
}

func setUBDToStore(_ sdk.Context, store storetypes.KVStore, cdc codec.BinaryCodec, ubd types.UnbondingDelegation) {
delegatorAddress := sdk.MustAccAddressFromBech32(ubd.DelegatorAddress)

bz := types.MustMarshalUBD(cdc, ubd)

addr, err := sdk.ValAddressFromBech32(ubd.ValidatorAddress)
if err != nil {
panic(err)
}

key := types.GetUBDKey(delegatorAddress, addr)

store.Set(key, bz)
}

// MigrateStore performs the in-place store migration for adding LSM support to v0.45.16-ics, including:
// - Adding params ValidatorBondFactor, GlobalLiquidStakingCap, ValidatorLiquidStakingCap
// - Setting each validator's ValidatorBondShares and LiquidShares to 0
// - Setting each delegation's ValidatorBond field to false
// - Calculating the total liquid staked by summing the delegations from ICA accounts
func MigrateStore(ctx sdk.Context, storeKey storetypes.StoreKey, cdc codec.BinaryCodec, k keeper) error {
store := ctx.KVStore(storeKey)

ctx.Logger().Info("Staking LSM Migration: Migrating param store")
MigrateParamsStore(ctx, k)

ctx.Logger().Info("Staking LSM Migration: Migrating validators")
MigrateValidators(ctx, k)

ctx.Logger().Info("Staking LSM Migration: Migrating delegations")
MigrateDelegations(ctx, k)

ctx.Logger().Info("Staking LSM Migration: Migrating UBD entries")
if err := MigrateUBDEntries(ctx, store, cdc); err != nil {
return err
}

ctx.Logger().Info("Staking LSM Migration: Calculating total liquid staked")
return k.RefreshTotalLiquidStaked(ctx)
}
Loading

0 comments on commit ce91df7

Please sign in to comment.