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

feat!: add memo to IBC transfers of ICS rewards (backport #2290) #2312

Merged
merged 10 commits into from
Sep 27, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- `[x/consumer]` Populate the memo on the IBC transfer packets used to send ICS rewards.
with the required consumer chain Id to identify the consumer to the provider.
- `[x/provider]` Identify the source of ICS rewards from the IBC transfer packet memo.
([\#2290](https://github.com/cosmos/interchain-security/pull/2290))
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- `[x/consumer]` Populate the memo on the IBC transfer packets used to send ICS rewards.
with the required consumer chain Id to identify the consumer to the provider.
- `[x/provider]` Identify the source of ICS rewards from the IBC transfer packet memo.
([\#2290](https://github.com/cosmos/interchain-security/pull/2290))
22 changes: 22 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@

This guide provides instructions for upgrading to specific versions of Replicated Security.

## [v4.5.x](https://github.com/cosmos/interchain-security/releases/tag/v4.5.0)

### Consumer

Upgrading a consumer from v4.4.x to v4.5.x requires state migrations. The following migrators should be added to the upgrade handler of the consumer chain:


```go
// InitializeConsumerId sets the consumer Id parameter in the consumer module,
// to the consumer id for which the consumer is registered on the provider chain.
// The consumer id can be obtained in by querying the provider, e.g. by using the
// QueryConsumerIdFromClientId query.
func InitializeConsumerId(ctx sdk.Context, consumerKeeper consumerkeeper.Keeper) error {
params, err := consumerKeeper.GetConsumerParams(ctx)
if err != nil {
return err
}
params.ConsumerId = ConsumerId
return consumerKeeper.SetParams(ctx, params)
}
```

## [v4.4.x](https://github.com/cosmos/interchain-security/releases/tag/v4.4.0)

### Provider
Expand Down
4 changes: 4 additions & 0 deletions proto/interchain_security/ccv/v1/shared_consumer.proto
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ message ConsumerParams {
// The period after which a consumer can retry sending a throttled packet.
google.protobuf.Duration retry_delay_period = 13
[ (gogoproto.nullable) = false, (gogoproto.stdduration) = true ];

// The consumer ID of this consumer chain. Used by the consumer module to send
// ICS rewards.
string consumer_id = 14;
}

// ConsumerGenesisState defines shared genesis information between provider and
Expand Down
1 change: 1 addition & 0 deletions tests/mbt/driver/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ func createConsumerGenesis(modelParams ModelParams, providerChain *ibctesting.Te
[]string{},
[]string{},
ccvtypes.DefaultRetryDelayPeriod,
"",
)

return consumertypes.NewInitialGenesisState(consumerClientState, providerConsState, valUpdates, params)
Expand Down
6 changes: 5 additions & 1 deletion x/ccv/consumer/keeper/distribution.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ func (k Keeper) SendRewardsToProvider(ctx sdk.Context) error {

sentCoins := sdk.NewCoins()
var allBalances sdk.Coins
rewardMemo, err := ccv.CreateTransferMemo(k.GetConsumerId(ctx), ctx.ChainID())
if err != nil {
return err
}
// iterate over all whitelisted reward denoms
for _, denom := range k.AllowedRewardDenoms(ctx) {
// get the balance of the denom in the toSendToProviderTokens address
Expand All @@ -133,7 +137,7 @@ func (k Keeper) SendRewardsToProvider(ctx sdk.Context) error {
Receiver: providerAddr, // provider fee pool address to send to
TimeoutHeight: timeoutHeight, // timeout height disabled
TimeoutTimestamp: timeoutTimestamp,
Memo: "consumer chain rewards distribution",
Memo: rewardMemo,
}

// validate MsgTransfer before calling Transfer()
Expand Down
7 changes: 7 additions & 0 deletions x/ccv/consumer/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func (k Keeper) GetConsumerParams(ctx sdk.Context) ccvtypes.ConsumerParams {
k.GetRewardDenoms(ctx),
k.GetProviderRewardDenoms(ctx),
k.GetRetryDelayPeriod(ctx),
k.GetConsumerId(ctx),
)
}

Expand Down Expand Up @@ -136,3 +137,9 @@ func (k Keeper) GetRetryDelayPeriod(ctx sdk.Context) time.Duration {
k.paramStore.Get(ctx, ccvtypes.KeyRetryDelayPeriod, &period)
return period
}

func (k Keeper) GetConsumerId(ctx sdk.Context) string {
var cId string
k.paramStore.Get(ctx, ccvtypes.KeyConsumerId, &cId)
return cId
}
3 changes: 2 additions & 1 deletion x/ccv/consumer/keeper/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ func TestParams(t *testing.T) {
rewardDenoms,
provideRewardDenoms,
ccv.DefaultRetryDelayPeriod,
"0",
) // these are the default params, IBC suite independently sets enabled=true

params := consumerKeeper.GetConsumerParams(ctx)
require.Equal(t, expParams, params)

newParams := ccv.NewParams(false, 1000,
"channel-2", "cosmos19pe9pg5dv9k5fzgzmsrgnw9rl9asf7ddwhu7lm",
7*24*time.Hour, 25*time.Hour, "0.5", 500, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour)
7*24*time.Hour, 25*time.Hour, "0.5", 500, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour, "1")
consumerKeeper.SetParams(ctx, newParams)
params = consumerKeeper.GetConsumerParams(ctx)
require.Equal(t, newParams, params)
Expand Down
3 changes: 3 additions & 0 deletions x/ccv/consumer/types/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ func TestValidateInitialGenesisState(t *testing.T) {
[]string{},
[]string{},
ccv.DefaultRetryDelayPeriod,
"1",
)),
true,
},
Expand All @@ -252,6 +253,7 @@ func TestValidateInitialGenesisState(t *testing.T) {
[]string{},
[]string{},
ccv.DefaultRetryDelayPeriod,
"1",
)),
true,
},
Expand Down Expand Up @@ -457,6 +459,7 @@ func TestValidateRestartConsumerGenesisState(t *testing.T) {
[]string{},
[]string{},
ccv.DefaultRetryDelayPeriod,
"1",
)),
true,
},
Expand Down
38 changes: 24 additions & 14 deletions x/ccv/consumer/types/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (

// Tests the validation of consumer params that happens at genesis
func TestValidateParams(t *testing.T) {
consumerId := "13"

testCases := []struct {
name string
params ccvtypes.ConsumerParams
Expand All @@ -19,59 +21,67 @@ func TestValidateParams(t *testing.T) {
{"default params", ccvtypes.DefaultParams(), true},
{
"custom valid params",
ccvtypes.NewParams(true, 5, "", "", 1004, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour), true,
ccvtypes.NewParams(true, 5, "", "", 1004, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour, consumerId), true,
},
{
"custom invalid params, block per dist transmission",
ccvtypes.NewParams(true, -5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour), false,
ccvtypes.NewParams(true, -5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour, consumerId), false,
},
{
"custom invalid params, dist transmission channel",
ccvtypes.NewParams(true, 5, "badchannel/", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour), false,
ccvtypes.NewParams(true, 5, "badchannel/", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour, consumerId), false,
},
{
"custom invalid params, ccv timeout",
ccvtypes.NewParams(true, 5, "", "", -5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour), false,
ccvtypes.NewParams(true, 5, "", "", -5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour, consumerId), false,
},
{
"custom invalid params, transfer timeout",
ccvtypes.NewParams(true, 5, "", "", 1004, -7, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour), false,
ccvtypes.NewParams(true, 5, "", "", 1004, -7, "0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour, consumerId), false,
},
{
"custom invalid params, consumer redist fraction is negative",
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "-0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour), false,
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "-0.5", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour, consumerId), false,
},
{
"custom invalid params, consumer redist fraction is over 1",
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "1.2", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour), false,
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "1.2", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour, consumerId), false,
},
{
"custom invalid params, bad consumer redist fraction ",
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "notFrac", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour), false,
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "notFrac", 1000, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour, consumerId), false,
},
{
"custom invalid params, negative num historical entries",
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", -100, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour), false,
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", -100, 24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour, consumerId), false,
},
{
"custom invalid params, negative unbonding period",
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, -24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour), false,
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, -24*21*time.Hour, []string{"untrn"}, []string{"uatom"}, 2*time.Hour, consumerId), false,
},
{
"custom invalid params, invalid reward denom",
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"u"}, []string{}, 2*time.Hour), false,
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{"u"}, []string{}, 2*time.Hour, consumerId), false,
},
{
"custom invalid params, invalid provider reward denom",
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{}, []string{"a"}, 2*time.Hour), false,
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{}, []string{"a"}, 2*time.Hour, consumerId), false,
},
{
"custom invalid params, retry delay period is negative",
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{}, []string{}, -2*time.Hour), false,
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{}, []string{}, -2*time.Hour, consumerId), false,
},
{
"custom invalid params, retry delay period is zero",
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{}, []string{}, 0), false,
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{}, []string{}, 0, consumerId), false,
},
{
"custom invalid params, consumer ID is blank",
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{}, []string{}, time.Hour, ""), false,
},
{
"custom invalid params, consumer ID is not a uint64",
ccvtypes.NewParams(true, 5, "", "", 5, 1005, "0.5", 1000, 24*21*time.Hour, []string{}, []string{}, time.Hour, "consumerId"), false,
},
}

