Skip to content

Commit

Permalink
provider migration
Browse files Browse the repository at this point in the history
  • Loading branch information
shaspitz committed May 22, 2023
1 parent 2d95e2e commit dbf9ded
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 9 deletions.
6 changes: 3 additions & 3 deletions x/ccv/consumer/keeper/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import (

// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
ccvConsumerParamSpace paramtypes.Subspace
ccvConsumerKeeper Keeper
ccvConsumerParamSpace paramtypes.Subspace
}

// NewMigrator returns a new Migrator.
func NewMigrator(ccvConsumerKeeper Keeper) Migrator {
return Migrator{ccvConsumerKeeper: ccvConsumerKeeper}
func NewMigrator(ccvConsumerKeeper Keeper, ccvConsumerParamSpace paramtypes.Subspace) Migrator {
return Migrator{ccvConsumerKeeper: ccvConsumerKeeper, ccvConsumerParamSpace: ccvConsumerParamSpace}
}

func (m Migrator) Migratev1p0To1p3(ctx sdk.Context) error {
Expand Down
4 changes: 4 additions & 0 deletions x/ccv/provider/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ func NewKeeper(
return k
}

func (k *Keeper) SetParamSpace(ctx sdk.Context, ps paramtypes.Subspace) {
k.paramSpace = ps
}

// Validates that the provider keeper is initialized with non-zero and
// non-nil values for all its fields. Otherwise this method will panic.
func (k Keeper) mustValidateFields() {
Expand Down
75 changes: 75 additions & 0 deletions x/ccv/provider/keeper/migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package keeper

import (
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
ibctmtypes "github.com/cosmos/ibc-go/v4/modules/light-clients/07-tendermint/types"
providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types"
ccvtypes "github.com/cosmos/interchain-security/x/ccv/types"
)

// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
ccvProviderKeeper Keeper
stakingKeeper ccvtypes.StakingKeeper
ccvProviderParamSpace paramtypes.Subspace
}

// NewMigrator returns a new Migrator.
func NewMigrator(ccvProviderKeeper Keeper, stakingKeeper ccvtypes.StakingKeeper,
ccvProviderParamSpace paramtypes.Subspace) Migrator {
return Migrator{ccvProviderKeeper: ccvProviderKeeper, ccvProviderParamSpace: ccvProviderParamSpace}
}

func (m Migrator) Migratev1p0To1p3(ctx sdk.Context) error {
// Migrate params
MigrateParamsv1p0To1p3(ctx,
m.ccvProviderParamSpace,
// See https://github.com/cosmos/interchain-security/blob/7861804cb311507ec6aebebbfad60ea42eb8ed4b/x/ccv/provider/keeper/params.go#L84
// The v1.1.0-multiden version of ICS hardcodes this param as 10 of bond type: k.stakingKeeper.BondDenom(ctx).
// Here we use the same starting value, but the param can now be changed through governance.
sdk.NewCoin(m.stakingKeeper.BondDenom(ctx), sdk.NewInt(10000000)),
)

return nil
}

// MigrateParamsv1p0To1p3 migrates the provider CCV module params from v1.0.0 to v1.3.0,
// setting default values for new params.
func MigrateParamsv1p0To1p3(ctx sdk.Context, paramsSubspace paramtypes.Subspace, consumerRewardDenomRegistrationFee sdk.Coin) {
// Get old params
var templateClient ibctmtypes.ClientState
paramsSubspace.Get(ctx, providertypes.KeyTemplateClient, &templateClient)
var trustingPeriodFraction string
paramsSubspace.Get(ctx, providertypes.KeyTrustingPeriodFraction, &trustingPeriodFraction)
var ccvTimeoutPeriod time.Duration
paramsSubspace.Get(ctx, ccvtypes.KeyCCVTimeoutPeriod, &ccvTimeoutPeriod)
var initTimeoutPeriod time.Duration
paramsSubspace.Get(ctx, providertypes.KeyInitTimeoutPeriod, &initTimeoutPeriod)
var vscTimeoutPeriod time.Duration
paramsSubspace.Get(ctx, providertypes.KeyVscTimeoutPeriod, &vscTimeoutPeriod)
var slashMeterReplenishPeriod time.Duration
paramsSubspace.Get(ctx, providertypes.KeySlashMeterReplenishPeriod, &slashMeterReplenishPeriod)
var slashMeterReplenishFraction string
paramsSubspace.Get(ctx, providertypes.KeySlashMeterReplenishFraction, &slashMeterReplenishFraction)
var maxThrottledPackets int64
paramsSubspace.Get(ctx, providertypes.KeyMaxThrottledPackets, &maxThrottledPackets)

// Recycle old params, set new param to input value
newParams := providertypes.NewParams(
&templateClient,
trustingPeriodFraction,
ccvTimeoutPeriod,
initTimeoutPeriod,
vscTimeoutPeriod,
slashMeterReplenishPeriod,
slashMeterReplenishFraction,
maxThrottledPackets,
consumerRewardDenomRegistrationFee,
)

// Persist new params
paramsSubspace.SetParamSet(ctx, &newParams)
}
130 changes: 130 additions & 0 deletions x/ccv/provider/keeper/migration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package keeper_test

import (
"testing"
"time"

"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/store"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
types2 "github.com/cosmos/ibc-go/v4/modules/light-clients/07-tendermint/types"
providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper"
providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types"
ccvtypes "github.com/cosmos/interchain-security/x/ccv/types"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmdb "github.com/tendermint/tm-db"
)

func TestMigrateParamsv1p0To1p3(t *testing.T) {
// Setup raw store
db := tmdb.NewMemDB()
stateStore := store.NewCommitMultiStore(db)
storeKey := sdk.NewKVStoreKey(paramtypes.StoreKey)
memStoreKey := storetypes.NewMemoryStoreKey("mem_key")
stateStore.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db)
stateStore.MountStoreWithDB(memStoreKey, sdk.StoreTypeMemory, nil)
require.NoError(t, stateStore.LoadLatestVersion())
registry := codectypes.NewInterfaceRegistry()
cdc := codec.NewProtoCodec(registry)
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())
require.NoError(t, stateStore.LoadLatestVersion())

// Create new empty subspace
subspace := paramtypes.NewSubspace(cdc,
codec.NewLegacyAmino(),
storeKey,
memStoreKey,
paramtypes.ModuleName,
)

// Note that new param key table is set in keeper constructor
subspace = subspace.WithKeyTable(v1p0p0KeyTable())

// Set 8 params from v1.0.0
subspace.Set(ctx, providertypes.KeyTemplateClient, providertypes.DefaultParams().TemplateClient)
subspace.Set(ctx, providertypes.KeyTrustingPeriodFraction, "0.75")
subspace.Set(ctx, ccvtypes.KeyCCVTimeoutPeriod, time.Hour)
subspace.Set(ctx, providertypes.KeyInitTimeoutPeriod, time.Hour)
subspace.Set(ctx, providertypes.KeyVscTimeoutPeriod, time.Hour)
subspace.Set(ctx, providertypes.KeySlashMeterReplenishPeriod, time.Hour)
subspace.Set(ctx, providertypes.KeySlashMeterReplenishFraction, "0.5")
subspace.Set(ctx, providertypes.KeyMaxThrottledPackets, int64(10))

// Confirm new param cannot be set with old key table
require.Panics(t, func() {
subspace.Set(ctx, providertypes.KeyConsumerRewardDenomRegistrationFee, sdk.NewInt64Coin("uatom", 100))
})

// Now create new subspace, mocking an upgrade where app initialization happens again
subspace = paramtypes.NewSubspace(cdc,
codec.NewLegacyAmino(),
storeKey,
memStoreKey,
paramtypes.ModuleName,
).WithKeyTable(providertypes.ParamKeyTable()) // Use new key table, this would be set in keeper constructor

// Run migration
providerkeeper.MigrateParamsv1p0To1p3(ctx, subspace, sdk.NewCoin("uatom", sdk.NewInt(100000)))

// Use keeper to confirm params are set correctly
keeper := providerkeeper.Keeper{}
keeper.SetParamSpace(ctx, subspace)

params := keeper.GetParams(ctx)
require.Equal(t, providertypes.DefaultParams().TemplateClient, params.TemplateClient)
require.Equal(t, "0.75", params.TrustingPeriodFraction)
require.Equal(t, time.Hour, params.CcvTimeoutPeriod)
require.Equal(t, time.Hour, params.InitTimeoutPeriod)
require.Equal(t, time.Hour, params.VscTimeoutPeriod)
require.Equal(t, time.Hour, params.SlashMeterReplenishPeriod)
require.Equal(t, "0.5", params.SlashMeterReplenishFraction)
require.Equal(t, int64(10), params.MaxThrottledPackets)
// New param should be set
require.Equal(t, sdk.NewCoin("uatom", sdk.NewInt(100000)), params.ConsumerRewardDenomRegistrationFee)

// Set new params to other values
params.ConsumerRewardDenomRegistrationFee = sdk.NewCoin("uatom", sdk.NewInt(1000000000))
keeper.SetParams(ctx, params)
require.Equal(t, sdk.NewCoin("uatom", sdk.NewInt(1000000000)), keeper.GetParams(ctx).ConsumerRewardDenomRegistrationFee)
}

