Skip to content

Commit

Permalink
imp: add updateClientCheckTx to redunant relayer ante decorator (back…
Browse files Browse the repository at this point in the history
…port #6279) (#6304)

* imp: add updateClientCheckTx to redunant relayer ante decorator (#6279)

* imp: add checkTxUpdateClient to redunant relayer ante decorator

* chore: update godoc and duplicate imports

* test: add coverage for checkTxUpdateClient func

* chore: rename ante func to updateClientCheckTx

(cherry picked from commit 3da4830)

# Conflicts:
#	modules/core/ante/ante.go
#	modules/core/ante/ante_test.go

* resolve conflicts and add changelog

* rm wasm dir

* chore: mv changelog

* Update modules/core/ante/ante.go

Co-authored-by: colin axnér <[email protected]>

---------

Co-authored-by: Damian Nolan <[email protected]>
Co-authored-by: colin axnér <[email protected]>
  • Loading branch information
3 people authored May 21, 2024
1 parent 6fbc8c9 commit b5b57ac
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

* (core/ante) [\#6302](https://github.com/cosmos/ibc-go/pull/6302) Performance: Skip app callbacks during RecvPacket execution in checkTx within the redundant relay ante handler.
* (core/ante) [\#6280](https://github.com/cosmos/ibc-go/pull/6280) Performance: Skip redundant proof checking in RecvPacket execution in reCheckTx within the redundant relay ante handler.
* (core/ante) [\#6306](https://github.com/cosmos/ibc-go/pull/6306) Performance: Skip misbehaviour checks in UpdateClient flow and skip signature checks in reCheckTx mode.

### Features

Expand Down
49 changes: 47 additions & 2 deletions modules/core/ante/ante.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package ante

import (
errorsmod "cosmossdk.io/errors"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

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"
solomachine "github.com/cosmos/ibc-go/v7/modules/light-clients/06-solomachine"
tendermint "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
)

type RedundantRelayDecorator struct {
Expand Down Expand Up @@ -83,8 +88,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
}

Expand All @@ -104,6 +108,47 @@ 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
}
}

// NOTE: the following avoids panics in ante handler client updates for ibc-go v7.5.x
// without state machine breaking changes within light client modules.
switch clientMsg.(type) {
case *solomachine.Misbehaviour:
// ignore solomachine misbehaviour for update state in ante
case *tendermint.Misbehaviour:
// ignore tendermint misbehaviour for update state in ante
default:
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
}

// recvPacketCheckTx runs a subset of ibc recv packet logic to be used specifically within the RedundantRelayDecorator AnteHandler.
// It only performs core IBC receiving logic and skips any application logic.
func (rrd RedundantRelayDecorator) recvPacketCheckTx(ctx sdk.Context, msg *channeltypes.MsgRecvPacket) (*channeltypes.MsgRecvPacketResponse, error) {
Expand Down
94 changes: 94 additions & 0 deletions modules/core/ante/ante_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ package ante_test

import (
"testing"
"time"

"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
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"
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"
)

Expand Down Expand Up @@ -342,6 +345,64 @@ func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() {
},
true,
},
{
"success on new UpdateClient messages: solomachine misbehaviour",
func(suite *AnteTestSuite) []sdk.Msg {
solomachine := ibctesting.NewSolomachine(suite.T(), suite.chainB.Codec, "06-solomachine-0", "testing", 1)
suite.chainB.GetSimApp().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainB.GetContext(), solomachine.ClientID, solomachine.ClientState())

msgUpdateClient, err := clienttypes.NewMsgUpdateClient(solomachine.ClientID, solomachine.CreateMisbehaviour(), suite.chainB.SenderAccount.GetAddress().String())
suite.Require().NoError(err)

msgs := []sdk.Msg{msgUpdateClient}

return msgs
},
true,
},
{
"success on new UpdateClient messages: solomachine multisig misbehaviour",
func(suite *AnteTestSuite) []sdk.Msg {
solomachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "06-solomachine-0", "testing", 4)
suite.chainB.GetSimApp().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainB.GetContext(), solomachine.ClientID, solomachine.ClientState())

msgUpdateClient, err := clienttypes.NewMsgUpdateClient(solomachine.ClientID, solomachine.CreateMisbehaviour(), suite.chainB.SenderAccount.GetAddress().String())
suite.Require().NoError(err)

msgs := []sdk.Msg{msgUpdateClient}

return msgs
},
true,
},
{
"success on new UpdateClient messages: tendermint misbehaviour",
func(suite *AnteTestSuite) []sdk.Msg {
trustedHeight := suite.path.EndpointB.GetClientState().GetLatestHeight().(clienttypes.Height)

trustedVals, found := suite.chainA.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
suite.Require().True(found)

err := suite.path.EndpointB.UpdateClient()
suite.Require().NoError(err)

height := suite.path.EndpointB.GetClientState().GetLatestHeight().(clienttypes.Height)

// construct valid fork misbehaviour: two headers at the same height with different time
misbehaviour := &ibctm.Misbehaviour{
Header1: suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainA.CurrentHeader.Time.Add(time.Minute), suite.chainA.Vals, suite.chainA.NextVals, trustedVals, suite.chainA.Signers),
Header2: suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, int64(height.RevisionHeight), trustedHeight, suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.NextVals, trustedVals, suite.chainA.Signers),
}

msgUpdateClient, err := clienttypes.NewMsgUpdateClient(suite.path.EndpointB.ClientID, misbehaviour, suite.chainB.SenderAccount.GetAddress().String())
suite.Require().NoError(err)

msgs := []sdk.Msg{msgUpdateClient}

return msgs
},
true,
},
{
"no success on one redundant RecvPacket message",
func(suite *AnteTestSuite) []sdk.Msg {
Expand Down Expand Up @@ -387,6 +448,39 @@ func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() {
},
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 {
Expand Down

0 comments on commit b5b57ac

Please sign in to comment.