diff --git a/modules/core/ante/ante.go b/modules/core/ante/ante.go index 7b8cdb326de..2295df4a328 100644 --- a/modules/core/ante/ante.go +++ b/modules/core/ante/ante.go @@ -1,10 +1,13 @@ package ante import ( + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/v7/modules/core/exported" "github.com/cosmos/ibc-go/v7/modules/core/keeper" ) @@ -70,8 +73,7 @@ func (rrd RedundantRelayDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula packetMsgs++ case *clienttypes.MsgUpdateClient: - _, err := rrd.k.UpdateClient(sdk.WrapSDKContext(ctx), msg) - if err != nil { + if err := rrd.updateClientCheckTx(ctx, msg); err != nil { return ctx, err } @@ -90,3 +92,36 @@ func (rrd RedundantRelayDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula } return next(ctx, tx, simulate) } + +// updateClientCheckTx runs a subset of ibc client update logic to be used specifically within the RedundantRelayDecorator AnteHandler. +// The following function performs ibc client message verification for CheckTx only and state updates in both CheckTx and ReCheckTx. +// Note that misbehaviour checks are omitted. +func (rrd RedundantRelayDecorator) updateClientCheckTx(ctx sdk.Context, msg *clienttypes.MsgUpdateClient) error { + clientMsg, err := clienttypes.UnpackClientMessage(msg.ClientMessage) + if err != nil { + return err + } + + clientState, found := rrd.k.ClientKeeper.GetClientState(ctx, msg.ClientId) + if !found { + return errorsmod.Wrapf(clienttypes.ErrClientNotFound, msg.ClientId) + } + + if status := rrd.k.ClientKeeper.GetClientStatus(ctx, clientState, msg.ClientId); status != exported.Active { + return errorsmod.Wrapf(clienttypes.ErrClientNotActive, "cannot update client (%s) with status %s", msg.ClientId, status) + } + + clientStore := rrd.k.ClientKeeper.ClientStore(ctx, msg.ClientId) + + if !ctx.IsReCheckTx() { + if err := clientState.VerifyClientMessage(ctx, rrd.k.Codec(), clientStore, clientMsg); err != nil { + return err + } + } + + heights := clientState.UpdateState(ctx, rrd.k.Codec(), clientStore, clientMsg) + + ctx.Logger().With("module", "x/"+exported.ModuleName).Debug("ante ibc client update", "consensusHeights", heights) + + return nil +} diff --git a/modules/core/ante/ante_test.go b/modules/core/ante/ante_test.go index aca0fefd9a7..ace412d11c5 100644 --- a/modules/core/ante/ante_test.go +++ b/modules/core/ante/ante_test.go @@ -3,8 +3,10 @@ package ante_test import ( "testing" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/suite" clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" @@ -12,6 +14,7 @@ import ( host "github.com/cosmos/ibc-go/v7/modules/core/24-host" "github.com/cosmos/ibc-go/v7/modules/core/ante" "github.com/cosmos/ibc-go/v7/modules/core/exported" + ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" ibctesting "github.com/cosmos/ibc-go/v7/testing" ) @@ -386,6 +389,39 @@ func (suite *AnteTestSuite) TestAnteDecorator() { }, false, }, + { + "no success on one new UpdateClient message: invalid client identifier", + func(suite *AnteTestSuite) []sdk.Msg { + clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{}) + suite.Require().NoError(err) + + msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: ibctesting.InvalidID, ClientMessage: clientMsg}} + return msgs + }, + false, + }, + { + "no success on one new UpdateClient message: client module not found", + func(suite *AnteTestSuite) []sdk.Msg { + clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{}) + suite.Require().NoError(err) + + msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: clienttypes.FormatClientIdentifier("08-wasm", 1), ClientMessage: clientMsg}} + return msgs + }, + false, + }, + { + "no success on one new UpdateClient message: no consensus state for trusted height", + func(suite *AnteTestSuite) []sdk.Msg { + clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{TrustedHeight: clienttypes.NewHeight(1, 10000)}) + suite.Require().NoError(err) + + msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: suite.path.EndpointA.ClientID, ClientMessage: clientMsg}} + return msgs + }, + false, + }, { "no success on three new UpdateClient messages and three redundant messages of each type", func(suite *AnteTestSuite) []sdk.Msg {