/** * The v0_16 x/auth migration logic is adapted from * https://github.com/cosmos/cosmos-sdk/blob/b75c29fc15d3320ec0c7596dbd7c787c48dccad8/x/auth/legacy/v040/migrate.go * * The original migration code is changed here to support the following custom Account from the kava modules. * - `x/validator-vesting/ValidatorVestingAccount` */ package v0_16 import ( "time" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" v039auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v039" v040auth "github.com/cosmos/cosmos-sdk/x/auth/types" v040vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" v015validatorvesting "github.com/kava-labs/kava/x/validator-vesting/legacy/v0_15" ) // convertBaseAccount converts a 0.39 BaseAccount to a 0.40 BaseAccount. func convertBaseAccount(old *v039auth.BaseAccount) *v040auth.BaseAccount { var any *codectypes.Any if old.PubKey != nil { var err error any, err = codectypes.NewAnyWithValue(old.PubKey) if err != nil { panic(err) } } return &v040auth.BaseAccount{ Address: old.Address.String(), PubKey: any, AccountNumber: old.AccountNumber, Sequence: old.Sequence, } } // convertBaseVestingAccount converts a 0.39 BaseVestingAccount to a 0.40 BaseVestingAccount. func convertBaseVestingAccount(old *v039auth.BaseVestingAccount) *v040vesting.BaseVestingAccount { baseAccount := convertBaseAccount(old.BaseAccount) return &v040vesting.BaseVestingAccount{ BaseAccount: baseAccount, OriginalVesting: old.OriginalVesting, DelegatedFree: old.DelegatedFree, DelegatedVesting: old.DelegatedVesting, EndTime: old.EndTime, } } // ResetPeriodicVestingAccount resets a periodic vesting account to a new start // time. The account is modified in place, and vesting periods before the new // start time are removed from the account. func ResetPeriodicVestingAccount(vacc *v040vesting.PeriodicVestingAccount, startTime time.Time) { currentPeriod := vacc.StartTime newOriginalVesting := sdk.Coins{} newStartTime := startTime.Unix() newPeriods := v040vesting.Periods{} for _, period := range vacc.VestingPeriods { currentPeriod = currentPeriod + period.Length // Periods less than the newStartTime are still vesting, // so adjust their length and add them to the newPeriods if newStartTime < currentPeriod { // adjust the length of the first vesting period // to be relative to the new start time if len(newPeriods) == 0 { period.Length = currentPeriod - newStartTime } newOriginalVesting = newOriginalVesting.Add(period.Amount...) newPeriods = append(newPeriods, period) } } // If the new original vesting amount is less than the delegated vesting amount, set delegated vesting // to the new original vesting amount, and add the difference to the delegated free amount for _, delegatedVestingCoin := range vacc.DelegatedVesting { newDelegatedVestingCoin := sdk.NewCoin(delegatedVestingCoin.Denom, sdk.MinInt(delegatedVestingCoin.Amount, newOriginalVesting.AmountOf(delegatedVestingCoin.Denom))) delegationAdjustment := delegatedVestingCoin.Sub(newDelegatedVestingCoin) if !delegationAdjustment.IsZero() { vacc.DelegatedVesting = vacc.DelegatedVesting.Sub(sdk.NewCoins(delegationAdjustment)) vacc.DelegatedFree = vacc.DelegatedFree.Add(delegationAdjustment) } } // update vesting account vacc.StartTime = newStartTime vacc.OriginalVesting = newOriginalVesting vacc.VestingPeriods = newPeriods // ensure end time is >= start time if vacc.StartTime >= vacc.EndTime { vacc.EndTime = vacc.StartTime } } // Migrate accepts exported x/auth genesis state from v0.38/v0.39 and migrates // it to v0.40 x/auth genesis state. The migration includes: // // - Removing coins from account encoding. // - Re-encode in v0.40 GenesisState. func MigrateAuthV040(authGenState v039auth.GenesisState, genesisTime time.Time) *v040auth.GenesisState { // Convert v0.39 accounts to v0.40 ones. var v040Accounts = make([]v040auth.GenesisAccount, len(authGenState.Accounts)) for i, v039Account := range authGenState.Accounts { switch v039Account := v039Account.(type) { case *v039auth.BaseAccount: { v040Accounts[i] = convertBaseAccount(v039Account) } case *v039auth.ModuleAccount: { v040Accounts[i] = &v040auth.ModuleAccount{ BaseAccount: convertBaseAccount(v039Account.BaseAccount), Name: v039Account.Name, Permissions: v039Account.Permissions, } } case *v039auth.BaseVestingAccount: { v040Accounts[i] = convertBaseVestingAccount(v039Account) } case *v039auth.ContinuousVestingAccount: { v040Accounts[i] = &v040vesting.ContinuousVestingAccount{ BaseVestingAccount: convertBaseVestingAccount(v039Account.BaseVestingAccount), StartTime: v039Account.StartTime, } } case *v039auth.DelayedVestingAccount: { v040Accounts[i] = &v040vesting.DelayedVestingAccount{ BaseVestingAccount: convertBaseVestingAccount(v039Account.BaseVestingAccount), } } case *v039auth.PeriodicVestingAccount: { vestingPeriods := make([]v040vesting.Period, len(v039Account.VestingPeriods)) for j, period := range v039Account.VestingPeriods { vestingPeriods[j] = v040vesting.Period{ Length: period.Length, Amount: period.Amount, } } vacc := v040vesting.PeriodicVestingAccount{ BaseVestingAccount: convertBaseVestingAccount(v039Account.BaseVestingAccount), StartTime: v039Account.StartTime, VestingPeriods: vestingPeriods, } ResetPeriodicVestingAccount(&vacc, genesisTime) // If periodic vesting account has zero periods, convert back // to a base account if genesisTime.Unix() >= vacc.EndTime { v040Accounts[i] = vacc.BaseVestingAccount.BaseAccount } else { v040Accounts[i] = &vacc } } case *v015validatorvesting.ValidatorVestingAccount: { // Convert validator vesting accounts to base accounts since no more vesting is needed v040Accounts[i] = convertBaseAccount(v039Account.BaseAccount) } default: panic(sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "got invalid type %T", v039Account)) } } // Convert v0.40 accounts into Anys. anys := make([]*codectypes.Any, len(v040Accounts)) for i, v040Account := range v040Accounts { any, err := codectypes.NewAnyWithValue(v040Account) if err != nil { panic(err) } anys[i] = any } return &v040auth.GenesisState{ Params: v040auth.Params{ MaxMemoCharacters: authGenState.Params.MaxMemoCharacters, TxSigLimit: authGenState.Params.TxSigLimit, TxSizeCostPerByte: authGenState.Params.TxSizeCostPerByte, SigVerifyCostED25519: authGenState.Params.SigVerifyCostED25519, SigVerifyCostSecp256k1: authGenState.Params.SigVerifyCostSecp256k1, }, Accounts: anys, } }