diff --git a/libs/cosmos-sdk/x/params/subspace/subspace.go b/libs/cosmos-sdk/x/params/subspace/subspace.go index 426dbe8b89..3572391dd2 100644 --- a/libs/cosmos-sdk/x/params/subspace/subspace.go +++ b/libs/cosmos-sdk/x/params/subspace/subspace.go @@ -1,6 +1,7 @@ package subspace import ( + "bytes" "fmt" "reflect" "strconv" @@ -408,6 +409,26 @@ func (s Subspace) GetParamSet(ctx sdk.Context, ps ParamSet) { } } +// GetParamSetForInitGenesis iterates through each ParamSetPair where for each pair, it will +// retrieve the value and set it to the corresponding value pointer provided, ignore the target keys for additional +// in the ParamSetPair by calling Subspace#Get. +func (s Subspace) GetParamSetForInitGenesis(ctx sdk.Context, ps ParamSet, ignoreList [][]byte) { + for _, pair := range ps.ParamSetPairs() { + beIgnore := false + for _, ignore := range ignoreList { + if bytes.Equal(ignore, pair.Key) { + beIgnore = true + break + } + } + + if beIgnore { + continue + } + s.Get(ctx, pair.Key, pair.Value) + } +} + // SetParamSet iterates through each ParamSetPair and sets the value with the // corresponding parameter key in the Subspace's KVStore. func (s Subspace) SetParamSet(ctx sdk.Context, ps ParamSet) { @@ -426,6 +447,36 @@ func (s Subspace) SetParamSet(ctx sdk.Context, ps ParamSet) { } } +// SetParamSetForInitGenesis iterates through each ParamSetPair and sets the value with the +// corresponding parameter key in the Subspace's KVStore, ignore the target keys for additional +func (s Subspace) SetParamSetForInitGenesis(ctx sdk.Context, ps ParamSet, ignoreList [][]byte) { + for _, pair := range ps.ParamSetPairs() { + beIgnore := false + for _, ignore := range ignoreList { + if bytes.Equal(ignore, pair.Key) { + beIgnore = true + break + } + } + + if beIgnore { + continue + } + + // pair.Field is a pointer to the field, so indirecting the ptr. + // go-amino automatically handles it but just for sure, + // since SetStruct is meant to be used in InitGenesis + // so this method will not be called frequently + v := reflect.Indirect(reflect.ValueOf(pair.Value)).Interface() + + if err := pair.ValidatorFn(v); err != nil { + panic(fmt.Sprintf("value from ParamSetPair is invalid: %s", err)) + } + + s.Set(ctx, pair.Key, v) + } +} + // Name returns the name of the Subspace. func (s Subspace) Name() string { return string(s.name) diff --git a/libs/cosmos-sdk/x/params/subspace/subspace_test.go b/libs/cosmos-sdk/x/params/subspace/subspace_test.go index 2ac256ade2..013a616551 100644 --- a/libs/cosmos-sdk/x/params/subspace/subspace_test.go +++ b/libs/cosmos-sdk/x/params/subspace/subspace_test.go @@ -1,6 +1,7 @@ package subspace_test import ( + "bytes" "fmt" "testing" "time" @@ -195,6 +196,44 @@ func (suite *SubspaceTestSuite) TestSetParamSet() { suite.Require().Equal(a.BondDenom, b.BondDenom) } +func (suite *SubspaceTestSuite) TestSetParamSetForInitGenesis() { + testCases := []struct { + name string + ps subspace.ParamSet + ignoreList [][]byte + }{ + {"ignore all", ¶ms{time.Hour * 48, 100, "stake"}, [][]byte{keyUnbondingTime, keyMaxValidators, keyBondDenom}}, + {"ignore two", ¶ms{time.Hour * 48, 100, "stake"}, [][]byte{keyUnbondingTime, keyMaxValidators}}, + {"ignore one", ¶ms{time.Hour * 48, 100, "stake"}, [][]byte{keyUnbondingTime}}, + {"ignore nil", ¶ms{time.Hour * 48, 100, "stake"}, [][]byte{}}, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.ss.SetParamSetForInitGenesis(suite.ctx, tc.ps, tc.ignoreList) + for _, pair := range tc.ps.ParamSetPairs() { + beIgnore := false + for _, ignore := range tc.ignoreList { + if bytes.Equal(ignore, pair.Key) { + beIgnore = true + break + } + } + + if beIgnore { + suite.Require().False(suite.ss.Has(suite.ctx, pair.Key)) + } else { + suite.Require().True(suite.ss.Has(suite.ctx, pair.Key)) + } + suite.Require().NotPanics(func() { + suite.ss.GetParamSetForInitGenesis(suite.ctx, tc.ps, tc.ignoreList) + }) + } + }) + } +} + func (suite *SubspaceTestSuite) TestName() { suite.Require().Equal("testsubspace", suite.ss.Name()) } diff --git a/x/distribution/genesis.go b/x/distribution/genesis.go index fe7b0b2d56..17a70f68ac 100644 --- a/x/distribution/genesis.go +++ b/x/distribution/genesis.go @@ -12,7 +12,7 @@ import ( func InitGenesis(ctx sdk.Context, keeper Keeper, supplyKeeper types.SupplyKeeper, data types.GenesisState) { keeper.SetFeePool(ctx, data.FeePool) - keeper.SetParams(ctx, data.Params) + keeper.SetParamsForInitGenesis(ctx, data.Params) keeper.SetPreviousProposerConsAddr(ctx, data.PreviousProposer) for _, dwi := range data.DelegatorWithdrawInfos { @@ -42,7 +42,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, supplyKeeper types.SupplyKeeper // ExportGenesis returns a GenesisState for a given context and keeper. func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState { feePool := keeper.GetFeePool(ctx) - params := keeper.GetParams(ctx) + params := keeper.GetParamsForInitGenesis(ctx) dwi := make([]types.DelegatorWithdrawInfo, 0) keeper.IterateDelegatorWithdrawAddrs(ctx, func(del sdk.AccAddress, addr sdk.AccAddress) (stop bool) { diff --git a/x/distribution/keeper/params.go b/x/distribution/keeper/params.go index a8e41825f6..c36d21400a 100644 --- a/x/distribution/keeper/params.go +++ b/x/distribution/keeper/params.go @@ -12,11 +12,22 @@ func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { return params } +// GetParamsForInitGenesis returns the total set of distribution parameters. +func (k Keeper) GetParamsForInitGenesis(ctx sdk.Context) (params types.Params) { + k.paramSpace.GetParamSetForInitGenesis(ctx, ¶ms, types.IgnoreInitGenesisList) + return params +} + // SetParams sets the distribution parameters to the param space. func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { k.paramSpace.SetParamSet(ctx, ¶ms) } +// SetParamsForInitGenesis sets the distribution parameters to the param space, and ignore the target keys for additional +func (k Keeper) SetParamsForInitGenesis(ctx sdk.Context, params types.Params) { + k.paramSpace.SetParamSetForInitGenesis(ctx, ¶ms, types.IgnoreInitGenesisList) +} + // GetCommunityTax returns the current CommunityTax rate from the global param store // nolint: errcheck func (k Keeper) GetCommunityTax(ctx sdk.Context) (percent sdk.Dec) { diff --git a/x/distribution/types/params.go b/x/distribution/types/params.go index 101cfd309a..ef8cc11994 100644 --- a/x/distribution/types/params.go +++ b/x/distribution/types/params.go @@ -19,6 +19,8 @@ var ( ParamStoreKeyDistributionType = []byte("distributiontype") ParamStoreKeyWithdrawRewardEnabled = []byte("withdrawrewardenabled") ParamStoreKeyRewardTruncatePrecision = []byte("rewardtruncateprecision") + + IgnoreInitGenesisList = [][]byte{ParamStoreKeyDistributionType, ParamStoreKeyWithdrawRewardEnabled, ParamStoreKeyRewardTruncatePrecision} ) // Params defines the set of distribution parameters. @@ -58,7 +60,7 @@ func (p *Params) ParamSetPairs() params.ParamSetPairs { return params.ParamSetPairs{ params.NewParamSetPair(ParamStoreKeyCommunityTax, &p.CommunityTax, validateCommunityTax), params.NewParamSetPair(ParamStoreKeyWithdrawAddrEnabled, &p.WithdrawAddrEnabled, validateWithdrawAddrEnabled), - //TODO, Check the first block of the older version is not compatible + //new params for distribution proposal params.NewParamSetPair(ParamStoreKeyDistributionType, &p.DistributionType, validateDistributionType), params.NewParamSetPair(ParamStoreKeyWithdrawRewardEnabled, &p.WithdrawRewardEnabled, validateWithdrawRewardEnabled), params.NewParamSetPair(ParamStoreKeyRewardTruncatePrecision, &p.RewardTruncatePrecision, validateRewardTruncatePrecision),