diff --git a/x/ibc/light-clients/07-tendermint/types/upgrade.go b/x/ibc/light-clients/07-tendermint/types/upgrade.go index 3f2f31e7b174..42f6ea31f00f 100644 --- a/x/ibc/light-clients/07-tendermint/types/upgrade.go +++ b/x/ibc/light-clients/07-tendermint/types/upgrade.go @@ -61,6 +61,10 @@ func (cs ClientState) VerifyUpgrade( return sdkerrors.Wrap(err, "could not retrieve latest consensus state") } + if cs.IsExpired(consState.Timestamp, ctx.BlockTime()) { + return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "cannot upgrade an expired client") + } + tmCommittedClient, ok := committedClient.(*ClientState) if !ok { return sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "upgraded client must be Tendermint client. expected: %T got: %T", diff --git a/x/ibc/light-clients/07-tendermint/types/upgrade_test.go b/x/ibc/light-clients/07-tendermint/types/upgrade_test.go index e69d7b111f6e..7ba1ea6ac7ae 100644 --- a/x/ibc/light-clients/07-tendermint/types/upgrade_test.go +++ b/x/ibc/light-clients/07-tendermint/types/upgrade_test.go @@ -191,6 +191,30 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { }, expPass: false, }, + { + name: "unsuccessful upgrade: client is expired", + setup: func() { + + upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, upgradeHeight, commitmenttypes.GetSDKSpecs(), &upgradePath, false, false) + // zero custom fields and store in upgrade store + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), upgradedClient) + + // commit upgrade store changes and update clients + + suite.coordinator.CommitBlock(suite.chainB) + err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, ibctesting.Tendermint) + suite.Require().NoError(err) + + // expire chainB's client + suite.chainA.ExpireClient(ubdPeriod) + + cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) + suite.Require().True(found) + + proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(), cs.GetLatestHeight().GetEpochHeight()) + }, + expPass: false, + }, } for _, tc := range testCases {