diff --git a/app/upgrades/v20/upgrades.go b/app/upgrades/v20/upgrades.go index cf8ead61492..9832ee9fa55 100644 --- a/app/upgrades/v20/upgrades.go +++ b/app/upgrades/v20/upgrades.go @@ -2,6 +2,7 @@ package v20 import ( "context" + "fmt" providerkeeper "github.com/cosmos/interchain-security/v5/x/ccv/provider/keeper" providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types" @@ -66,7 +67,8 @@ func CreateUpgradeHandler( } ctx.Logger().Info("Migrating ICS legacy proposals...") - err = MigrateICSLegacyProposals(ctx, *keepers.GovKeeper) + msgServer := providerkeeper.NewMsgServerImpl(&keepers.ProviderKeeper) + err = MigrateICSLegacyProposals(ctx, msgServer, keepers.ProviderKeeper, *keepers.GovKeeper) if err != nil { return vm, errorsmod.Wrapf(err, "migrating ICS legacy proposals during migration") } @@ -134,9 +136,9 @@ func InitializeLastProviderConsensusValidatorSet( } // MigrateICSLegacyProposals migrates ICS legacy proposals -func MigrateICSLegacyProposals(ctx sdk.Context, govKeeper govkeeper.Keeper) error { +func MigrateICSLegacyProposals(ctx sdk.Context, msgServer providertypes.MsgServer, providerKeeper providerkeeper.Keeper, govKeeper govkeeper.Keeper) error { return govKeeper.Proposals.Walk(ctx, nil, func(key uint64, proposal govtypes.Proposal) (stop bool, err error) { - err = MigrateProposal(ctx, govKeeper, proposal) + err = MigrateProposal(ctx, msgServer, providerKeeper, govKeeper, proposal) if err != nil { return true, errorsmod.Wrapf(err, "migrating proposal %d", key) } @@ -144,123 +146,502 @@ func MigrateICSLegacyProposals(ctx sdk.Context, govKeeper govkeeper.Keeper) erro }) } -// MigrateProposal migrates a proposal by converting legacy messages to new messages. -func MigrateProposal(ctx sdk.Context, govKeeper govkeeper.Keeper, proposal govtypes.Proposal) error { - for idx, msg := range proposal.GetMessages() { - sdkLegacyMsg, isLegacyProposal := msg.GetCachedValue().(*govtypes.MsgExecLegacyContent) - if !isLegacyProposal { - continue - } - content, err := govtypes.LegacyContentFromMessage(sdkLegacyMsg) - if err != nil { - continue - } +// MigrateProposal migrates an ICS proposal +func MigrateProposal( + ctx sdk.Context, + msgServer providertypes.MsgServer, + providerKeeper providerkeeper.Keeper, + govKeeper govkeeper.Keeper, + proposal govtypes.Proposal, +) error { + // ignore proposals that were rejected or failed + if proposal.Status != govtypes.StatusDepositPeriod && + proposal.Status != govtypes.StatusVotingPeriod && + proposal.Status != govtypes.StatusPassed { + return nil + } - msgAdd, ok := content.(*providertypes.ConsumerAdditionProposal) - if ok { - anyMsg, err := MigrateLegacyConsumerAddition(*msgAdd, govKeeper.GetAuthority()) - if err != nil { - return err - } - proposal.Messages[idx] = anyMsg - continue // skip the rest of the loop - } + // ignore proposals with more than one message as we are interested only + // in legacy proposals (which have only one message) + messages := proposal.GetMessages() + if len(messages) != 1 { + return nil + } + msg := messages[0] + + // ignore non-legacy proposals + sdkLegacyMsg, isLegacyProposal := msg.GetCachedValue().(*govtypes.MsgExecLegacyContent) + if !isLegacyProposal { + return nil + } + content, err := govtypes.LegacyContentFromMessage(sdkLegacyMsg) + if err != nil { + return err + } - msgRemove, ok := content.(*providertypes.ConsumerRemovalProposal) - if ok { - anyMsg, err := MigrateLegacyConsumerRemoval(*msgRemove, govKeeper.GetAuthority()) + switch msg := content.(type) { + case *providertypes.ConsumerAdditionProposal: + return MigrateConsumerAdditionProposal( + ctx, + msgServer, + providerKeeper, + govKeeper, + proposal, + msg, + ) + + case *providertypes.ConsumerRemovalProposal: + return MigrateConsumerRemovalProposal( + ctx, + msgServer, + providerKeeper, + govKeeper, + proposal, + msg, + ) + + case *providertypes.ConsumerModificationProposal: + return MigrateConsumerModificationProposal( + ctx, + msgServer, + providerKeeper, + govKeeper, + proposal, + msg, + ) + + case *providertypes.ChangeRewardDenomsProposal: + return MigrateChangeRewardDenomsProposal( + ctx, + msgServer, + providerKeeper, + govKeeper, + proposal, + msg, + ) + } + + return nil +} + +// MigrateConsumerAdditionProposal migrates a ConsumerAdditionProposal +func MigrateConsumerAdditionProposal( + ctx sdk.Context, + msgServer providertypes.MsgServer, + providerKeeper providerkeeper.Keeper, + govKeeper govkeeper.Keeper, + proposal govtypes.Proposal, + msg *providertypes.ConsumerAdditionProposal, +) error { + if proposal.Status == govtypes.StatusPassed { + // ConsumerAdditionProposal that passed -- it was added to the + // list of pending consumer addition proposals, which was deleted during + // the migration of the provider module + for _, consumerID := range providerKeeper.GetAllActiveConsumerIds(ctx) { + chainID, err := providerKeeper.GetConsumerChainId(ctx, consumerID) if err != nil { - return err + return err // this means something is wrong with the provider state } - proposal.Messages[idx] = anyMsg - continue // skip the rest of the loop + if chainID == msg.ChainId { + // this proposal was already handled in a previous block + ctx.Logger().Info( + fmt.Sprintf( + "Proposal with ID(%d) was skipped as it was already handled - consumerID(%s), chainID(%s), spawnTime(%s)", + proposal.Id, consumerID, msg.ChainId, msg.SpawnTime.String(), + ), + ) + return nil + } + } + // create a new consumer chain with all the parameters + metadata, err := metadataFromCAP(msg) + if err != nil { + return err + } + initParams, err := initParamsFromCAP(msg) + if err != nil { + return err } + powerShapingParams, err := powerShapingParamsFromCAP(msg) + if err != nil { + return err + } + msgCreateConsumer := providertypes.MsgCreateConsumer{ + Signer: govKeeper.GetAuthority(), + ChainId: msg.ChainId, + Metadata: metadata, + InitializationParameters: &initParams, + PowerShapingParameters: &powerShapingParams, + } + resp, err := msgServer.CreateConsumer(ctx, &msgCreateConsumer) + if err != nil { + return err + } + ctx.Logger().Info( + fmt.Sprintf( + "Created consumer with ID(%s), chainID(%s), and spawnTime(%s) from proposal with ID(%d)", + resp.ConsumerId, msg.ChainId, initParams.SpawnTime.String(), proposal.Id, + ), + ) + } else { + // ConsumerAdditionProposal that was submitted, but not yet passed + + // first, create a new consumer chain to get a consumer ID + metadata, err := metadataFromCAP(msg) + if err != nil { + return err + } + msgCreateConsumer := providertypes.MsgCreateConsumer{ + Signer: govKeeper.GetAuthority(), + ChainId: msg.ChainId, + Metadata: metadata, + InitializationParameters: nil, // to be added to MsgUpdateConsumer + PowerShapingParameters: nil, // to be added to MsgUpdateConsumer + } + resp, err := msgServer.CreateConsumer(ctx, &msgCreateConsumer) + if err != nil { + return err + } + ctx.Logger().Info( + fmt.Sprintf( + "Created consumer with ID(%s), chainID(%s), and no spawnTime from proposal with ID(%d)", + resp.ConsumerId, msg.ChainId, proposal.Id, + ), + ) + + // second, replace the message in the proposal with a MsgUpdateConsumer + initParams, err := initParamsFromCAP(msg) + if err != nil { + return err + } + powerShapingParams, err := powerShapingParamsFromCAP(msg) + if err != nil { + return err + } + msgUpdateConsumer := providertypes.MsgUpdateConsumer{ + Signer: govKeeper.GetAuthority(), + ConsumerId: resp.ConsumerId, + Metadata: nil, + InitializationParameters: &initParams, + PowerShapingParameters: &powerShapingParams, + } + anyMsg, err := codec.NewAnyWithValue(&msgUpdateConsumer) + if err != nil { + return err + } + proposal.Messages[0] = anyMsg + // TODO: check if we can call SetProposal within govKeeper.Proposals.Walk + if err := govKeeper.SetProposal(ctx, proposal); err != nil { + return err + } + ctx.Logger().Info( + fmt.Sprintf( + "Replaced proposal with ID(%d) with MsgUpdateConsumer - consumerID(%s), chainID(%s), spawnTime(%s)", + proposal.Id, resp.ConsumerId, msg.ChainId, initParams.SpawnTime.String(), + ), + ) + } + return nil +} - msgMod, ok := content.(*providertypes.ConsumerModificationProposal) - if ok { - anyMsg, err := MigrateConsumerModificationProposal(*msgMod, govKeeper.GetAuthority()) - if err != nil { +// metadataFromCAP returns ConsumerMetadata from a ConsumerAdditionProposal +func metadataFromCAP( + prop *providertypes.ConsumerAdditionProposal, +) (providertypes.ConsumerMetadata, error) { + metadata := providertypes.ConsumerMetadata{ + Name: prop.Title, + Description: prop.Description, + Metadata: "TBA", + } + err := providertypes.ValidateConsumerMetadata(metadata) + // TODO: avoid returning an error here; + // for this, we need to make sure the validation works always + // (e.g., truncate the fields) + return metadata, err +} + +// initParamsFromCAP returns ConsumerInitializationParameters from +// a ConsumerAdditionProposal +func initParamsFromCAP( + prop *providertypes.ConsumerAdditionProposal, +) (providertypes.ConsumerInitializationParameters, error) { + initParams := providertypes.ConsumerInitializationParameters{ + InitialHeight: prop.InitialHeight, + GenesisHash: prop.GenesisHash, + BinaryHash: prop.BinaryHash, + SpawnTime: prop.SpawnTime, + UnbondingPeriod: prop.UnbondingPeriod, + CcvTimeoutPeriod: prop.CcvTimeoutPeriod, + TransferTimeoutPeriod: prop.TransferTimeoutPeriod, + ConsumerRedistributionFraction: prop.ConsumerRedistributionFraction, + BlocksPerDistributionTransmission: prop.BlocksPerDistributionTransmission, + HistoricalEntries: prop.HistoricalEntries, + DistributionTransmissionChannel: prop.DistributionTransmissionChannel, + } + err := providertypes.ValidateInitializationParameters(initParams) + // TODO: avoid returning an error here; + // for this, we need to make sure the validation works always + return initParams, err +} + +// powerShapingParamsFromCAP returns PowerShapingParameters from a ConsumerAdditionProposal +func powerShapingParamsFromCAP( + prop *providertypes.ConsumerAdditionProposal, +) (providertypes.PowerShapingParameters, error) { + powerShapingParams := providertypes.PowerShapingParameters{ + Top_N: prop.Top_N, + ValidatorsPowerCap: prop.ValidatorsPowerCap, + ValidatorSetCap: prop.ValidatorSetCap, + Allowlist: prop.Allowlist, + Denylist: prop.Denylist, + MinStake: prop.MinStake, + AllowInactiveVals: prop.AllowInactiveVals, + } + err := providertypes.ValidatePowerShapingParameters(powerShapingParams) + // TODO: avoid returning an error here; + // for this, we need to make sure the validation works always + return powerShapingParams, err +} + +// MigrateConsumerRemovalProposal migrates a ConsumerRemovalProposal +func MigrateConsumerRemovalProposal( + ctx sdk.Context, + msgServer providertypes.MsgServer, + providerKeeper providerkeeper.Keeper, + govKeeper govkeeper.Keeper, + proposal govtypes.Proposal, + msg *providertypes.ConsumerRemovalProposal, +) error { + // identify the consumer chain + rmConsumerID := "" + for _, consumerID := range providerKeeper.GetAllActiveConsumerIds(ctx) { + chainID, err := providerKeeper.GetConsumerChainId(ctx, consumerID) + if err != nil { + return err // this means is something wrong with the provider state + } + if chainID == msg.ChainId { + rmConsumerID = consumerID + break + } + } + if rmConsumerID == "" { + // ignore proposal as there is no consumer with that chain ID + ctx.Logger().Info( + fmt.Sprintf( + "Proposal with ID(%d) was skipped as there is no consumer with chainID(%s)", + proposal.Id, msg.ChainId, + ), + ) + if proposal.Status != govtypes.StatusPassed { + // if the proposal didn't pass yet, then just remove it + if err := govKeeper.DeleteProposal(ctx, proposal.Id); err != nil { return err } - proposal.Messages[idx] = anyMsg - continue // skip the rest of the loop + ctx.Logger().Info( + fmt.Sprintf( + "Proposal with ID(%d) was deleted -- chainID(%s)", + proposal.Id, msg.ChainId, + ), + ) } + return nil + } - msgChangeRewardDenoms, ok := content.(*providertypes.ChangeRewardDenomsProposal) - if ok { - anyMsg, err := MigrateChangeRewardDenomsProposal(*msgChangeRewardDenoms, govKeeper.GetAuthority()) - if err != nil { - return err - } - proposal.Messages[idx] = anyMsg - continue // skip the rest of the loop + msgRemoveConsumer := providertypes.MsgRemoveConsumer{ + ConsumerId: rmConsumerID, + StopTime: msg.StopTime, + Signer: govKeeper.GetAuthority(), + } + + if proposal.Status == govtypes.StatusPassed { + // ConsumerRemovalProposal that passed -- it was added to the + // list of pending consumer removal proposals, which was deleted during + // the migration of the provider module + _, err := msgServer.RemoveConsumer(ctx, &msgRemoveConsumer) + if err != nil { + ctx.Logger().Error( + fmt.Sprintf( + "Could not remove consumer with ID(%s), chainID(%s), and stopTime(%s) as per proposal with ID(%d)", + rmConsumerID, msg.ChainId, msg.StopTime.String(), proposal.Id, + ), + ) + return nil // do not stop the migration because of this } + ctx.Logger().Info( + fmt.Sprintf( + "Consumer with ID(%s), chainID(%s) will stop at stopTime(%s) as per proposal with ID(%d)", + rmConsumerID, msg.ChainId, msg.StopTime.String(), proposal.Id, + ), + ) + } else { + // ConsumerRemovalProposal that was submitted, but not yet passed + + // replace the message in the proposal with a MsgRemoveConsumer + anyMsg, err := codec.NewAnyWithValue(&msgRemoveConsumer) + if err != nil { + return err + } + proposal.Messages[0] = anyMsg + // TODO: check if we can call SetProposal within govKeeper.Proposals.Walk + if err := govKeeper.SetProposal(ctx, proposal); err != nil { + return err + } + ctx.Logger().Info( + fmt.Sprintf( + "Replaced proposal with ID(%d) with MsgRemoveConsumer - consumerID(%s), chainID(%s), spawnTime(%s)", + proposal.Id, rmConsumerID, msg.ChainId, msg.StopTime.String(), + ), + ) } - return govKeeper.SetProposal(ctx, proposal) + return nil } -// MigrateLegacyConsumerAddition converts a ConsumerAdditionProposal to a MsgConsumerAdditionProposal -// and returns it as `Any` suitable to replace the legacy message. -// `authority` contains the signer address -func MigrateLegacyConsumerAddition(msg providertypes.ConsumerAdditionProposal, authority string) (*codec.Any, error) { - sdkMsg := providertypes.MsgConsumerAddition{ - ChainId: msg.ChainId, - InitialHeight: msg.InitialHeight, - GenesisHash: msg.GenesisHash, - BinaryHash: msg.BinaryHash, - SpawnTime: msg.SpawnTime, - UnbondingPeriod: msg.UnbondingPeriod, - CcvTimeoutPeriod: msg.CcvTimeoutPeriod, - TransferTimeoutPeriod: msg.TransferTimeoutPeriod, - ConsumerRedistributionFraction: msg.ConsumerRedistributionFraction, - BlocksPerDistributionTransmission: msg.BlocksPerDistributionTransmission, - HistoricalEntries: msg.HistoricalEntries, - DistributionTransmissionChannel: msg.DistributionTransmissionChannel, - Top_N: msg.Top_N, - ValidatorsPowerCap: msg.ValidatorsPowerCap, - ValidatorSetCap: msg.ValidatorSetCap, - Allowlist: msg.Allowlist, - Denylist: msg.Denylist, - Authority: authority, - MinStake: msg.MinStake, - AllowInactiveVals: msg.AllowInactiveVals, +// MigrateConsumerModificationProposal migrates a ConsumerModificationProposal +func MigrateConsumerModificationProposal( + ctx sdk.Context, + msgServer providertypes.MsgServer, + providerKeeper providerkeeper.Keeper, + govKeeper govkeeper.Keeper, + proposal govtypes.Proposal, + msg *providertypes.ConsumerModificationProposal, +) error { + if proposal.Status == govtypes.StatusPassed { + // ConsumerModificationProposal that passed -- it was already handled in + // a previous block since these proposals are handled immediately + ctx.Logger().Info( + fmt.Sprintf( + "Proposal with ID(%d) was skipped as it was already handled - chainID(%s)", + proposal.Id, msg.ChainId, + ), + ) + return nil + } + + // ConsumerModificationProposal that was submitted, but not yet passed + modifyConsumerID := "" + for _, consumerID := range providerKeeper.GetAllActiveConsumerIds(ctx) { + chainID, err := providerKeeper.GetConsumerChainId(ctx, consumerID) + if err != nil { + return err // this means is something wrong with the provider state + } + if chainID == msg.ChainId { + modifyConsumerID = consumerID + break + } + } + if modifyConsumerID == "" { + // delete proposal as there is no consumer with that chain ID + if err := govKeeper.DeleteProposal(ctx, proposal.Id); err != nil { + return err + } + ctx.Logger().Info( + fmt.Sprintf( + "Proposal with ID(%d) was deleted - chainID(%s)", + proposal.Id, msg.ChainId, + ), + ) + return nil } - return codec.NewAnyWithValue(&sdkMsg) -} -// MigrateLegacyConsumerRemoval converts a ConsumerRemovalProposal to a MsgConsumerRemovalProposal -// and returns it as `Any` suitable to replace the legacy message. -// `authority` contains the signer address -func MigrateLegacyConsumerRemoval(msg providertypes.ConsumerRemovalProposal, authority string) (*codec.Any, error) { - sdkMsg := providertypes.MsgConsumerRemoval{ - ChainId: msg.ChainId, - StopTime: msg.StopTime, - Authority: authority, + // replace the message in the proposal with a MsgUpdateConsumer + powerShapingParams, err := powerShapingParamsFromCMP(msg) + if err != nil { + return err + } + msgUpdateConsumer := providertypes.MsgUpdateConsumer{ + Signer: govKeeper.GetAuthority(), + ConsumerId: modifyConsumerID, + Metadata: nil, + InitializationParameters: nil, + PowerShapingParameters: &powerShapingParams, + } + anyMsg, err := codec.NewAnyWithValue(&msgUpdateConsumer) + if err != nil { + return err } - return codec.NewAnyWithValue(&sdkMsg) + proposal.Messages[0] = anyMsg + // TODO: check if we can call SetProposal within govKeeper.Proposals.Walk + if err := govKeeper.SetProposal(ctx, proposal); err != nil { + return err + } + ctx.Logger().Info( + fmt.Sprintf( + "Replaced proposal with ID(%d) with MsgUpdateConsumer - consumerID(%s), chainID(%s)", + proposal.Id, modifyConsumerID, msg.ChainId, + ), + ) + return nil } -// MigrateConsumerModificationProposal converts a ConsumerModificationProposal to a MsgConsumerModificationProposal -// and returns it as `Any` suitable to replace the legacy message. -// `authority` contains the signer address -func MigrateConsumerModificationProposal(msg providertypes.ConsumerModificationProposal, authority string) (*codec.Any, error) { - sdkMsg := providertypes.MsgConsumerModification{ - ChainId: msg.ChainId, - Allowlist: msg.Allowlist, - Denylist: msg.Denylist, - Authority: authority, +// powerShapingParamsFromCMP returns PowerShapingParameters from a ConsumerModificationProposal +func powerShapingParamsFromCMP( + prop *providertypes.ConsumerModificationProposal, +) (providertypes.PowerShapingParameters, error) { + powerShapingParams := providertypes.PowerShapingParameters{ + Top_N: prop.Top_N, + ValidatorsPowerCap: prop.ValidatorsPowerCap, + ValidatorSetCap: prop.ValidatorSetCap, + Allowlist: prop.Allowlist, + Denylist: prop.Denylist, + MinStake: prop.MinStake, + AllowInactiveVals: prop.AllowInactiveVals, } - return codec.NewAnyWithValue(&sdkMsg) + err := providertypes.ValidatePowerShapingParameters(powerShapingParams) + // TODO: avoid returning an error here; + // for this, we need to make sure the validation works always + return powerShapingParams, err } -// MigrateChangeRewardDenomsProposal converts a ChangeRewardDenomsProposal to a MigrateChangeRewardDenomsProposal -// and returns it as `Any` suitable to replace the legacy message. -// `authority` contains the signer address -func MigrateChangeRewardDenomsProposal(msg providertypes.ChangeRewardDenomsProposal, authority string) (*codec.Any, error) { - sdkMsg := providertypes.MsgChangeRewardDenoms{ - DenomsToAdd: msg.GetDenomsToAdd(), - DenomsToRemove: msg.GetDenomsToRemove(), - Authority: authority, +// MigrateChangeRewardDenomsProposal migrates a ChangeRewardDenomsProposal +func MigrateChangeRewardDenomsProposal( + ctx sdk.Context, + msgServer providertypes.MsgServer, + providerKeeper providerkeeper.Keeper, + govKeeper govkeeper.Keeper, + proposal govtypes.Proposal, + msg *providertypes.ChangeRewardDenomsProposal, +) error { + if proposal.Status == govtypes.StatusPassed { + // ChangeRewardDenomsProposal that passed -- it was already handled in + // a previous block since these proposals are handled immediately + ctx.Logger().Info( + fmt.Sprintf("Proposal with ID(%d) was skipped as it was already handled", proposal.Id), + ) + } else { + // ChangeRewardDenomsProposal that was submitted, but not yet passed + + // replace the message in the proposal with a MsgChangeRewardDenoms + msgChangeRewardDenoms := providertypes.MsgChangeRewardDenoms{ + Authority: govKeeper.GetAuthority(), + DenomsToAdd: msg.DenomsToAdd, + DenomsToRemove: msg.DenomsToRemove, + } + if err := msgChangeRewardDenoms.ValidateBasic(); err != nil { + // this should not happen if the original ChangeRewardDenomsProposal + // was well formed + if err := govKeeper.DeleteProposal(ctx, proposal.Id); err != nil { + return err + } + ctx.Logger().Error( + fmt.Sprintf( + "Proposal with ID(%d) was deleted as it failed validation: %s", + proposal.Id, err.Error(), + ), + ) + return nil + } + anyMsg, err := codec.NewAnyWithValue(&msgChangeRewardDenoms) + if err != nil { + return err + } + proposal.Messages[0] = anyMsg + // TODO: check if we can call SetProposal within govKeeper.Proposals.Walk + if err := govKeeper.SetProposal(ctx, proposal); err != nil { + return err + } + ctx.Logger().Info( + fmt.Sprintf("Replaced proposal with ID(%d) with MsgChangeRewardDenoms", proposal.Id), + ) } - return codec.NewAnyWithValue(&sdkMsg) + return nil } diff --git a/go.mod b/go.mod index 0cc9c837939..ae828f4d576 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/cosmos/ibc-apps/modules/rate-limiting/v8 v8.0.0 github.com/cosmos/ibc-go/modules/capability v1.0.0 github.com/cosmos/ibc-go/v8 v8.4.0 - github.com/cosmos/interchain-security/v5 v5.0.0-20240828132703-cc68344cd0f1 + github.com/cosmos/interchain-security/v5 v5.0.0-20240829091139-29b1bf4d6940 github.com/google/gofuzz v1.2.0 github.com/gorilla/mux v1.8.1 github.com/ory/dockertest/v3 v3.11.0 diff --git a/go.sum b/go.sum index 36f67292047..712c07d85b2 100644 --- a/go.sum +++ b/go.sum @@ -441,12 +441,12 @@ github.com/cosmos/ibc-go/v8 v8.4.0 h1:K2PfX0AZ+1XKZytHGEMuSjQXG/MZshPb83RSTQt2+c github.com/cosmos/ibc-go/v8 v8.4.0/go.mod h1:zh6x1osR0hNvEcFrC/lhGD08sMfQmr9wHVvZ/mRWMCs= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= -github.com/cosmos/interchain-security/v5 v5.0.0-20240806104629-29327696b8e6 h1:aFwnbEdeMUaQg9ZU+Pm8fE3CzZM2gG5jSeAvYOd+hoU= -github.com/cosmos/interchain-security/v5 v5.0.0-20240806104629-29327696b8e6/go.mod h1:sT6a/OIwwkXuH9fBzt5IBa4lrlWO8etgQ+b59pIE8k4= -github.com/cosmos/interchain-security/v5 v5.0.0-20240823135732-3a0c55f65769 h1:R1ncQp/CwgV/u2fWebEWdp/o3IiINb3RuWEg4ATrEGQ= -github.com/cosmos/interchain-security/v5 v5.0.0-20240823135732-3a0c55f65769/go.mod h1:y3LdR1GPxF8SMFRb/V38OWGZNwEriJDFlka/hoH1GEk= -github.com/cosmos/interchain-security/v5 v5.0.0-20240828132703-cc68344cd0f1 h1:HLCT8P+6VobYZZDkQ1LUa1V4eHWZa5kcUBozMUhXbDI= -github.com/cosmos/interchain-security/v5 v5.0.0-20240828132703-cc68344cd0f1/go.mod h1:y3LdR1GPxF8SMFRb/V38OWGZNwEriJDFlka/hoH1GEk= +github.com/cosmos/interchain-security/v5 v5.0.0-20240829084649-7aa6db910325 h1:ueWHkJmLAKaHmhuWknABjvbT7Fsb0O6IVoQocUPqJ84= +github.com/cosmos/interchain-security/v5 v5.0.0-20240829084649-7aa6db910325/go.mod h1:y3LdR1GPxF8SMFRb/V38OWGZNwEriJDFlka/hoH1GEk= +github.com/cosmos/interchain-security/v5 v5.0.0-20240829085830-43ecf100aa0e h1:ag161bPs24kepjQ3M2OgCGEx1OSVh5q0uSqikwdXWRs= +github.com/cosmos/interchain-security/v5 v5.0.0-20240829085830-43ecf100aa0e/go.mod h1:y3LdR1GPxF8SMFRb/V38OWGZNwEriJDFlka/hoH1GEk= +github.com/cosmos/interchain-security/v5 v5.0.0-20240829091139-29b1bf4d6940 h1:EtZZjzahQTW14hk2MLkpoTefGDcb3sgpgRQ7sxy0mIQ= +github.com/cosmos/interchain-security/v5 v5.0.0-20240829091139-29b1bf4d6940/go.mod h1:y3LdR1GPxF8SMFRb/V38OWGZNwEriJDFlka/hoH1GEk= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= diff --git a/tests/integration/interchain_security_test.go b/tests/integration/interchain_security_test.go index 26cdf1c4a16..79406657495 100644 --- a/tests/integration/interchain_security_test.go +++ b/tests/integration/interchain_security_test.go @@ -65,13 +65,13 @@ func TestICSEpochs(t *testing.T) { } getVSCPacketsFn := func() []types.ValidatorSetChangePacketData { - return providerKeeper.GetPendingVSCPackets(provCtx, ccvSuite.GetCCVPath().EndpointA.Chain.ChainID) + consumerID := icstestingutils.FirstConsumerID + return providerKeeper.GetPendingVSCPackets(provCtx, consumerID) } nextEpoch := func(ctx sdk.Context) sdk.Context { - blockPerEpochs := providerKeeper.GetBlocksPerEpoch(ctx) for { - if ctx.BlockHeight()%blockPerEpochs == 0 { + if providerKeeper.BlocksUntilNextEpoch(ctx) == 0 { return ctx } ccvSuite.GetProviderChain().NextBlock()