//
// Note: the following methods and struct could be removed if v1.3.0 is actually defined as v2.0.0
// and we bump the go.mod package name accordingly
//

// v1p0p0Params is a copy of the ParamKeyTable method from v1.0.0
func v1p0p0KeyTable() paramtypes.KeyTable {
return paramtypes.NewKeyTable().RegisterParamSet(&v1p0p0Params{})
}

// ParamSetPairs implements params.ParamSet for v1p0p0Params
func (p *v1p0p0Params) ParamSetPairs() paramtypes.ParamSetPairs {
return paramtypes.ParamSetPairs{
paramtypes.NewParamSetPair(providertypes.KeyTemplateClient, p.TemplateClient, providertypes.ValidateTemplateClient),
paramtypes.NewParamSetPair(providertypes.KeyTrustingPeriodFraction, p.TrustingPeriodFraction, ccvtypes.ValidateStringFraction),
paramtypes.NewParamSetPair(ccvtypes.KeyCCVTimeoutPeriod, p.CcvTimeoutPeriod, ccvtypes.ValidateDuration),
paramtypes.NewParamSetPair(providertypes.KeyInitTimeoutPeriod, p.InitTimeoutPeriod, ccvtypes.ValidateDuration),
paramtypes.NewParamSetPair(providertypes.KeyVscTimeoutPeriod, p.VscTimeoutPeriod, ccvtypes.ValidateDuration),
paramtypes.NewParamSetPair(providertypes.KeySlashMeterReplenishPeriod, p.SlashMeterReplenishPeriod, ccvtypes.ValidateDuration),
paramtypes.NewParamSetPair(providertypes.KeySlashMeterReplenishFraction, p.SlashMeterReplenishFraction, ccvtypes.ValidateStringFraction),
paramtypes.NewParamSetPair(providertypes.KeyMaxThrottledPackets, p.MaxThrottledPackets, ccvtypes.ValidatePositiveInt64),
}
}

