Skip to content

Commit ee842be

Browse files
refactor(v7.4.x): performance improvements for update client in ante (#6306)
* 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 * refactor: ignore misbehaviour types for UpdateState in ante handler * chore: make lint-fix * test: add misbehaviour testcases to ante handler * lint * chore: add changelog entry --------- Co-authored-by: Colin Axnér <[email protected]>
1 parent f60998d commit ee842be

File tree

3 files changed

+142
-2
lines changed

3 files changed

+142
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
4747
* (apps/27-interchain-accounts) [\#6144](https://github.com/cosmos/ibc-go/pull/6144) Emit an event signalling that the host submodule is disabled.
4848
* (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.
4949
* (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.
50+
* (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.
5051

5152
### Features
5253

modules/core/ante/ante.go

+47-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
package ante
22

33
import (
4+
errorsmod "cosmossdk.io/errors"
5+
46
sdk "github.com/cosmos/cosmos-sdk/types"
57
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
68

79
clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
810
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
11+
"github.com/cosmos/ibc-go/v7/modules/core/exported"
912
"github.com/cosmos/ibc-go/v7/modules/core/keeper"
13+
solomachine "github.com/cosmos/ibc-go/v7/modules/light-clients/06-solomachine"
14+
tendermint "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
1015
)
1116

1217
type RedundantRelayDecorator struct {
@@ -83,8 +88,7 @@ func (rrd RedundantRelayDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
8388
packetMsgs++
8489

8590
case *clienttypes.MsgUpdateClient:
86-
_, err := rrd.k.UpdateClient(sdk.WrapSDKContext(ctx), msg)
87-
if err != nil {
91+
if err := rrd.updateClientCheckTx(ctx, msg); err != nil {
8892
return ctx, err
8993
}
9094

@@ -149,3 +153,44 @@ func (rrd RedundantRelayDecorator) recvPacketReCheckTx(ctx sdk.Context, msg *cha
149153

150154
return &channeltypes.MsgRecvPacketResponse{Result: channeltypes.SUCCESS}, nil
151155
}
156+
157+
// updateClientCheckTx runs a subset of ibc client update logic to be used specifically within the RedundantRelayDecorator AnteHandler.
158+
// The following function performs ibc client message verification for CheckTx only and state updates in both CheckTx and ReCheckTx.
159+
// Note that misbehaviour checks are omitted.
160+
func (rrd RedundantRelayDecorator) updateClientCheckTx(ctx sdk.Context, msg *clienttypes.MsgUpdateClient) error {
161+
clientMsg, err := clienttypes.UnpackClientMessage(msg.ClientMessage)
162+
if err != nil {
163+
return err
164+
}
165+
166+
clientState, found := rrd.k.ClientKeeper.GetClientState(ctx, msg.ClientId)
167+
if !found {
168+
return errorsmod.Wrapf(clienttypes.ErrClientNotFound, msg.ClientId)
169+
}
170+
171+
if status := rrd.k.ClientKeeper.GetClientStatus(ctx, clientState, msg.ClientId); status != exported.Active {
172+
return errorsmod.Wrapf(clienttypes.ErrClientNotActive, "cannot update client (%s) with status %s", msg.ClientId, status)
173+
}
174+
175+
clientStore := rrd.k.ClientKeeper.ClientStore(ctx, msg.ClientId)
176+
177+
if !ctx.IsReCheckTx() {
178+
if err := clientState.VerifyClientMessage(ctx, rrd.k.Codec(), clientStore, clientMsg); err != nil {
179+
return err
180+
}
181+
}
182+
183+
// NOTE: the following avoids panics in ante handler client updates for ibc-go v7.4.x
184+
// without state machine breaking changes within light client modules.
185+
switch clientMsg.(type) {
186+
case *solomachine.Misbehaviour:
187+
// ignore solomachine misbehaviour for update state in ante
188+
case *tendermint.Misbehaviour:
189+
// ignore tendermint misbehaviour for update state in ante
190+
default:
191+
heights := clientState.UpdateState(ctx, rrd.k.Codec(), clientStore, clientMsg)
192+
ctx.Logger().With("module", "x/"+exported.ModuleName).Debug("ante ibc client update", "consensusHeights", heights)
193+
}
194+
195+
return nil
196+
}

modules/core/ante/ante_test.go

+94
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@ package ante_test
22

33
import (
44
"testing"
5+
"time"
56

67
"github.com/stretchr/testify/require"
78
"github.com/stretchr/testify/suite"
89

10+
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
911
sdk "github.com/cosmos/cosmos-sdk/types"
1012

1113
clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
1214
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
1315
host "github.com/cosmos/ibc-go/v7/modules/core/24-host"
1416
"github.com/cosmos/ibc-go/v7/modules/core/ante"
1517
"github.com/cosmos/ibc-go/v7/modules/core/exported"
18+
ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
1619
ibctesting "github.com/cosmos/ibc-go/v7/testing"
1720
)
1821

@@ -342,6 +345,64 @@ func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() {
342345
},
343346
true,
344347
},
348+
{
349+
"success on new UpdateClient messages: solomachine misbehaviour",
350+
func(suite *AnteTestSuite) []sdk.Msg {
351+
solomachine := ibctesting.NewSolomachine(suite.T(), suite.chainB.Codec, "06-solomachine-0", "testing", 1)
352+
suite.chainB.GetSimApp().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainB.GetContext(), solomachine.ClientID, solomachine.ClientState())
353+
354+
msgUpdateClient, err := clienttypes.NewMsgUpdateClient(solomachine.ClientID, solomachine.CreateMisbehaviour(), suite.chainB.SenderAccount.GetAddress().String())
355+
suite.Require().NoError(err)
356+
357+
msgs := []sdk.Msg{msgUpdateClient}
358+
359+
return msgs
360+
},
361+
true,
362+
},
363+
{
364+
"success on new UpdateClient messages: solomachine multisig misbehaviour",
365+
func(suite *AnteTestSuite) []sdk.Msg {
366+
solomachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "06-solomachine-0", "testing", 4)
367+
suite.chainB.GetSimApp().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainB.GetContext(), solomachine.ClientID, solomachine.ClientState())
368+
369+
msgUpdateClient, err := clienttypes.NewMsgUpdateClient(solomachine.ClientID, solomachine.CreateMisbehaviour(), suite.chainB.SenderAccount.GetAddress().String())
370+
suite.Require().NoError(err)
371+
372+
msgs := []sdk.Msg{msgUpdateClient}
373+
374+
return msgs
375+
},
376+
true,
377+
},
378+
{
379+
"success on new UpdateClient messages: tendermint misbehaviour",
380+
func(suite *AnteTestSuite) []sdk.Msg {
381+
trustedHeight := suite.path.EndpointB.GetClientState().GetLatestHeight().(clienttypes.Height)
382+
383+
trustedVals, found := suite.chainA.GetValsAtHeight(int64(trustedHeight.RevisionHeight) + 1)
384+
suite.Require().True(found)
385+
386+
err := suite.path.EndpointB.UpdateClient()
387+
suite.Require().NoError(err)
388+
389+
height := suite.path.EndpointB.GetClientState().GetLatestHeight().(clienttypes.Height)
390+
391+
// construct valid fork misbehaviour: two headers at the same height with different time
392+
misbehaviour := &ibctm.Misbehaviour{
393+
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),
394+
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),
395+
}
396+
397+
msgUpdateClient, err := clienttypes.NewMsgUpdateClient(suite.path.EndpointB.ClientID, misbehaviour, suite.chainB.SenderAccount.GetAddress().String())
398+
suite.Require().NoError(err)
399+
400+
msgs := []sdk.Msg{msgUpdateClient}
401+
402+
return msgs
403+
},
404+
true,
405+
},
345406
{
346407
"no success on one redundant RecvPacket message",
347408
func(suite *AnteTestSuite) []sdk.Msg {
@@ -387,6 +448,39 @@ func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() {
387448
},
388449
false,
389450
},
451+
{
452+
"no success on one new UpdateClient message: invalid client identifier",
453+
func(suite *AnteTestSuite) []sdk.Msg {
454+
clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{})
455+
suite.Require().NoError(err)
456+
457+
msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: ibctesting.InvalidID, ClientMessage: clientMsg}}
458+
return msgs
459+
},
460+
false,
461+
},
462+
{
463+
"no success on one new UpdateClient message: client module not found",
464+
func(suite *AnteTestSuite) []sdk.Msg {
465+
clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{})
466+
suite.Require().NoError(err)
467+
468+
msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: clienttypes.FormatClientIdentifier("08-wasm", 1), ClientMessage: clientMsg}}
469+
return msgs
470+
},
471+
false,
472+
},
473+
{
474+
"no success on one new UpdateClient message: no consensus state for trusted height",
475+
func(suite *AnteTestSuite) []sdk.Msg {
476+
clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{TrustedHeight: clienttypes.NewHeight(1, 10000)})
477+
suite.Require().NoError(err)
478+
479+
msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: suite.path.EndpointA.ClientID, ClientMessage: clientMsg}}
480+
return msgs
481+
},
482+
false,
483+
},
390484
{
391485
"no success on three new UpdateClient messages and three redundant messages of each type",
392486
func(suite *AnteTestSuite) []sdk.Msg {

0 commit comments

Comments
 (0)