From 6af3ad3c52605b9b654876bfb33740b88b08dcaf Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 18 Mar 2024 16:47:50 +0100 Subject: [PATCH 1/9] refactor: rename SelfClientValidator to ConsensusHost --- ...{client_validator.go => consensus_host.go} | 20 +++++----- modules/core/02-client/keeper/keeper.go | 40 +++++++++---------- modules/core/02-client/keeper/keeper_test.go | 14 +++---- modules/core/02-client/types/client.go | 4 +- .../03-connection/keeper/handshake_test.go | 4 +- ...{client_validator.go => consensus_host.go} | 19 +++++---- testing/mock/client_validator.go | 8 ++-- 7 files changed, 56 insertions(+), 53 deletions(-) rename modules/core/02-client/keeper/{client_validator.go => consensus_host.go} (83%) rename modules/light-clients/08-wasm/types/{client_validator.go => consensus_host.go} (63%) diff --git a/modules/core/02-client/keeper/client_validator.go b/modules/core/02-client/keeper/consensus_host.go similarity index 83% rename from modules/core/02-client/keeper/client_validator.go rename to modules/core/02-client/keeper/consensus_host.go index 7010c5958e4..019a89c15b6 100644 --- a/modules/core/02-client/keeper/client_validator.go +++ b/modules/core/02-client/keeper/consensus_host.go @@ -17,22 +17,22 @@ import ( ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" ) -var _ types.SelfClientValidator = (*TendermintClientValidator)(nil) +var _ types.ConsensusHost = (*TendermintConsensusHost)(nil) -// TendermintClientValidator implements the SelfClientValidator interface. -type TendermintClientValidator struct { +// TendermintConsensusHost implements the 02-client types.ConsensusHost interface +type TendermintConsensusHost struct { stakingKeeper types.StakingKeeper } -// NewTendermintClientValidator creates and returns a new SelfClientValidator for tendermint consensus. -func NewTendermintClientValidator(stakingKeeper types.StakingKeeper) *TendermintClientValidator { - return &TendermintClientValidator{ +// NewTendermintConsensusHost creates and returns a new ConsensusHost for tendermint consensus. +func NewTendermintConsensusHost(stakingKeeper types.StakingKeeper) types.ConsensusHost { + return &TendermintConsensusHost{ stakingKeeper: stakingKeeper, } } -// GetSelfConsensusState implements types.SelfClientValidatorI. -func (tcv *TendermintClientValidator) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { +// GetSelfConsensusState implements the 02-client types.ConsensusHost interface. +func (tcv *TendermintConsensusHost) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { selfHeight, ok := height.(types.Height) if !ok { return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", types.Height{}, height) @@ -58,8 +58,8 @@ func (tcv *TendermintClientValidator) GetSelfConsensusState(ctx sdk.Context, hei return consensusState, nil } -// ValidateSelfClient implements types.SelfClientValidatorI. -func (tcv *TendermintClientValidator) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { +// ValidateSelfClient implements the 02-client types.ConsensusHost interface. +func (tcv *TendermintConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { tmClient, ok := clientState.(*ibctm.ClientState) if !ok { return errorsmod.Wrapf(types.ErrInvalidClient, "client must be a Tendermint client, expected: %T, got: %T", &ibctm.ClientState{}, tmClient) diff --git a/modules/core/02-client/keeper/keeper.go b/modules/core/02-client/keeper/keeper.go index c58c6799a29..d66386f2667 100644 --- a/modules/core/02-client/keeper/keeper.go +++ b/modules/core/02-client/keeper/keeper.go @@ -24,13 +24,13 @@ import ( // Keeper represents a type that grants read and write permissions to any client // state information type Keeper struct { - storeKey storetypes.StoreKey - cdc codec.BinaryCodec - router *types.Router - selfClientValidator types.SelfClientValidator - legacySubspace types.ParamSubspace - stakingKeeper types.StakingKeeper - upgradeKeeper types.UpgradeKeeper + storeKey storetypes.StoreKey + cdc codec.BinaryCodec + router *types.Router + consensusHost types.ConsensusHost + legacySubspace types.ParamSubspace + stakingKeeper types.StakingKeeper + upgradeKeeper types.UpgradeKeeper } // NewKeeper creates a new NewKeeper instance @@ -40,13 +40,13 @@ func NewKeeper(cdc codec.BinaryCodec, key storetypes.StoreKey, legacySubspace ty router.AddRoute(exported.Localhost, localhostModule) return Keeper{ - storeKey: key, - cdc: cdc, - router: router, - selfClientValidator: NewTendermintClientValidator(sk), - legacySubspace: legacySubspace, - stakingKeeper: sk, - upgradeKeeper: uk, + storeKey: key, + cdc: cdc, + router: router, + consensusHost: NewTendermintConsensusHost(sk), + legacySubspace: legacySubspace, + stakingKeeper: sk, + upgradeKeeper: uk, } } @@ -80,13 +80,13 @@ func (k Keeper) UpdateLocalhostClient(ctx sdk.Context, clientState exported.Clie return clientModule.UpdateState(ctx, exported.LocalhostClientID, nil) } -// SetSelfClientValidator sets a custom self client validation function. -func (k *Keeper) SetSelfClientValidator(selfClientValidator types.SelfClientValidator) { - if selfClientValidator == nil { +// SetSelfConsensusHost sets a custom ConsensusHost for self client state and consensus state validation. +func (k *Keeper) SetSelfConsensusHost(consensusHost types.ConsensusHost) { + if consensusHost == nil { panic(fmt.Errorf("cannot set a nil self client validator")) } - k.selfClientValidator = selfClientValidator + k.consensusHost = consensusHost } // GenerateClientIdentifier returns the next client identifier. @@ -309,7 +309,7 @@ func (k Keeper) GetLatestClientConsensusState(ctx sdk.Context, clientID string) // and returns the expected consensus state at that height. // For now, can only retrieve self consensus states for the current revision func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { - return k.selfClientValidator.GetSelfConsensusState(ctx, height) + return k.consensusHost.GetSelfConsensusState(ctx, height) } // ValidateSelfClient validates the client parameters for a client of the running chain. @@ -317,7 +317,7 @@ func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height exported.Height) ( // NOTE: If the client type is not of type Tendermint then delegate to a custom client validator function. // This allows support for non-Tendermint clients, for example 08-wasm clients. func (k Keeper) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { - return k.selfClientValidator.ValidateSelfClient(ctx, clientState) + return k.consensusHost.ValidateSelfClient(ctx, clientState) } // GetUpgradePlan executes the upgrade keeper GetUpgradePlan function. diff --git a/modules/core/02-client/keeper/keeper_test.go b/modules/core/02-client/keeper/keeper_test.go index 37cd9550af4..b99c2f86ef6 100644 --- a/modules/core/02-client/keeper/keeper_test.go +++ b/modules/core/02-client/keeper/keeper_test.go @@ -176,7 +176,7 @@ func (suite *KeeperTestSuite) TestValidateSelfClient() { func() { clientState = solomachine.NewClientState(1, &solomachine.ConsensusState{}) - smSelfClientValidator := &mock.ClientValidator{ + smConsensusHost := &mock.ConsensusHost{ ValidateSelfClientFn: func(ctx sdk.Context, clientState exported.ClientState) error { smClientState, ok := clientState.(*solomachine.ClientState) suite.Require().True(ok) @@ -186,8 +186,8 @@ func (suite *KeeperTestSuite) TestValidateSelfClient() { }, } - // add some mock validation logic - suite.chainA.App.GetIBCKeeper().ClientKeeper.SetSelfClientValidator(smSelfClientValidator) + // add mock validation logic + suite.chainA.App.GetIBCKeeper().ClientKeeper.SetSelfConsensusHost(smConsensusHost) }, nil, }, @@ -378,24 +378,24 @@ func (suite *KeeperTestSuite) TestGetConsensusState() { { name: "custom client validator: failure", malleate: func() { - clientValidator := &mock.ClientValidator{ + consensusHost := &mock.ConsensusHost{ GetSelfConsensusStateFn: func(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { return nil, mock.MockApplicationCallbackError }, } - suite.keeper.SetSelfClientValidator(clientValidator) + suite.keeper.SetSelfConsensusHost(consensusHost) }, expError: mock.MockApplicationCallbackError, }, { name: "custom client validator: success", malleate: func() { - clientValidator := &mock.ClientValidator{ + consensusHost := &mock.ConsensusHost{ GetSelfConsensusStateFn: func(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { return &solomachine.ConsensusState{}, nil }, } - suite.keeper.SetSelfClientValidator(clientValidator) + suite.keeper.SetSelfConsensusHost(consensusHost) }, expError: nil, }, diff --git a/modules/core/02-client/types/client.go b/modules/core/02-client/types/client.go index 2b2447aced8..2b1cb965b85 100644 --- a/modules/core/02-client/types/client.go +++ b/modules/core/02-client/types/client.go @@ -22,8 +22,8 @@ var ( _ codectypes.UnpackInterfacesMessage = (*ConsensusStateWithHeight)(nil) ) -// SelfClientValidator defines an interface used to validate an IBC ClientState against a host chain's underlying consensus parameters. -type SelfClientValidator interface { +// ConsensusHost defines an interface used to validate an IBC ClientState and ConsensusState against the host chain's underlying consensus parameters. +type ConsensusHost interface { GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error } diff --git a/modules/core/03-connection/keeper/handshake_test.go b/modules/core/03-connection/keeper/handshake_test.go index 44cb568906b..6c5945b2b6f 100644 --- a/modules/core/03-connection/keeper/handshake_test.go +++ b/modules/core/03-connection/keeper/handshake_test.go @@ -226,13 +226,13 @@ func (suite *KeeperTestSuite) TestConnOpenTry() { // retrieve client state of chainA to pass as counterpartyClient counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID) - mockValidator := mock.ClientValidator{ + mockValidator := mock.ConsensusHost{ ValidateSelfClientFn: func(ctx sdk.Context, clientState exported.ClientState) error { return mock.MockApplicationCallbackError }, } - suite.chainB.App.GetIBCKeeper().ClientKeeper.SetSelfClientValidator(&mockValidator) + suite.chainB.App.GetIBCKeeper().ClientKeeper.SetSelfConsensusHost(&mockValidator) }, false}, } diff --git a/modules/light-clients/08-wasm/types/client_validator.go b/modules/light-clients/08-wasm/types/consensus_host.go similarity index 63% rename from modules/light-clients/08-wasm/types/client_validator.go rename to modules/light-clients/08-wasm/types/consensus_host.go index 0a1659c1232..a5c4c843792 100644 --- a/modules/light-clients/08-wasm/types/client_validator.go +++ b/modules/light-clients/08-wasm/types/consensus_host.go @@ -11,22 +11,24 @@ import ( "github.com/cosmos/ibc-go/v8/modules/core/exported" ) -type WasmTMClientValidator struct { +// WasmTMConsensusHost implements the 02-client types.ConsensusHost interface. +type WasmTMConsensusHost struct { cdc codec.BinaryCodec - tm *clientkeeper.TendermintClientValidator + tm *clientkeeper.TendermintConsensusHost } -var _ clienttypes.SelfClientValidator = (*WasmTMClientValidator)(nil) +var _ clienttypes.ConsensusHost = (*WasmTMConsensusHost)(nil) -// NewWasmTMClientValidator creates and returns a new SelfClientValidator for wasm tendermint consensus. -func NewWasmTMClientValidator(cdc codec.BinaryCodec, tm *clientkeeper.TendermintClientValidator) *WasmTMClientValidator { - return &WasmTMClientValidator{ +// NewWasmTMConsensusHost creates and returns a new ConsensusHost for wasm tendermint consensus client state and consensus state self validation. +func NewWasmTMConsensusHost(cdc codec.BinaryCodec, tm *clientkeeper.TendermintConsensusHost) *WasmTMConsensusHost { + return &WasmTMConsensusHost{ cdc: cdc, tm: tm, } } -func (w *WasmTMClientValidator) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { +// GetSelfConsensusState implements the 02-client types.ConsensusHost interface. +func (w *WasmTMConsensusHost) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { consensusState, err := w.tm.GetSelfConsensusState(ctx, height) if err != nil { return nil, err @@ -45,7 +47,8 @@ func (w *WasmTMClientValidator) GetSelfConsensusState(ctx sdk.Context, height ex return wasmConsensusState, nil } -func (w *WasmTMClientValidator) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { +// ValidateSelfClient implements the 02-client types.ConsensusHost interface. +func (w *WasmTMConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { wasmClientState, ok := clientState.(*ClientState) if !ok { return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "client must be a wasm client, expected: %T, got: %T", ClientState{}, wasmClientState) diff --git a/testing/mock/client_validator.go b/testing/mock/client_validator.go index ad7be616b20..4ce25373a53 100644 --- a/testing/mock/client_validator.go +++ b/testing/mock/client_validator.go @@ -7,14 +7,14 @@ import ( "github.com/cosmos/ibc-go/v8/modules/core/exported" ) -var _ clienttypes.SelfClientValidator = (*ClientValidator)(nil) +var _ clienttypes.ConsensusHost = (*ConsensusHost)(nil) -type ClientValidator struct { +type ConsensusHost struct { GetSelfConsensusStateFn func(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) ValidateSelfClientFn func(ctx sdk.Context, clientState exported.ClientState) error } -func (cv *ClientValidator) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { +func (cv *ConsensusHost) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { if cv.GetSelfConsensusStateFn == nil { return nil, nil } @@ -22,7 +22,7 @@ func (cv *ClientValidator) GetSelfConsensusState(ctx sdk.Context, height exporte return cv.GetSelfConsensusStateFn(ctx, height) } -func (cv *ClientValidator) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { +func (cv *ConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { if cv.ValidateSelfClientFn == nil { return nil } From 5419a6f3899bf79f62f7b0928d3adbd25a96d90d Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 18 Mar 2024 16:57:20 +0100 Subject: [PATCH 2/9] refactor: rename recvr vars --- modules/core/02-client/keeper/consensus_host.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/core/02-client/keeper/consensus_host.go b/modules/core/02-client/keeper/consensus_host.go index 019a89c15b6..fdc4e7cba9e 100644 --- a/modules/core/02-client/keeper/consensus_host.go +++ b/modules/core/02-client/keeper/consensus_host.go @@ -32,7 +32,7 @@ func NewTendermintConsensusHost(stakingKeeper types.StakingKeeper) types.Consens } // GetSelfConsensusState implements the 02-client types.ConsensusHost interface. -func (tcv *TendermintConsensusHost) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { +func (tch *TendermintConsensusHost) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { selfHeight, ok := height.(types.Height) if !ok { return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", types.Height{}, height) @@ -44,7 +44,7 @@ func (tcv *TendermintConsensusHost) GetSelfConsensusState(ctx sdk.Context, heigh return nil, errorsmod.Wrapf(types.ErrInvalidHeight, "chainID revision number does not match height revision number: expected %d, got %d", revision, height.GetRevisionNumber()) } - histInfo, err := tcv.stakingKeeper.GetHistoricalInfo(ctx, int64(selfHeight.RevisionHeight)) + histInfo, err := tch.stakingKeeper.GetHistoricalInfo(ctx, int64(selfHeight.RevisionHeight)) if err != nil { return nil, errorsmod.Wrapf(err, "height %d", selfHeight.RevisionHeight) } @@ -59,7 +59,7 @@ func (tcv *TendermintConsensusHost) GetSelfConsensusState(ctx sdk.Context, heigh } // ValidateSelfClient implements the 02-client types.ConsensusHost interface. -func (tcv *TendermintConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { +func (tch *TendermintConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { tmClient, ok := clientState.(*ibctm.ClientState) if !ok { return errorsmod.Wrapf(types.ErrInvalidClient, "client must be a Tendermint client, expected: %T, got: %T", &ibctm.ClientState{}, tmClient) @@ -98,7 +98,7 @@ func (tcv *TendermintConsensusHost) ValidateSelfClient(ctx sdk.Context, clientSt return errorsmod.Wrapf(types.ErrInvalidClient, "trust-level invalid: %v", err) } - expectedUbdPeriod, err := tcv.stakingKeeper.UnbondingTime(ctx) + expectedUbdPeriod, err := tch.stakingKeeper.UnbondingTime(ctx) if err != nil { return errorsmod.Wrapf(err, "failed to retrieve unbonding period") } From 41abdcfa488f37669cc93bee218f3284b09735dc Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 18 Mar 2024 17:05:28 +0100 Subject: [PATCH 3/9] refactor: move TestGetSelfConsensusState and TestValidateSelfClient to new file --- .../02-client/keeper/consensus_host_test.go | 234 ++++++++++++++++++ modules/core/02-client/keeper/keeper_test.go | 206 --------------- 2 files changed, 234 insertions(+), 206 deletions(-) create mode 100644 modules/core/02-client/keeper/consensus_host_test.go diff --git a/modules/core/02-client/keeper/consensus_host_test.go b/modules/core/02-client/keeper/consensus_host_test.go new file mode 100644 index 00000000000..125bcf65f37 --- /dev/null +++ b/modules/core/02-client/keeper/consensus_host_test.go @@ -0,0 +1,234 @@ +package keeper_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + "github.com/cosmos/ibc-go/v8/modules/core/exported" + solomachine "github.com/cosmos/ibc-go/v8/modules/light-clients/06-solomachine" + ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" + ibctesting "github.com/cosmos/ibc-go/v8/testing" + "github.com/cosmos/ibc-go/v8/testing/mock" +) + +func (suite *KeeperTestSuite) TestGetSelfConsensusState() { + var height types.Height + + cases := []struct { + name string + malleate func() + expError error + }{ + { + name: "zero height", + malleate: func() { + height = types.ZeroHeight() + }, + expError: stakingtypes.ErrNoHistoricalInfo, + }, + { + name: "height > latest height", + malleate: func() { + height = types.NewHeight(0, uint64(suite.ctx.BlockHeight())+1) + }, + expError: stakingtypes.ErrNoHistoricalInfo, + }, + { + name: "custom client validator: failure", + malleate: func() { + consensusHost := &mock.ConsensusHost{ + GetSelfConsensusStateFn: func(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { + return nil, mock.MockApplicationCallbackError + }, + } + suite.keeper.SetSelfConsensusHost(consensusHost) + }, + expError: mock.MockApplicationCallbackError, + }, + { + name: "custom client validator: success", + malleate: func() { + consensusHost := &mock.ConsensusHost{ + GetSelfConsensusStateFn: func(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { + return &solomachine.ConsensusState{}, nil + }, + } + suite.keeper.SetSelfConsensusHost(consensusHost) + }, + expError: nil, + }, + { + name: "latest height - 1", + malleate: func() { + height = types.NewHeight(0, uint64(suite.ctx.BlockHeight())-1) + }, + expError: nil, + }, + { + name: "latest height", + malleate: func() { + height = types.GetSelfHeight(suite.ctx) + }, + expError: nil, + }, + } + + for i, tc := range cases { + suite.SetupTest() + suite.ctx = suite.ctx.WithBlockHeight(10) + tc := tc + + height = types.ZeroHeight() + + tc.malleate() + + cs, err := suite.keeper.GetSelfConsensusState(suite.ctx, height) + + expPass := tc.expError == nil + if expPass { + suite.Require().NoError(err, "Case %d should have passed: %s", i, tc.name) + suite.Require().NotNil(cs, "Case %d should have passed: %s", i, tc.name) + } else { + suite.Require().ErrorIs(err, tc.expError, "Case %d should have failed: %s", i, tc.name) + suite.Require().Nil(cs, "Case %d should have failed: %s", i, tc.name) + } + } +} + +func (suite *KeeperTestSuite) TestValidateSelfClient() { + testClientHeight := types.GetSelfHeight(suite.chainA.GetContext()) + testClientHeight.RevisionHeight-- + + var clientState exported.ClientState + + testCases := []struct { + name string + malleate func() + expError error + }{ + { + name: "success", + malleate: func() { + clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) + }, + expError: nil, + }, + { + name: "success with nil UpgradePath", + malleate: func() { + clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), nil) + }, + expError: nil, + }, + { + name: "success with custom self validator: solomachine", + malleate: func() { + clientState = solomachine.NewClientState(1, &solomachine.ConsensusState{}) + + smConsensusHost := &mock.ConsensusHost{ + ValidateSelfClientFn: func(ctx sdk.Context, clientState exported.ClientState) error { + smClientState, ok := clientState.(*solomachine.ClientState) + suite.Require().True(ok) + suite.Require().Equal(uint64(1), smClientState.Sequence) + + return nil + }, + } + + // add mock validation logic + suite.chainA.App.GetIBCKeeper().ClientKeeper.SetSelfConsensusHost(smConsensusHost) + }, + expError: nil, + }, + { + name: "frozen client", + malleate: func() { + clientState = &ibctm.ClientState{ChainId: suite.chainA.ChainID, TrustLevel: ibctm.DefaultTrustLevel, TrustingPeriod: trustingPeriod, UnbondingPeriod: ubdPeriod, MaxClockDrift: maxClockDrift, FrozenHeight: testClientHeight, LatestHeight: testClientHeight, ProofSpecs: commitmenttypes.GetSDKSpecs(), UpgradePath: ibctesting.UpgradePath} + }, + expError: types.ErrClientFrozen, + }, + { + name: "incorrect chainID", + malleate: func() { + clientState = ibctm.NewClientState("gaiatestnet", ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) + }, + expError: types.ErrInvalidClient, + }, + { + name: "invalid client height", + malleate: func() { + clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.GetSelfHeight(suite.chainA.GetContext()).Increment().(types.Height), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) + }, + expError: types.ErrInvalidClient, + }, + { + name: "invalid client type", + malleate: func() { + clientState = solomachine.NewClientState(0, &solomachine.ConsensusState{PublicKey: suite.solomachine.ConsensusState().PublicKey, Diversifier: suite.solomachine.Diversifier, Timestamp: suite.solomachine.Time}) + }, + expError: types.ErrInvalidClient, + }, + { + name: "invalid client revision", + malleate: func() { + clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeightRevision1, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) + }, + expError: types.ErrInvalidClient, + }, + { + name: "invalid proof specs", + malleate: func() { + clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, nil, ibctesting.UpgradePath) + }, + expError: types.ErrInvalidClient, + }, + { + name: "invalid trust level", + malleate: func() { + clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) + }, + expError: types.ErrInvalidClient, + }, + { + name: "invalid unbonding period", + malleate: func() { + clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod+10, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) + }, + expError: types.ErrInvalidClient, + }, + { + name: "invalid trusting period", + malleate: func() { + clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ubdPeriod+10, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) + }, + expError: types.ErrInvalidClient, + }, + { + name: "invalid upgrade path", + malleate: func() { + clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), []string{"bad", "upgrade", "path"}) + }, + expError: types.ErrInvalidClient, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() + + tc.malleate() + + err := suite.chainA.App.GetIBCKeeper().ClientKeeper.ValidateSelfClient(suite.chainA.GetContext(), clientState) + + expPass := tc.expError == nil + if expPass { + suite.Require().NoError(err, "expected valid client for case: %s", tc.name) + } else { + suite.Require().Error(err, "expected invalid client for case: %s", tc.name) + } + }) + } +} diff --git a/modules/core/02-client/keeper/keeper_test.go b/modules/core/02-client/keeper/keeper_test.go index b99c2f86ef6..1b423b144a7 100644 --- a/modules/core/02-client/keeper/keeper_test.go +++ b/modules/core/02-client/keeper/keeper_test.go @@ -25,11 +25,9 @@ import ( commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" host "github.com/cosmos/ibc-go/v8/modules/core/24-host" "github.com/cosmos/ibc-go/v8/modules/core/exported" - solomachine "github.com/cosmos/ibc-go/v8/modules/light-clients/06-solomachine" ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost" ibctesting "github.com/cosmos/ibc-go/v8/testing" - "github.com/cosmos/ibc-go/v8/testing/mock" "github.com/cosmos/ibc-go/v8/testing/simapp" ) @@ -146,142 +144,6 @@ func (suite *KeeperTestSuite) TestSetClientConsensusState() { suite.Require().Equal(suite.consensusState, tmConsState, "ConsensusState not stored correctly") } -func (suite *KeeperTestSuite) TestValidateSelfClient() { - testClientHeight := types.GetSelfHeight(suite.chainA.GetContext()) - testClientHeight.RevisionHeight-- - - var clientState exported.ClientState - - testCases := []struct { - name string - malleate func() - expError error - }{ - { - "success", - func() { - clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) - }, - nil, - }, - { - "success with nil UpgradePath", - func() { - clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), nil) - }, - nil, - }, - { - "success with custom self validator: solomachine", - func() { - clientState = solomachine.NewClientState(1, &solomachine.ConsensusState{}) - - smConsensusHost := &mock.ConsensusHost{ - ValidateSelfClientFn: func(ctx sdk.Context, clientState exported.ClientState) error { - smClientState, ok := clientState.(*solomachine.ClientState) - suite.Require().True(ok) - suite.Require().Equal(uint64(1), smClientState.Sequence) - - return nil - }, - } - - // add mock validation logic - suite.chainA.App.GetIBCKeeper().ClientKeeper.SetSelfConsensusHost(smConsensusHost) - }, - nil, - }, - { - "frozen client", - func() { - clientState = &ibctm.ClientState{ChainId: suite.chainA.ChainID, TrustLevel: ibctm.DefaultTrustLevel, TrustingPeriod: trustingPeriod, UnbondingPeriod: ubdPeriod, MaxClockDrift: maxClockDrift, FrozenHeight: testClientHeight, LatestHeight: testClientHeight, ProofSpecs: commitmenttypes.GetSDKSpecs(), UpgradePath: ibctesting.UpgradePath} - }, - types.ErrClientFrozen, - }, - { - "incorrect chainID", - func() { - clientState = ibctm.NewClientState("gaiatestnet", ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) - }, - types.ErrInvalidClient, - }, - { - "invalid client height", - func() { - clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.GetSelfHeight(suite.chainA.GetContext()).Increment().(types.Height), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) - }, - types.ErrInvalidClient, - }, - { - "invalid client type", - func() { - clientState = solomachine.NewClientState(0, &solomachine.ConsensusState{PublicKey: suite.solomachine.ConsensusState().PublicKey, Diversifier: suite.solomachine.Diversifier, Timestamp: suite.solomachine.Time}) - }, - types.ErrInvalidClient, - }, - { - "invalid client revision", - func() { - clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeightRevision1, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) - }, - types.ErrInvalidClient, - }, - { - "invalid proof specs", - func() { - clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, nil, ibctesting.UpgradePath) - }, - types.ErrInvalidClient, - }, - { - "invalid trust level", - func() { - clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) - }, - types.ErrInvalidClient, - }, - { - "invalid unbonding period", - func() { - clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod+10, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) - }, - types.ErrInvalidClient, - }, - { - "invalid trusting period", - func() { - clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ubdPeriod+10, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) - }, - types.ErrInvalidClient, - }, - { - "invalid upgrade path", - func() { - clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), []string{"bad", "upgrade", "path"}) - }, - types.ErrInvalidClient, - }, - } - - for _, tc := range testCases { - tc := tc - suite.Run(tc.name, func() { - suite.SetupTest() - - tc.malleate() - - err := suite.chainA.App.GetIBCKeeper().ClientKeeper.ValidateSelfClient(suite.chainA.GetContext(), clientState) - - expPass := tc.expError == nil - if expPass { - suite.Require().NoError(err, "expected valid client for case: %s", tc.name) - } else { - suite.Require().Error(err, "expected invalid client for case: %s", tc.name) - } - }) - } -} - func (suite *KeeperTestSuite) TestGetAllGenesisClients() { clientIDs := []string{ exported.LocalhostClientID, testClientID2, testClientID3, testClientID, @@ -361,74 +223,6 @@ func (suite *KeeperTestSuite) TestGetAllGenesisMetadata() { }) } -func (suite *KeeperTestSuite) TestGetConsensusState() { - var height types.Height - - cases := []struct { - name string - malleate func() - expError error - }{ - {"zero height", func() { - height = types.ZeroHeight() - }, stakingtypes.ErrNoHistoricalInfo}, - {"height > latest height", func() { - height = types.NewHeight(0, uint64(suite.ctx.BlockHeight())+1) - }, stakingtypes.ErrNoHistoricalInfo}, - { - name: "custom client validator: failure", - malleate: func() { - consensusHost := &mock.ConsensusHost{ - GetSelfConsensusStateFn: func(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { - return nil, mock.MockApplicationCallbackError - }, - } - suite.keeper.SetSelfConsensusHost(consensusHost) - }, - expError: mock.MockApplicationCallbackError, - }, - { - name: "custom client validator: success", - malleate: func() { - consensusHost := &mock.ConsensusHost{ - GetSelfConsensusStateFn: func(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { - return &solomachine.ConsensusState{}, nil - }, - } - suite.keeper.SetSelfConsensusHost(consensusHost) - }, - expError: nil, - }, - {"latest height - 1", func() { - height = types.NewHeight(0, uint64(suite.ctx.BlockHeight())-1) - }, nil}, - {"latest height", func() { - height = types.GetSelfHeight(suite.ctx) - }, nil}, - } - - for i, tc := range cases { - suite.SetupTest() - suite.ctx = suite.ctx.WithBlockHeight(10) - tc := tc - - height = types.ZeroHeight() - - tc.malleate() - - cs, err := suite.keeper.GetSelfConsensusState(suite.ctx, height) - - expPass := tc.expError == nil - if expPass { - suite.Require().NoError(err, "Case %d should have passed: %s", i, tc.name) - suite.Require().NotNil(cs, "Case %d should have passed: %s", i, tc.name) - } else { - suite.Require().ErrorIs(err, tc.expError, "Case %d should have failed: %s", i, tc.name) - suite.Require().Nil(cs, "Case %d should have failed: %s", i, tc.name) - } - } -} - // 2 clients in total are created on chainA. The first client is updated so it contains an initial consensus state // and a consensus state at the update height. func (suite *KeeperTestSuite) TestGetAllConsensusStates() { From a68c75b9736afd6c870137a08b8731751a2de9a4 Mon Sep 17 00:00:00 2001 From: Carlos Rodriguez Date: Tue, 19 Mar 2024 13:36:25 +0100 Subject: [PATCH 4/9] chore: rename client validator to consensus host (#6021) --- modules/core/02-client/keeper/consensus_host_test.go | 4 ++-- modules/core/02-client/keeper/keeper.go | 2 +- modules/core/03-connection/keeper/handshake_test.go | 2 +- modules/light-clients/08-wasm/types/consensus_host.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/core/02-client/keeper/consensus_host_test.go b/modules/core/02-client/keeper/consensus_host_test.go index 125bcf65f37..fd5de556244 100644 --- a/modules/core/02-client/keeper/consensus_host_test.go +++ b/modules/core/02-client/keeper/consensus_host_test.go @@ -36,7 +36,7 @@ func (suite *KeeperTestSuite) TestGetSelfConsensusState() { expError: stakingtypes.ErrNoHistoricalInfo, }, { - name: "custom client validator: failure", + name: "custom consensus host: failure", malleate: func() { consensusHost := &mock.ConsensusHost{ GetSelfConsensusStateFn: func(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { @@ -48,7 +48,7 @@ func (suite *KeeperTestSuite) TestGetSelfConsensusState() { expError: mock.MockApplicationCallbackError, }, { - name: "custom client validator: success", + name: "custom consensus host: success", malleate: func() { consensusHost := &mock.ConsensusHost{ GetSelfConsensusStateFn: func(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { diff --git a/modules/core/02-client/keeper/keeper.go b/modules/core/02-client/keeper/keeper.go index d66386f2667..6f6c6c88e1e 100644 --- a/modules/core/02-client/keeper/keeper.go +++ b/modules/core/02-client/keeper/keeper.go @@ -83,7 +83,7 @@ func (k Keeper) UpdateLocalhostClient(ctx sdk.Context, clientState exported.Clie // SetSelfConsensusHost sets a custom ConsensusHost for self client state and consensus state validation. func (k *Keeper) SetSelfConsensusHost(consensusHost types.ConsensusHost) { if consensusHost == nil { - panic(fmt.Errorf("cannot set a nil self client validator")) + panic(fmt.Errorf("cannot set a nil self consensus host")) } k.consensusHost = consensusHost diff --git a/modules/core/03-connection/keeper/handshake_test.go b/modules/core/03-connection/keeper/handshake_test.go index 6c5945b2b6f..4b27757e50e 100644 --- a/modules/core/03-connection/keeper/handshake_test.go +++ b/modules/core/03-connection/keeper/handshake_test.go @@ -219,7 +219,7 @@ func (suite *KeeperTestSuite) TestConnOpenTry() { err := path.EndpointA.ConnOpenInit() suite.Require().NoError(err) }, false}, - {"override self client validator", func() { + {"override self consensus host", func() { err := path.EndpointA.ConnOpenInit() suite.Require().NoError(err) diff --git a/modules/light-clients/08-wasm/types/consensus_host.go b/modules/light-clients/08-wasm/types/consensus_host.go index a5c4c843792..c19b15dfdfb 100644 --- a/modules/light-clients/08-wasm/types/consensus_host.go +++ b/modules/light-clients/08-wasm/types/consensus_host.go @@ -55,11 +55,11 @@ func (w *WasmTMConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState ex } if w == nil { - return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "wasm client validator is nil") + return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "wasm consensus host is nil") } if w.cdc == nil { - return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "wasm client validator cdc is nil") + return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "wasm consensus host cdc is nil") } if wasmClientState.Data == nil { From 92412ee5f087cff5a7b075a3d18d53afed4e3973 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Tue, 19 Mar 2024 15:43:11 +0100 Subject: [PATCH 5/9] refactor: mv tendermint consensus host to 07-tendermint pkg and refactor tests --- .../core/02-client/keeper/consensus_host.go | 126 ------------------ modules/core/02-client/keeper/keeper.go | 2 +- .../07-tendermint/consensus_host.go | 125 +++++++++++++++++ .../07-tendermint}/consensus_host_test.go | 83 ++++++------ .../08-wasm/types/consensus_host.go | 27 ++-- 5 files changed, 183 insertions(+), 180 deletions(-) delete mode 100644 modules/core/02-client/keeper/consensus_host.go create mode 100644 modules/light-clients/07-tendermint/consensus_host.go rename modules/{core/02-client/keeper => light-clients/07-tendermint}/consensus_host_test.go (69%) diff --git a/modules/core/02-client/keeper/consensus_host.go b/modules/core/02-client/keeper/consensus_host.go deleted file mode 100644 index fdc4e7cba9e..00000000000 --- a/modules/core/02-client/keeper/consensus_host.go +++ /dev/null @@ -1,126 +0,0 @@ -package keeper - -import ( - "reflect" - - errorsmod "cosmossdk.io/errors" - upgradetypes "cosmossdk.io/x/upgrade/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/cometbft/cometbft/light" - - "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" - commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" - ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" - "github.com/cosmos/ibc-go/v8/modules/core/exported" - ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" -) - -var _ types.ConsensusHost = (*TendermintConsensusHost)(nil) - -// TendermintConsensusHost implements the 02-client types.ConsensusHost interface -type TendermintConsensusHost struct { - stakingKeeper types.StakingKeeper -} - -// NewTendermintConsensusHost creates and returns a new ConsensusHost for tendermint consensus. -func NewTendermintConsensusHost(stakingKeeper types.StakingKeeper) types.ConsensusHost { - return &TendermintConsensusHost{ - stakingKeeper: stakingKeeper, - } -} - -// GetSelfConsensusState implements the 02-client types.ConsensusHost interface. -func (tch *TendermintConsensusHost) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { - selfHeight, ok := height.(types.Height) - if !ok { - return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", types.Height{}, height) - } - - // check that height revision matches chainID revision - revision := types.ParseChainID(ctx.ChainID()) - if revision != height.GetRevisionNumber() { - return nil, errorsmod.Wrapf(types.ErrInvalidHeight, "chainID revision number does not match height revision number: expected %d, got %d", revision, height.GetRevisionNumber()) - } - - histInfo, err := tch.stakingKeeper.GetHistoricalInfo(ctx, int64(selfHeight.RevisionHeight)) - if err != nil { - return nil, errorsmod.Wrapf(err, "height %d", selfHeight.RevisionHeight) - } - - consensusState := &ibctm.ConsensusState{ - Timestamp: histInfo.Header.Time, - Root: commitmenttypes.NewMerkleRoot(histInfo.Header.GetAppHash()), - NextValidatorsHash: histInfo.Header.NextValidatorsHash, - } - - return consensusState, nil -} - -// ValidateSelfClient implements the 02-client types.ConsensusHost interface. -func (tch *TendermintConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { - tmClient, ok := clientState.(*ibctm.ClientState) - if !ok { - return errorsmod.Wrapf(types.ErrInvalidClient, "client must be a Tendermint client, expected: %T, got: %T", &ibctm.ClientState{}, tmClient) - } - - if !tmClient.FrozenHeight.IsZero() { - return types.ErrClientFrozen - } - - if ctx.ChainID() != tmClient.ChainId { - return errorsmod.Wrapf(types.ErrInvalidClient, "invalid chain-id. expected: %s, got: %s", - ctx.ChainID(), tmClient.ChainId) - } - - revision := types.ParseChainID(ctx.ChainID()) - - // client must be in the same revision as executing chain - if tmClient.LatestHeight.RevisionNumber != revision { - return errorsmod.Wrapf(types.ErrInvalidClient, "client is not in the same revision as the chain. expected revision: %d, got: %d", - tmClient.LatestHeight.RevisionNumber, revision) - } - - selfHeight := types.NewHeight(revision, uint64(ctx.BlockHeight())) - if tmClient.LatestHeight.GTE(selfHeight) { - return errorsmod.Wrapf(types.ErrInvalidClient, "client has LatestHeight %d greater than or equal to chain height %d", - tmClient.LatestHeight, selfHeight) - } - - expectedProofSpecs := commitmenttypes.GetSDKSpecs() - if !reflect.DeepEqual(expectedProofSpecs, tmClient.ProofSpecs) { - return errorsmod.Wrapf(types.ErrInvalidClient, "client has invalid proof specs. expected: %v got: %v", - expectedProofSpecs, tmClient.ProofSpecs) - } - - if err := light.ValidateTrustLevel(tmClient.TrustLevel.ToTendermint()); err != nil { - return errorsmod.Wrapf(types.ErrInvalidClient, "trust-level invalid: %v", err) - } - - expectedUbdPeriod, err := tch.stakingKeeper.UnbondingTime(ctx) - if err != nil { - return errorsmod.Wrapf(err, "failed to retrieve unbonding period") - } - - if expectedUbdPeriod != tmClient.UnbondingPeriod { - return errorsmod.Wrapf(types.ErrInvalidClient, "invalid unbonding period. expected: %s, got: %s", - expectedUbdPeriod, tmClient.UnbondingPeriod) - } - - if tmClient.UnbondingPeriod < tmClient.TrustingPeriod { - return errorsmod.Wrapf(types.ErrInvalidClient, "unbonding period must be greater than trusting period. unbonding period (%d) < trusting period (%d)", - tmClient.UnbondingPeriod, tmClient.TrustingPeriod) - } - - if len(tmClient.UpgradePath) != 0 { - // For now, SDK IBC implementation assumes that upgrade path (if defined) is defined by SDK upgrade module - expectedUpgradePath := []string{upgradetypes.StoreKey, upgradetypes.KeyUpgradedIBCState} - if !reflect.DeepEqual(expectedUpgradePath, tmClient.UpgradePath) { - return errorsmod.Wrapf(types.ErrInvalidClient, "upgrade path must be the upgrade path defined by upgrade module. expected %v, got %v", - expectedUpgradePath, tmClient.UpgradePath) - } - } - - return nil -} diff --git a/modules/core/02-client/keeper/keeper.go b/modules/core/02-client/keeper/keeper.go index 6f6c6c88e1e..9c070ee066e 100644 --- a/modules/core/02-client/keeper/keeper.go +++ b/modules/core/02-client/keeper/keeper.go @@ -43,7 +43,7 @@ func NewKeeper(cdc codec.BinaryCodec, key storetypes.StoreKey, legacySubspace ty storeKey: key, cdc: cdc, router: router, - consensusHost: NewTendermintConsensusHost(sk), + consensusHost: ibctm.NewConsensusHost(sk), legacySubspace: legacySubspace, stakingKeeper: sk, upgradeKeeper: uk, diff --git a/modules/light-clients/07-tendermint/consensus_host.go b/modules/light-clients/07-tendermint/consensus_host.go new file mode 100644 index 00000000000..d0c62c75c08 --- /dev/null +++ b/modules/light-clients/07-tendermint/consensus_host.go @@ -0,0 +1,125 @@ +package tendermint + +import ( + "reflect" + + errorsmod "cosmossdk.io/errors" + upgradetypes "cosmossdk.io/x/upgrade/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cometbft/cometbft/light" + + clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" + "github.com/cosmos/ibc-go/v8/modules/core/exported" +) + +var _ clienttypes.ConsensusHost = (*ConsensusHost)(nil) + +// ConsensusHost implements the 02-client clienttypes.ConsensusHost interface +type ConsensusHost struct { + stakingKeeper clienttypes.StakingKeeper +} + +// NewConsensusHost creates and returns a new ConsensusHost for tendermint consensus. +func NewConsensusHost(stakingKeeper clienttypes.StakingKeeper) clienttypes.ConsensusHost { + return &ConsensusHost{ + stakingKeeper: stakingKeeper, + } +} + +// GetSelfConsensusState implements the 02-client clienttypes.ConsensusHost interface. +func (c *ConsensusHost) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { + selfHeight, ok := height.(clienttypes.Height) + if !ok { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected %T, got %T", clienttypes.Height{}, height) + } + + // check that height revision matches chainID revision + revision := clienttypes.ParseChainID(ctx.ChainID()) + if revision != height.GetRevisionNumber() { + return nil, errorsmod.Wrapf(clienttypes.ErrInvalidHeight, "chainID revision number does not match height revision number: expected %d, got %d", revision, height.GetRevisionNumber()) + } + + histInfo, err := c.stakingKeeper.GetHistoricalInfo(ctx, int64(selfHeight.RevisionHeight)) + if err != nil { + return nil, errorsmod.Wrapf(err, "height %d", selfHeight.RevisionHeight) + } + + consensusState := &ConsensusState{ + Timestamp: histInfo.Header.Time, + Root: commitmenttypes.NewMerkleRoot(histInfo.Header.GetAppHash()), + NextValidatorsHash: histInfo.Header.NextValidatorsHash, + } + + return consensusState, nil +} + +// ValidateSelfClient implements the 02-client clienttypes.ConsensusHost interface. +func (c *ConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { + tmClient, ok := clientState.(*ClientState) + if !ok { + return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "client must be a Tendermint client, expected: %T, got: %T", &ClientState{}, tmClient) + } + + if !tmClient.FrozenHeight.IsZero() { + return clienttypes.ErrClientFrozen + } + + if ctx.ChainID() != tmClient.ChainId { + return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "invalid chain-id. expected: %s, got: %s", + ctx.ChainID(), tmClient.ChainId) + } + + revision := clienttypes.ParseChainID(ctx.ChainID()) + + // client must be in the same revision as executing chain + if tmClient.LatestHeight.RevisionNumber != revision { + return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "client is not in the same revision as the chain. expected revision: %d, got: %d", + tmClient.LatestHeight.RevisionNumber, revision) + } + + selfHeight := clienttypes.NewHeight(revision, uint64(ctx.BlockHeight())) + if tmClient.LatestHeight.GTE(selfHeight) { + return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "client has LatestHeight %d greater than or equal to chain height %d", + tmClient.LatestHeight, selfHeight) + } + + expectedProofSpecs := commitmenttypes.GetSDKSpecs() + if !reflect.DeepEqual(expectedProofSpecs, tmClient.ProofSpecs) { + return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "client has invalid proof specs. expected: %v got: %v", + expectedProofSpecs, tmClient.ProofSpecs) + } + + if err := light.ValidateTrustLevel(tmClient.TrustLevel.ToTendermint()); err != nil { + return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "trust-level invalid: %v", err) + } + + expectedUbdPeriod, err := c.stakingKeeper.UnbondingTime(ctx) + if err != nil { + return errorsmod.Wrapf(err, "failed to retrieve unbonding period") + } + + if expectedUbdPeriod != tmClient.UnbondingPeriod { + return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "invalid unbonding period. expected: %s, got: %s", + expectedUbdPeriod, tmClient.UnbondingPeriod) + } + + if tmClient.UnbondingPeriod < tmClient.TrustingPeriod { + return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "unbonding period must be greater than trusting period. unbonding period (%d) < trusting period (%d)", + tmClient.UnbondingPeriod, tmClient.TrustingPeriod) + } + + if len(tmClient.UpgradePath) != 0 { + // For now, SDK IBC implementation assumes that upgrade path (if defined) is defined by SDK upgrade module + expectedUpgradePath := []string{upgradetypes.StoreKey, upgradetypes.KeyUpgradedIBCState} + if !reflect.DeepEqual(expectedUpgradePath, tmClient.UpgradePath) { + return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "upgrade path must be the upgrade path defined by upgrade module. expected %v, got %v", + expectedUpgradePath, tmClient.UpgradePath) + } + } + + return nil +} diff --git a/modules/core/02-client/keeper/consensus_host_test.go b/modules/light-clients/07-tendermint/consensus_host_test.go similarity index 69% rename from modules/core/02-client/keeper/consensus_host_test.go rename to modules/light-clients/07-tendermint/consensus_host_test.go index fd5de556244..3a62d27c182 100644 --- a/modules/core/02-client/keeper/consensus_host_test.go +++ b/modules/light-clients/07-tendermint/consensus_host_test.go @@ -1,10 +1,10 @@ -package keeper_test +package tendermint_test import ( sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" "github.com/cosmos/ibc-go/v8/modules/core/exported" solomachine "github.com/cosmos/ibc-go/v8/modules/light-clients/06-solomachine" @@ -13,8 +13,8 @@ import ( "github.com/cosmos/ibc-go/v8/testing/mock" ) -func (suite *KeeperTestSuite) TestGetSelfConsensusState() { - var height types.Height +func (suite *TendermintTestSuite) TestGetSelfConsensusState() { + var height clienttypes.Height cases := []struct { name string @@ -24,14 +24,14 @@ func (suite *KeeperTestSuite) TestGetSelfConsensusState() { { name: "zero height", malleate: func() { - height = types.ZeroHeight() + height = clienttypes.ZeroHeight() }, - expError: stakingtypes.ErrNoHistoricalInfo, + expError: clienttypes.ErrInvalidHeight, }, { name: "height > latest height", malleate: func() { - height = types.NewHeight(0, uint64(suite.ctx.BlockHeight())+1) + height = clienttypes.NewHeight(1, uint64(suite.chainA.GetContext().BlockHeight())+1) }, expError: stakingtypes.ErrNoHistoricalInfo, }, @@ -43,7 +43,7 @@ func (suite *KeeperTestSuite) TestGetSelfConsensusState() { return nil, mock.MockApplicationCallbackError }, } - suite.keeper.SetSelfConsensusHost(consensusHost) + suite.chainA.GetSimApp().GetIBCKeeper().ClientKeeper.SetSelfConsensusHost(consensusHost) }, expError: mock.MockApplicationCallbackError, }, @@ -55,50 +55,55 @@ func (suite *KeeperTestSuite) TestGetSelfConsensusState() { return &solomachine.ConsensusState{}, nil }, } - suite.keeper.SetSelfConsensusHost(consensusHost) + suite.chainA.GetSimApp().GetIBCKeeper().ClientKeeper.SetSelfConsensusHost(consensusHost) }, expError: nil, }, { name: "latest height - 1", malleate: func() { - height = types.NewHeight(0, uint64(suite.ctx.BlockHeight())-1) + height = clienttypes.NewHeight(1, uint64(suite.chainA.GetContext().BlockHeight())-1) }, expError: nil, }, { name: "latest height", malleate: func() { - height = types.GetSelfHeight(suite.ctx) + // historical info is set on BeginBlock in x/staking, which is now encapsulated within the FinalizeBlock abci method, + // thus, we do not have historical info for current height due to how the ibctesting library operates. + // ibctesting calls app.Commit() as a final step on NextBlock and we invoke test code before FinalizeBlock is called at the current height once again. + suite.chainA.GetSimApp().StakingKeeper.TrackHistoricalInfo(suite.chainA.GetContext()) + height = clienttypes.GetSelfHeight(suite.chainA.GetContext()) }, expError: nil, }, } for i, tc := range cases { - suite.SetupTest() - suite.ctx = suite.ctx.WithBlockHeight(10) tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() - height = types.ZeroHeight() + height = clienttypes.ZeroHeight() - tc.malleate() + tc.malleate() - cs, err := suite.keeper.GetSelfConsensusState(suite.ctx, height) + cs, err := suite.chainA.GetSimApp().GetIBCKeeper().ClientKeeper.GetSelfConsensusState(suite.chainA.GetContext(), height) - expPass := tc.expError == nil - if expPass { - suite.Require().NoError(err, "Case %d should have passed: %s", i, tc.name) - suite.Require().NotNil(cs, "Case %d should have passed: %s", i, tc.name) - } else { - suite.Require().ErrorIs(err, tc.expError, "Case %d should have failed: %s", i, tc.name) - suite.Require().Nil(cs, "Case %d should have failed: %s", i, tc.name) - } + expPass := tc.expError == nil + if expPass { + suite.Require().NoError(err, "Case %d should have passed: %s", i, tc.name) + suite.Require().NotNil(cs, "Case %d should have passed: %s", i, tc.name) + } else { + suite.Require().ErrorIs(err, tc.expError, "Case %d should have failed: %s", i, tc.name) + suite.Require().Nil(cs, "Case %d should have failed: %s", i, tc.name) + } + }) } } -func (suite *KeeperTestSuite) TestValidateSelfClient() { - testClientHeight := types.GetSelfHeight(suite.chainA.GetContext()) +func (suite *TendermintTestSuite) TestValidateSelfClient() { + testClientHeight := clienttypes.GetSelfHeight(suite.chainA.GetContext()) testClientHeight.RevisionHeight-- var clientState exported.ClientState @@ -147,70 +152,70 @@ func (suite *KeeperTestSuite) TestValidateSelfClient() { malleate: func() { clientState = &ibctm.ClientState{ChainId: suite.chainA.ChainID, TrustLevel: ibctm.DefaultTrustLevel, TrustingPeriod: trustingPeriod, UnbondingPeriod: ubdPeriod, MaxClockDrift: maxClockDrift, FrozenHeight: testClientHeight, LatestHeight: testClientHeight, ProofSpecs: commitmenttypes.GetSDKSpecs(), UpgradePath: ibctesting.UpgradePath} }, - expError: types.ErrClientFrozen, + expError: clienttypes.ErrClientFrozen, }, { name: "incorrect chainID", malleate: func() { clientState = ibctm.NewClientState("gaiatestnet", ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) }, - expError: types.ErrInvalidClient, + expError: clienttypes.ErrInvalidClient, }, { name: "invalid client height", malleate: func() { - clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.GetSelfHeight(suite.chainA.GetContext()).Increment().(types.Height), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) + clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.GetSelfHeight(suite.chainA.GetContext()).Increment().(clienttypes.Height), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) }, - expError: types.ErrInvalidClient, + expError: clienttypes.ErrInvalidClient, }, { name: "invalid client type", malleate: func() { - clientState = solomachine.NewClientState(0, &solomachine.ConsensusState{PublicKey: suite.solomachine.ConsensusState().PublicKey, Diversifier: suite.solomachine.Diversifier, Timestamp: suite.solomachine.Time}) + clientState = solomachine.NewClientState(0, &solomachine.ConsensusState{}) }, - expError: types.ErrInvalidClient, + expError: clienttypes.ErrInvalidClient, }, { name: "invalid client revision", malleate: func() { - clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeightRevision1, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) + clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 5), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) }, - expError: types.ErrInvalidClient, + expError: clienttypes.ErrInvalidClient, }, { name: "invalid proof specs", malleate: func() { clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, nil, ibctesting.UpgradePath) }, - expError: types.ErrInvalidClient, + expError: clienttypes.ErrInvalidClient, }, { name: "invalid trust level", malleate: func() { clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) }, - expError: types.ErrInvalidClient, + expError: clienttypes.ErrInvalidClient, }, { name: "invalid unbonding period", malleate: func() { clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod+10, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) }, - expError: types.ErrInvalidClient, + expError: clienttypes.ErrInvalidClient, }, { name: "invalid trusting period", malleate: func() { clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, ubdPeriod+10, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath) }, - expError: types.ErrInvalidClient, + expError: clienttypes.ErrInvalidClient, }, { name: "invalid upgrade path", malleate: func() { clientState = ibctm.NewClientState(suite.chainA.ChainID, ibctm.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), []string{"bad", "upgrade", "path"}) }, - expError: types.ErrInvalidClient, + expError: clienttypes.ErrInvalidClient, }, } diff --git a/modules/light-clients/08-wasm/types/consensus_host.go b/modules/light-clients/08-wasm/types/consensus_host.go index c19b15dfdfb..6dbc4f9b428 100644 --- a/modules/light-clients/08-wasm/types/consensus_host.go +++ b/modules/light-clients/08-wasm/types/consensus_host.go @@ -6,29 +6,28 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - clientkeeper "github.com/cosmos/ibc-go/v8/modules/core/02-client/keeper" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" "github.com/cosmos/ibc-go/v8/modules/core/exported" ) -// WasmTMConsensusHost implements the 02-client types.ConsensusHost interface. -type WasmTMConsensusHost struct { +// WasmConsensusHost implements the 02-client types.ConsensusHost interface. +type WasmConsensusHost struct { cdc codec.BinaryCodec - tm *clientkeeper.TendermintConsensusHost + tm clienttypes.ConsensusHost } -var _ clienttypes.ConsensusHost = (*WasmTMConsensusHost)(nil) +var _ clienttypes.ConsensusHost = (*WasmConsensusHost)(nil) -// NewWasmTMConsensusHost creates and returns a new ConsensusHost for wasm tendermint consensus client state and consensus state self validation. -func NewWasmTMConsensusHost(cdc codec.BinaryCodec, tm *clientkeeper.TendermintConsensusHost) *WasmTMConsensusHost { - return &WasmTMConsensusHost{ +// NewWasmConsensusHost creates and returns a new ConsensusHost for wasm wrapped consensus client state and consensus state self validation. +func NewWasmConsensusHost(cdc codec.BinaryCodec, tm clienttypes.ConsensusHost) *WasmConsensusHost { + return &WasmConsensusHost{ cdc: cdc, tm: tm, } } // GetSelfConsensusState implements the 02-client types.ConsensusHost interface. -func (w *WasmTMConsensusHost) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { +func (w *WasmConsensusHost) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { consensusState, err := w.tm.GetSelfConsensusState(ctx, height) if err != nil { return nil, err @@ -48,7 +47,7 @@ func (w *WasmTMConsensusHost) GetSelfConsensusState(ctx sdk.Context, height expo } // ValidateSelfClient implements the 02-client types.ConsensusHost interface. -func (w *WasmTMConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { +func (w *WasmConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { wasmClientState, ok := clientState.(*ClientState) if !ok { return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "client must be a wasm client, expected: %T, got: %T", ClientState{}, wasmClientState) @@ -66,11 +65,11 @@ func (w *WasmTMConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState ex return errorsmod.Wrapf(clienttypes.ErrInvalidClient, "wasm client state data is nil") } - // unmarshal the wasmClientState bytes into tendermint client and call self validation - var tmClientState exported.ClientState - if err := w.cdc.UnmarshalInterface(wasmClientState.Data, &tmClientState); err != nil { + // unmarshal the wasmClientState bytes into the ClientState interface and call self validation + var unwrappedClientState exported.ClientState + if err := w.cdc.UnmarshalInterface(wasmClientState.Data, &unwrappedClientState); err != nil { return err } - return w.tm.ValidateSelfClient(ctx, tmClientState) + return w.tm.ValidateSelfClient(ctx, unwrappedClientState) } From 91f32c043df851dc13c0fdbbd61eeb2aa8812746 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Tue, 19 Mar 2024 15:48:59 +0100 Subject: [PATCH 6/9] rename tm -> delegate in 08-wasm impl --- .../light-clients/08-wasm/types/consensus_host.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/light-clients/08-wasm/types/consensus_host.go b/modules/light-clients/08-wasm/types/consensus_host.go index 6dbc4f9b428..3325fdbabc8 100644 --- a/modules/light-clients/08-wasm/types/consensus_host.go +++ b/modules/light-clients/08-wasm/types/consensus_host.go @@ -12,23 +12,23 @@ import ( // WasmConsensusHost implements the 02-client types.ConsensusHost interface. type WasmConsensusHost struct { - cdc codec.BinaryCodec - tm clienttypes.ConsensusHost + cdc codec.BinaryCodec + delegate clienttypes.ConsensusHost } var _ clienttypes.ConsensusHost = (*WasmConsensusHost)(nil) // NewWasmConsensusHost creates and returns a new ConsensusHost for wasm wrapped consensus client state and consensus state self validation. -func NewWasmConsensusHost(cdc codec.BinaryCodec, tm clienttypes.ConsensusHost) *WasmConsensusHost { +func NewWasmConsensusHost(cdc codec.BinaryCodec, delegate clienttypes.ConsensusHost) *WasmConsensusHost { return &WasmConsensusHost{ - cdc: cdc, - tm: tm, + cdc: cdc, + delegate: delegate, } } // GetSelfConsensusState implements the 02-client types.ConsensusHost interface. func (w *WasmConsensusHost) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, error) { - consensusState, err := w.tm.GetSelfConsensusState(ctx, height) + consensusState, err := w.delegate.GetSelfConsensusState(ctx, height) if err != nil { return nil, err } @@ -71,5 +71,5 @@ func (w *WasmConsensusHost) ValidateSelfClient(ctx sdk.Context, clientState expo return err } - return w.tm.ValidateSelfClient(ctx, unwrappedClientState) + return w.delegate.ValidateSelfClient(ctx, unwrappedClientState) } From 8bb9e80f879c97fc358b022a512030c849cbeb67 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Tue, 19 Mar 2024 17:04:27 +0100 Subject: [PATCH 7/9] fix: make lint-fix and address errs --- modules/core/02-client/keeper/keeper_test.go | 3 +-- modules/light-clients/07-tendermint/consensus_host_test.go | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/core/02-client/keeper/keeper_test.go b/modules/core/02-client/keeper/keeper_test.go index 1b423b144a7..817a9423048 100644 --- a/modules/core/02-client/keeper/keeper_test.go +++ b/modules/core/02-client/keeper/keeper_test.go @@ -45,8 +45,7 @@ const ( ) var ( - testClientHeight = types.NewHeight(0, 5) - testClientHeightRevision1 = types.NewHeight(1, 5) + testClientHeight = types.NewHeight(0, 5) ) type KeeperTestSuite struct { diff --git a/modules/light-clients/07-tendermint/consensus_host_test.go b/modules/light-clients/07-tendermint/consensus_host_test.go index 3a62d27c182..21e390cbf03 100644 --- a/modules/light-clients/07-tendermint/consensus_host_test.go +++ b/modules/light-clients/07-tendermint/consensus_host_test.go @@ -72,7 +72,9 @@ func (suite *TendermintTestSuite) TestGetSelfConsensusState() { // historical info is set on BeginBlock in x/staking, which is now encapsulated within the FinalizeBlock abci method, // thus, we do not have historical info for current height due to how the ibctesting library operates. // ibctesting calls app.Commit() as a final step on NextBlock and we invoke test code before FinalizeBlock is called at the current height once again. - suite.chainA.GetSimApp().StakingKeeper.TrackHistoricalInfo(suite.chainA.GetContext()) + err := suite.chainA.GetSimApp().StakingKeeper.TrackHistoricalInfo(suite.chainA.GetContext()) + suite.Require().NoError(err) + height = clienttypes.GetSelfHeight(suite.chainA.GetContext()) }, expError: nil, From 4f31a507bf9fc6f5f8bb5c871d18fece805b29df Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Tue, 19 Mar 2024 22:47:39 +0100 Subject: [PATCH 8/9] chore: make format --- modules/core/02-client/keeper/keeper_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/core/02-client/keeper/keeper_test.go b/modules/core/02-client/keeper/keeper_test.go index 817a9423048..95bcd0b83bd 100644 --- a/modules/core/02-client/keeper/keeper_test.go +++ b/modules/core/02-client/keeper/keeper_test.go @@ -44,9 +44,7 @@ const ( maxClockDrift time.Duration = time.Second * 10 ) -var ( - testClientHeight = types.NewHeight(0, 5) -) +var testClientHeight = types.NewHeight(0, 5) type KeeperTestSuite struct { testifysuite.Suite From 0ff0fd75d8bac75fecf1bf106d36e8cff291fad4 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Wed, 20 Mar 2024 15:13:55 +0100 Subject: [PATCH 9/9] chore: rename client_validator.go -> consensus_host.go in mocks --- testing/mock/{client_validator.go => consensus_host.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename testing/mock/{client_validator.go => consensus_host.go} (100%) diff --git a/testing/mock/client_validator.go b/testing/mock/consensus_host.go similarity index 100% rename from testing/mock/client_validator.go rename to testing/mock/consensus_host.go