// v1p0p0Params is a copy of the Params struct from v1.0.0
type v1p0p0Params struct {
TemplateClient *types2.ClientState `protobuf:"bytes,1,opt,name=template_client,json=templateClient,proto3" json:"template_client,omitempty"`
TrustingPeriodFraction string `protobuf:"bytes,2,opt,name=trusting_period_fraction,json=trustingPeriodFraction,proto3" json:"trusting_period_fraction,omitempty"`
CcvTimeoutPeriod time.Duration `protobuf:"bytes,3,opt,name=ccv_timeout_period,json=ccvTimeoutPeriod,proto3,stdduration" json:"ccv_timeout_period"`
InitTimeoutPeriod time.Duration `protobuf:"bytes,4,opt,name=init_timeout_period,json=initTimeoutPeriod,proto3,stdduration" json:"init_timeout_period"`
VscTimeoutPeriod time.Duration `protobuf:"bytes,5,opt,name=vsc_timeout_period,json=vscTimeoutPeriod,proto3,stdduration" json:"vsc_timeout_period"`
SlashMeterReplenishPeriod time.Duration `protobuf:"bytes,6,opt,name=slash_meter_replenish_period,json=slashMeterReplenishPeriod,proto3,stdduration" json:"slash_meter_replenish_period"`
SlashMeterReplenishFraction string `protobuf:"bytes,7,opt,name=slash_meter_replenish_fraction,json=slashMeterReplenishFraction,proto3" json:"slash_meter_replenish_fraction,omitempty"`
MaxThrottledPackets int64 `protobuf:"varint,8,opt,name=max_throttled_packets,json=maxThrottledPackets,proto3" json:"max_throttled_packets,omitempty"`
}
12 changes: 6 additions & 6 deletions x/ccv/provider/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (p Params) Validate() error {
if p.TemplateClient == nil {
return fmt.Errorf("template client is nil")
}
if err := validateTemplateClient(*p.TemplateClient); err != nil {
if err := ValidateTemplateClient(*p.TemplateClient); err != nil {
return err
}
if err := ccvtypes.ValidateStringFraction(p.TrustingPeriodFraction); err != nil {
Expand All @@ -145,7 +145,7 @@ func (p Params) Validate() error {
if err := ccvtypes.ValidatePositiveInt64(p.MaxThrottledPackets); err != nil {
return fmt.Errorf("max throttled packets is invalid: %s", err)
}
if err := validateCoin(p.ConsumerRewardDenomRegistrationFee); err != nil {
if err := ValidateCoin(p.ConsumerRewardDenomRegistrationFee); err != nil {
return fmt.Errorf("consumer reward denom registration fee is invalid: %s", err)
}
return nil
Expand All @@ -154,19 +154,19 @@ func (p Params) Validate() error {
// ParamSetPairs implements params.ParamSet
func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
return paramtypes.ParamSetPairs{
paramtypes.NewParamSetPair(KeyTemplateClient, p.TemplateClient, validateTemplateClient),
paramtypes.NewParamSetPair(KeyTemplateClient, p.TemplateClient, ValidateTemplateClient),
paramtypes.NewParamSetPair(KeyTrustingPeriodFraction, p.TrustingPeriodFraction, ccvtypes.ValidateStringFraction),
paramtypes.NewParamSetPair(ccvtypes.KeyCCVTimeoutPeriod, p.CcvTimeoutPeriod, ccvtypes.ValidateDuration),
paramtypes.NewParamSetPair(KeyInitTimeoutPeriod, p.InitTimeoutPeriod, ccvtypes.ValidateDuration),
paramtypes.NewParamSetPair(KeyVscTimeoutPeriod, p.VscTimeoutPeriod, ccvtypes.ValidateDuration),
paramtypes.NewParamSetPair(KeySlashMeterReplenishPeriod, p.SlashMeterReplenishPeriod, ccvtypes.ValidateDuration),
paramtypes.NewParamSetPair(KeySlashMeterReplenishFraction, p.SlashMeterReplenishFraction, ccvtypes.ValidateStringFraction),
paramtypes.NewParamSetPair(KeyMaxThrottledPackets, p.MaxThrottledPackets, ccvtypes.ValidatePositiveInt64),
paramtypes.NewParamSetPair(KeyConsumerRewardDenomRegistrationFee, p.ConsumerRewardDenomRegistrationFee, validateCoin),
paramtypes.NewParamSetPair(KeyConsumerRewardDenomRegistrationFee, p.ConsumerRewardDenomRegistrationFee, ValidateCoin),
}
}

func validateTemplateClient(i interface{}) error {
func ValidateTemplateClient(i interface{}) error {
cs, ok := i.(ibctmtypes.ClientState)
if !ok {
return fmt.Errorf("invalid parameter type: %T, expected: %T", i, ibctmtypes.ClientState{})
Expand All @@ -193,7 +193,7 @@ func validateTemplateClient(i interface{}) error {
return nil
}

func validateCoin(i interface{}) error {
func ValidateCoin(i interface{}) error {
v, ok := i.(sdk.Coin)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
Expand Down

0 comments on commit dbf9ded

Please sign in to comment.