diff --git a/.changelog/unreleased/features/3079-init-ics-epochs.md b/.changelog/unreleased/features/3079-init-ics-epochs.md new file mode 100644 index 00000000000..c1f112ffe9e --- /dev/null +++ b/.changelog/unreleased/features/3079-init-ics-epochs.md @@ -0,0 +1,2 @@ +- Initialize ICS epochs by adding a consumer validator set for every existing consumer chain. + ([\#3079](https://github.com/cosmos/gaia/pull/3079)) \ No newline at end of file diff --git a/.changelog/unreleased/state-breaking/3079-init-ics-epochs.md b/.changelog/unreleased/state-breaking/3079-init-ics-epochs.md new file mode 100644 index 00000000000..c1f112ffe9e --- /dev/null +++ b/.changelog/unreleased/state-breaking/3079-init-ics-epochs.md @@ -0,0 +1,2 @@ +- Initialize ICS epochs by adding a consumer validator set for every existing consumer chain. + ([\#3079](https://github.com/cosmos/gaia/pull/3079)) \ No newline at end of file diff --git a/app/upgrades/v16/upgrades.go b/app/upgrades/v16/upgrades.go index d45131f398a..dddc318f3fc 100644 --- a/app/upgrades/v16/upgrades.go +++ b/app/upgrades/v16/upgrades.go @@ -7,6 +7,7 @@ import ( ratelimittypes "github.com/Stride-Labs/ibc-rate-limiting/ratelimit/types" icacontrollertypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/types" + providerkeeper "github.com/cosmos/interchain-security/v4/x/ccv/provider/keeper" providertypes "github.com/cosmos/interchain-security/v4/x/ccv/provider/types" errorsmod "cosmossdk.io/errors" @@ -14,6 +15,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/cosmos/gaia/v16/app/keepers" @@ -87,6 +89,11 @@ func CreateUpgradeHandler( } else if addErr != nil { return vm, errorsmod.Wrapf(addErr, "unable to add rate limits") } + + if err := InitICSEpochs(ctx, keepers.ProviderKeeper, *keepers.StakingKeeper); err != nil { + return vm, errorsmod.Wrapf(err, "failed initializing ICS epochs") + } + ctx.Logger().Info("Upgrade complete") return vm, err } @@ -155,3 +162,25 @@ func AddRateLimits(ctx sdk.Context, k ratelimitkeeper.Keeper) error { ctx.Logger().Info("Finished adding rate limits") return nil } + +func InitICSEpochs(ctx sdk.Context, pk providerkeeper.Keeper, sk stakingkeeper.Keeper) error { + ctx.Logger().Info("Initializing ICS epochs...") + + // get the bonded validators from the staking module + bondedValidators := sk.GetLastValidators(ctx) + + for _, chain := range pk.GetAllConsumerChains(ctx) { + chainID := chain.ChainId + valset := pk.GetConsumerValSet(ctx, chainID) + if len(valset) > 0 { + ctx.Logger().Info("consumer chain `%s` already has the valset initialized", chainID) + } else { + // init valset for consumer with chainID + nextValidators := pk.ComputeNextEpochConsumerValSet(ctx, chainID, bondedValidators) + pk.SetConsumerValSet(ctx, chainID, nextValidators) + } + } + + ctx.Logger().Info("Finished initializing ICS epochs") + return nil +} diff --git a/app/upgrades/v16/upgrades_test.go b/app/upgrades/v16/upgrades_test.go index ec75e121bac..039117990b1 100644 --- a/app/upgrades/v16/upgrades_test.go +++ b/app/upgrades/v16/upgrades_test.go @@ -73,3 +73,37 @@ func TestAddRateLimits(t *testing.T) { require.Equal(t, expectedRateLimit, rateLimit) } } + +func TestInitICSEpochs(t *testing.T) { + gaiaApp := helpers.Setup(t) + ctx := gaiaApp.NewUncachedContext(true, tmproto.Header{}) + + providerKeeper := gaiaApp.ProviderKeeper + stakingKeeper := gaiaApp.StakingKeeper + + // the setup has only one validator that is bonded + expBondedVals := stakingKeeper.GetAllValidators(ctx) + require.Equal(t, 1, len(expBondedVals)) + expVal := expBondedVals[0] + expPower := expVal.ConsensusPower(stakingKeeper.PowerReduction(ctx)) + expConsAddr, err := expVal.GetConsAddr() + require.NoError(t, err) + expConsumerPublicKey, err := expVal.TmConsPublicKey() + require.NoError(t, err) + + providerKeeper.SetConsumerClientId(ctx, "chainID-0", "clientID-0") + providerKeeper.SetConsumerClientId(ctx, "chainID-1", "clientID-1") + + err = v16.InitICSEpochs(ctx, providerKeeper, *stakingKeeper) + require.NoError(t, err) + + for _, chain := range providerKeeper.GetAllConsumerChains(ctx) { + chainID := chain.ChainId + valset := providerKeeper.GetConsumerValSet(ctx, chainID) + require.Equal(t, 1, len(valset)) + val := valset[0] + require.Equal(t, expPower, val.Power) + require.Equal(t, expConsAddr.Bytes(), val.ProviderConsAddr) + require.Equal(t, expConsumerPublicKey, *val.ConsumerPublicKey) + } +}