Expand Down
1 change: 1 addition & 0 deletions x/ccv/provider/keeper/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ func (k Keeper) MakeConsumerGenesis(
[]string{},
[]string{},
ccv.DefaultRetryDelayPeriod,
"0",
)

gen = *ccv.NewInitialConsumerGenesisState(
Expand Down
3 changes: 2 additions & 1 deletion x/ccv/provider/keeper/proposal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,8 @@ func TestMakeConsumerGenesis(t *testing.T) {
"soft_opt_out_threshold": "0",
"reward_denoms": [],
"provider_reward_denoms": [],
"retry_delay_period": 3600000000000
"retry_delay_period": 3600000000000,
"consumer_id": "0"
},
"new_chain": true,
"provider" : {
Expand Down
3 changes: 3 additions & 0 deletions x/ccv/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ var (
ErrDuplicateConsumerChain = errorsmod.Register(ModuleName, 14, "consumer chain already exists")
ErrConsumerChainNotFound = errorsmod.Register(ModuleName, 15, "consumer chain not found")
ErrInvalidDoubleVotingEvidence = errorsmod.Register(ModuleName, 16, "invalid consumer double voting evidence")
ErrStoreKeyNotFound = errorsmod.Register(ModuleName, 17, "store key not found")
ErrStoreUnmarshal = errorsmod.Register(ModuleName, 18, "cannot unmarshal value from store")
ErrInvalidConsumerId = errorsmod.Register(ModuleName, 19, "invalid consumer id")
)
9 changes: 9 additions & 0 deletions x/ccv/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ var (
KeyRewardDenoms = []byte("RewardDenoms")
KeyProviderRewardDenoms = []byte("ProviderRewardDenoms")
KeyRetryDelayPeriod = []byte("RetryDelayPeriod")
KeyConsumerId = []byte("ConsumerId")
)

// ParamKeyTable type declaration for parameters
Expand All @@ -68,6 +69,7 @@ func NewParams(enabled bool, blocksPerDistributionTransmission int64,
consumerRedistributionFraction string, historicalEntries int64,
consumerUnbondingPeriod time.Duration,
rewardDenoms, providerRewardDenoms []string, retryDelayPeriod time.Duration,
consumerId string,
) ConsumerParams {
return ConsumerParams{
Enabled: enabled,
Expand All @@ -84,6 +86,7 @@ func NewParams(enabled bool, blocksPerDistributionTransmission int64,
RewardDenoms: rewardDenoms,
ProviderRewardDenoms: providerRewardDenoms,
RetryDelayPeriod: retryDelayPeriod,
ConsumerId: consumerId,
}
}

Expand All @@ -104,6 +107,7 @@ func DefaultParams() ConsumerParams {
rewardDenoms,
provideRewardDenoms,
DefaultRetryDelayPeriod,
"0",
)
}

Expand Down Expand Up @@ -145,6 +149,9 @@ func (p ConsumerParams) Validate() error {
if err := ValidateDuration(p.RetryDelayPeriod); err != nil {
return err
}
if err := ValidateConsumerId(p.ConsumerId); err != nil {
return err
}
return nil
}

Expand Down Expand Up @@ -174,6 +181,8 @@ func (p *ConsumerParams) ParamSetPairs() paramtypes.ParamSetPairs {
p.ProviderRewardDenoms, ValidateDenoms),
paramtypes.NewParamSetPair(KeyRetryDelayPeriod,
p.RetryDelayPeriod, ValidateDuration),
paramtypes.NewParamSetPair(KeyConsumerId,
p.ConsumerId, ValidateConsumerId),
}
}

Expand Down
Loading
Loading