Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 3 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Improvements
* (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
46 changes: 44 additions & 2 deletions modules/core/ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import (

clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types"
"github.com/cosmos/ibc-go/v8/modules/core/exported"
"github.com/cosmos/ibc-go/v8/modules/core/keeper"
solomachine "github.com/cosmos/ibc-go/v8/modules/light-clients/06-solomachine"
tendermint "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint"
)

type RedundantRelayDecorator struct {
Expand Down Expand Up @@ -84,8 +87,7 @@ func (rrd RedundantRelayDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
packetMsgs++

case *clienttypes.MsgUpdateClient:
_, err := rrd.k.UpdateClient(ctx, msg)
if err != nil {
if err := rrd.updateClientCheckTx(ctx, msg); err != nil {
return ctx, err
}

Expand All @@ -105,6 +107,46 @@ 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.4.x
damiannolan marked this conversation as resolved.
Show resolved Hide resolved
// 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 @@ -3,17 +3,20 @@ package ante_test
import (
"fmt"
"testing"
"time"

"github.com/stretchr/testify/require"
testifysuite "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/v8/modules/core/02-client/types"
channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types"
host "github.com/cosmos/ibc-go/v8/modules/core/24-host"
"github.com/cosmos/ibc-go/v8/modules/core/ante"
"github.com/cosmos/ibc-go/v8/modules/core/exported"
ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v8/testing"
)

Expand Down Expand Up @@ -357,6 +360,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 @@ -402,6 +463,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
Loading