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

refactor!: decouple client routing from encoding #5806

Merged
merged 92 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
c459971
refactor: add initial light client module interface
colin-axner Jan 29, 2024
e44bfc1
wip: add boiler plate light client module for tendermint client
colin-axner Jan 29, 2024
53a8dbe
feat: adding initial light client module impl for 06-solomachine
damiannolan Jan 29, 2024
f90c702
chore: adding LightClientModule interface assertion for 06-solomachine
damiannolan Jan 29, 2024
87e952f
chore: adding initial boiilerplate for 08-wasm mod
damiannolan Jan 30, 2024
100340a
refactor: add boilerplate tendermint light client module
colin-axner Jan 30, 2024
cc856d2
Merge branch 'feat/02-client-router' of github.com:cosmos/ibc-go into…
colin-axner Jan 30, 2024
1ec5291
refactor: add localhost boilerplate code
colin-axner Jan 30, 2024
a21fded
imp: add basic 02-client router
colin-axner Jan 30, 2024
9ee3fff
refactor: use light client module for client status
colin-axner Jan 30, 2024
95f1ff5
chore: move solomachine keeper to internal
damiannolan Jan 30, 2024
63483bf
chore: adding GetTimestampAtHeight to clientkeeper using 02-client ro…
damiannolan Jan 30, 2024
f08c004
refactor: rm GetTimestampAtHeight from 03-connection and adapt api ca…
damiannolan Jan 30, 2024
090cbbf
chore: wire up solomachine module with clientRouter in app.go
damiannolan Jan 30, 2024
8d8bb34
chore: move commented out test to client keeper - still has todo to u…
damiannolan Jan 30, 2024
2875686
chore: add solomachine client module to AppModule constructor and wir…
damiannolan Jan 30, 2024
f36001b
fix: use correct route for client status lookup
colin-axner Jan 30, 2024
3cf291f
Merge branch 'feat/02-client-router' of github.com:cosmos/ibc-go into…
colin-axner Jan 30, 2024
a7f995d
chore: add clientRouter to 08-wasm simapp and wire up
damiannolan Jan 30, 2024
46ebec2
fix: solo machine unmarshal bug and 02-client keeper tests
colin-axner Jan 30, 2024
542dd95
Merge branch 'feat/02-client-router' of github.com:cosmos/ibc-go into…
colin-axner Jan 30, 2024
896f225
test: fix GetTimestampAtHeight test in clientkeeper
damiannolan Jan 30, 2024
145c834
Merge branch 'feat/02-client-router' of github.com:cosmos/ibc-go into…
colin-axner Jan 30, 2024
55ffa19
refactor(solomachine): add getClientState helper and unmarhsal interface
damiannolan Jan 30, 2024
3e9a40c
refactor: align 08-wasm, add GetClientState helper and unmarshal inte…
damiannolan Jan 30, 2024
61311e8
fix(temp): temporarily add WithStoreKey opt to wasmkeeper to fix fail…
damiannolan Jan 30, 2024
daf3b47
fix: wire up callbacks simapp to fix failing tests
damiannolan Jan 30, 2024
a4cc0bc
refactor: modify UpdateClient handler to use light client module api
damiannolan Jan 30, 2024
8efa5be
Merge branch 'main' of github.com:cosmos/ibc-go into feat/02-client-r…
colin-axner Jan 31, 2024
3020f38
feat: add ClientStoreProvider interface for isolated prefix stores (#…
damiannolan Jan 31, 2024
92747c8
refactor: rm internal/keeper from solomachine
damiannolan Jan 31, 2024
379e0d3
refactor: begin removing stale client state interfaces
colin-axner Jan 31, 2024
b639a87
Merge branch 'feat/02-client-router' of github.com:cosmos/ibc-go into…
colin-axner Jan 31, 2024
3099d33
feat: wire up localhost
colin-axner Jan 31, 2024
2ca1ddf
fix: tests in 06-solomachine and 07-tendermint
colin-axner Jan 31, 2024
029f5ef
fix: rest of tests
colin-axner Jan 31, 2024
23b5cbb
refactor: use light client module APIs in 03-connection state verify
damiannolan Jan 31, 2024
2a2133b
chore: adapt remaining handlers to use light client module api in 03-…
damiannolan Jan 31, 2024
f60c4be
fix: locahost verify membership and non membership in light client mo…
colin-axner Jan 31, 2024
5ccc21b
Merge branch 'feat/02-client-router' of github.com:cosmos/ibc-go into…
colin-axner Jan 31, 2024
47521d7
refactor: remove VerifyMembership and VerifyNonMembership from client…
colin-axner Jan 31, 2024
11e40d0
Merge branch 'main' of github.com:cosmos/ibc-go into feat/02-client-r…
colin-axner Jan 31, 2024
91084ba
fix: rm getters for clientID from connection (conflict)
damiannolan Feb 1, 2024
acdec44
Merge branch 'main' into feat/02-client-router
crodriguezvega Feb 7, 2024
f08a0e6
02-client routing: fix linter warnings (#5818)
crodriguezvega Feb 8, 2024
daedbf6
02-client routing: pass client ID to get route instead of client type…
crodriguezvega Feb 8, 2024
2f9186c
use localhost client ID
crodriguezvega Feb 8, 2024
61937ea
02-client routing: function in store provider to return client store …
crodriguezvega Feb 15, 2024
b715710
02-client routing: implement `RecoverClient` in light client modules …
crodriguezvega Feb 15, 2024
f4ee20b
Merge branch 'main' into feat/02-client-router
crodriguezvega Feb 18, 2024
1225ce0
fixes from merge of main
crodriguezvega Feb 18, 2024
f9eaf91
02-client routing: remove client ID validation (#5897)
crodriguezvega Feb 27, 2024
87c6a65
Merge branch 'main' into feat/02-client-router
damiannolan Mar 4, 2024
6b55091
Merge branch 'main' into feat/02-client-router
damiannolan Mar 5, 2024
650d785
Merge branch 'main' into feat/02-client-router
crodriguezvega Mar 6, 2024
68bb9f2
docs: add removal of `ClientState` interface functions to migration d…
crodriguezvega Mar 7, 2024
501a846
02-client routing: remove `GetLatestHeight` from `ClientState` interf…
crodriguezvega Mar 11, 2024
ccf2adf
docs: refactor light client developer guide
colin-axner Mar 11, 2024
63ec69c
imp: cleanup godoc on router type
colin-axner Mar 11, 2024
b6d07a5
02-client routing: implement `VerifyUpgradeAndUpdateState` in light c…
crodriguezvega Mar 12, 2024
e143ecb
Merge branch 'main' into feat/02-client-router
damiannolan Mar 12, 2024
93f84b0
nit: lcm -> l for all light client modules
colin-axner Mar 12, 2024
e3348f3
remove unnecessary comment
colin-axner Mar 12, 2024
39601e3
chore: remove unnecessary todo's
colin-axner Mar 12, 2024
0921bf6
chore: lint fix docs
colin-axner Mar 12, 2024
89112a1
Apply suggestions from code review
colin-axner Mar 12, 2024
4f9b535
chore: 02-client handler godoc
colin-axner Mar 12, 2024
ea3fff4
Merge branch 'feat/02-client-router' of github.com:cosmos/ibc-go into…
colin-axner Mar 12, 2024
8c5f67c
Update modules/core/02-client/keeper/client.go
colin-axner Mar 12, 2024
fa51d0d
Update modules/light-clients/06-solomachine/light_client_module_test.go
colin-axner Mar 12, 2024
bddbb07
remove commented out code in msg server
colin-axner Mar 13, 2024
184a271
chore: update godoc, remove todo's
colin-axner Mar 13, 2024
708e452
chore: remove unnecessary func from localhost + cleanup
colin-axner Mar 13, 2024
9bad009
Apply suggestions from code review
colin-axner Mar 13, 2024
cbfaea7
Update docs/docs/03-light-clients/01-developer-guide/01-overview.md
colin-axner Mar 13, 2024
5de2ebc
chore: remove todo + deprecation notice
colin-axner Mar 13, 2024
02d40b2
Merge branch 'feat/02-client-router' of github.com:cosmos/ibc-go into…
colin-axner Mar 13, 2024
7674954
chore: fix broken link
colin-axner Mar 13, 2024
a830c11
chore: godoc for exported client.go file
colin-axner Mar 13, 2024
3b3ff19
chore: test update
colin-axner Mar 13, 2024
cfb8607
chore: godoc
colin-axner Mar 13, 2024
a43b1b3
chore: update godoc in 06-solomachine light client module
colin-axner Mar 13, 2024
3128ab8
chore: update 07-tendermint light client module godoc
colin-axner Mar 13, 2024
5ed427a
chore: update localhost client module godocs
colin-axner Mar 13, 2024
0d821c5
chore: update 08-wasm light client module godoc
colin-axner Mar 13, 2024
ba429b9
fix: broken link
colin-axner Mar 13, 2024
0329451
fix(e2e): correctly assign trusted height and latest height vars to b…
damiannolan Mar 13, 2024
16e141b
address my self-review comments and some of rabbit's comments
crodriguezvega Mar 14, 2024
4cd3a59
Merge branch 'main' into feat/02-client-router
crodriguezvega Mar 14, 2024
c1c70ae
Update e2e/tests/transfer/localhost_test.go
damiannolan Mar 14, 2024
696f852
chore: godocs, rm ClientStore from expected keeper, rename events arg…
damiannolan Mar 14, 2024
86f3679
Merge branch 'main' into feat/02-client-router
damiannolan Mar 14, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ Learn how to implement the [`ClientState`](https://github.com/cosmos/ibc-go/blob
`ClientType` should return a unique string identifier of the light client. This will be used when generating a client identifier.
The format is created as follows: `ClientType-{N}` where `{N}` is the unique global nonce associated with a specific client.

## `GetLatestHeight` method

`GetLatestHeight` should return the latest block height that the client state represents.

## `Validate` method

`Validate` should validate every client state field and should return an error if any value is invalid. The light client
Expand Down
23 changes: 23 additions & 0 deletions docs/docs/05-migrations/13-v8-to-v9.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,29 @@

The `ExportMetadata` interface function has been removed from the `ClientState` interface. Core IBC will export all key/value's within the 02-client store.

The `ZeroCustomFields` interface function has been removed from the `ClientState` interface.

The following functions have also been removed from the `ClientState` interface: `Initialize`, `Status`, `GetLatestHeight`, `GetTimestampAtHeight`, `VerifyClientMessage`, `VerifyMembership`, `VerifyNonMembership`, `CheckForMisbehaviour`, `UpdateState`, `UpdateStateOnMisbehaviour`, `CheckSubstituteAndUpdateState` and `VerifyUpgradeAndUpdateState`. ibc-go v9 decouples routing at the `02-client` layer from the light clients' encoding structure (i.e. every light client implementation of the `ClientState` interface is not used anymore to route the requests to the right light client at the `02-client` layer, instead a _light client module_ is registered for every light client type and `02-client` routes the requests to the right light client module based on the client ID). Light client developers must implement the newly introduced `LightClientModule` interface and are encouraged to move the logic implemented in the functions of their light client's implementation of the `ClientState` interface to the equivalent function in the `LightClientModule` interface. The table below shows the equivalence between the `ClientState` interface functions that have been removed and the functions in the `LightClientModule` interface:

Check failure on line 60 in docs/docs/05-migrations/13-v8-to-v9.md

View workflow job for this annotation

GitHub Actions / lint

Emphasis style

docs/docs/05-migrations/13-v8-to-v9.md:60:622 MD049/emphasis-style Emphasis style [Expected: asterisk; Actual: underscore] https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md049.md

Check failure on line 60 in docs/docs/05-migrations/13-v8-to-v9.md

View workflow job for this annotation

GitHub Actions / lint

Emphasis style

docs/docs/05-migrations/13-v8-to-v9.md:60:642 MD049/emphasis-style Emphasis style [Expected: asterisk; Actual: underscore] https://github.com/DavidAnson/markdownlint/blob/v0.33.0/doc/md049.md

|`ClientState` interface|`LightClientModule` interface|
|-----------------------|-----------------------------|
|`Initialize` |`Initialize` |
|`Status` |`Status` |
|`GetLatestHeight` |`LatestHeight` |
|`GetTimestampAtHeight` |`TimestampAtHeight` |
|`VerifyClientMessage` |`VerifyClientMessage` |
|`VerifyMembership` |`VerifyMembership` |
|`VerifyNonMembership` |`VerifyNonMembership` |
|`CheckForMisbehaviour` |`CheckForMisbehaviour` |
|`UpdateState` |`UpdateState` |
|`UpdateStateOnMisbehaviour` |`UpdateStateOnMisbehaviour` |
|`CheckSubstituteAndUpdateState`|`RecoverClient` |
|`VerifyUpgradeAndUpdateState` |`VerifyUpgradeAndUpdateState`|
|`ExportMetadata` | |
|`ZeroCustomFields` | |

Please check also the [light client developer guide](../03-light-clients/01-developer-guide/01-overview.md) for more information. The light client module implementation for `07-tendermint` may also be useful as reference.
damiannolan marked this conversation as resolved.
Show resolved Hide resolved

### 07-tendermint

The `IterateConsensusMetadata` function has been removed.
Expand Down
8 changes: 4 additions & 4 deletions e2e/tests/core/02-client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,8 @@ func (s *ClientTestSuite) TestClient_Update_Misbehaviour() {
tmClientState, ok := clientState.(*ibctm.ClientState)
s.Require().True(ok)

trustedHeight, ok = tmClientState.GetLatestHeight().(clienttypes.Height)
s.Require().True(ok)
trustedHeight := tmClientState.LatestHeight
s.Require().True(trustedHeight.GT(clienttypes.ZeroHeight()))
})

t.Run("update clients", func(t *testing.T) {
Expand All @@ -377,8 +377,8 @@ func (s *ClientTestSuite) TestClient_Update_Misbehaviour() {
tmClientState, ok := clientState.(*ibctm.ClientState)
s.Require().True(ok)

latestHeight, ok = tmClientState.GetLatestHeight().(clienttypes.Height)
s.Require().True(ok)
latestHeight := tmClientState.LatestHeight
s.Require().True(latestHeight.GT(clienttypes.ZeroHeight()))
})

t.Run("create validator set", func(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions e2e/tests/transfer/localhost_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ func (s *LocalhostTransferTestSuite) TestMsgTransfer_Localhost() {
t.Run("verify begin blocker was executed", func(t *testing.T) {
cs, err := s.QueryClientState(ctx, chainA, exported.LocalhostClientID)
s.Require().NoError(err)
originalHeight := cs.GetLatestHeight()
originalHeight := cs.(*localhost.ClientState).LatestHeight

s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA), "failed to wait for blocks")

cs, err = s.QueryClientState(ctx, chainA, exported.LocalhostClientID)
s.Require().NoError(err)
s.Require().True(cs.GetLatestHeight().GT(originalHeight), "client state height was not incremented")
s.Require().True(cs.(*localhost.ClientState).LatestHeight.GT(originalHeight), "client state height was not incremented")
})

t.Run("channel open init localhost", func(t *testing.T) {
Expand Down
12 changes: 10 additions & 2 deletions modules/apps/callbacks/testing/simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,14 @@ func NewSimApp(
// Seal the IBC Router
app.IBCKeeper.SetRouter(ibcRouter)

clientRouter := app.IBCKeeper.ClientKeeper.GetRouter()

tmLightClientModule := ibctm.NewLightClientModule(appCodec, authtypes.NewModuleAddress(govtypes.ModuleName).String())
clientRouter.AddRoute(ibctm.ModuleName, &tmLightClientModule)

smLightClientModule := solomachine.NewLightClientModule(appCodec)
clientRouter.AddRoute(solomachine.ModuleName, &smLightClientModule)

// create evidence keeper with router
evidenceKeeper := evidencekeeper.NewKeeper(
appCodec, runtime.NewKVStoreService(keys[evidencetypes.StoreKey]), app.StakingKeeper, app.SlashingKeeper, app.AccountKeeper.AddressCodec(), runtime.ProvideCometInfoService(),
Expand Down Expand Up @@ -611,8 +619,8 @@ func NewSimApp(
transfer.NewAppModule(app.TransferKeeper),
ibcfee.NewAppModule(app.IBCFeeKeeper),
ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper),
ibctm.NewAppModule(),
solomachine.NewAppModule(),
ibctm.NewAppModule(tmLightClientModule),
colin-axner marked this conversation as resolved.
Show resolved Hide resolved
solomachine.NewAppModule(smLightClientModule),
mockModule,
)

Expand Down
2 changes: 1 addition & 1 deletion modules/core/02-client/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

// update the localhost client with the latest block height if it is active.
if clientState, found := k.GetClientState(ctx, exported.Localhost); found {
if k.GetClientStatus(ctx, clientState, exported.Localhost) == exported.Active {
if k.GetClientStatus(ctx, exported.LocalhostClientID) == exported.Active {
Dismissed Show dismissed Hide dismissed
k.UpdateLocalhostClient(ctx, clientState)
}
}
Expand Down
117 changes: 62 additions & 55 deletions modules/core/02-client/keeper/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,106 +9,113 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors"
"github.com/cosmos/ibc-go/v8/modules/core/exported"
)

// CreateClient generates a new client identifier and isolated prefix store for the provided client state.
// The client state is responsible for setting any client-specific data in the store via the Initialize method.
// This includes the client state, initial consensus state and any associated metadata.
colin-axner marked this conversation as resolved.
Show resolved Hide resolved
func (k Keeper) CreateClient(
ctx sdk.Context, clientState exported.ClientState, consensusState exported.ConsensusState,
ctx sdk.Context, clientType string, clientState []byte, consensusState []byte,
) (string, error) {
if clientState.ClientType() == exported.Localhost {
return "", errorsmod.Wrapf(types.ErrInvalidClientType, "cannot create client of type: %s", clientState.ClientType())
if clientType == exported.Localhost {
return "", errorsmod.Wrapf(types.ErrInvalidClientType, "cannot create client of type: %s", clientType)
}

params := k.GetParams(ctx)
if !params.IsAllowedClient(clientState.ClientType()) {
if !params.IsAllowedClient(clientType) {
return "", errorsmod.Wrapf(
types.ErrInvalidClientType,
"client state type %s is not registered in the allowlist", clientState.ClientType(),
"client state type %s is not registered in the allowlist", clientType,
)
}

clientID := k.GenerateClientIdentifier(ctx, clientState.ClientType())
clientStore := k.ClientStore(ctx, clientID)
clientID := k.GenerateClientIdentifier(ctx, clientType)

clientModule, found := k.router.GetRoute(clientID)
if !found {
return "", errorsmod.Wrap(types.ErrRouteNotFound, clientID)
}

if err := clientState.Initialize(ctx, k.cdc, clientStore, consensusState); err != nil {
if err := clientModule.Initialize(ctx, clientID, clientState, consensusState); err != nil {
return "", err
}

if status := k.GetClientStatus(ctx, clientState, clientID); status != exported.Active {
if status := k.GetClientStatus(ctx, clientID); status != exported.Active {
return "", errorsmod.Wrapf(types.ErrClientNotActive, "cannot create client (%s) with status %s", clientID, status)
}

k.Logger(ctx).Info("client created at height", "client-id", clientID, "height", clientState.GetLatestHeight().String())
initialHeight := clientModule.LatestHeight(ctx, clientID)
k.Logger(ctx).Info("client created at height", "client-id", clientID, "height", initialHeight.String())

defer telemetry.IncrCounterWithLabels(
[]string{"ibc", "client", "create"},
1,
[]metrics.Label{telemetry.NewLabel(types.LabelClientType, clientState.ClientType())},
[]metrics.Label{telemetry.NewLabel(types.LabelClientType, clientType)},
)

emitCreateClientEvent(ctx, clientID, clientState)
emitCreateClientEvent(ctx, clientID, clientType, initialHeight)
damiannolan marked this conversation as resolved.
Show resolved Hide resolved

return clientID, nil
}

// UpdateClient updates the consensus state and the state root from a provided header.
func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) error {
clientState, found := k.GetClientState(ctx, clientID)
if !found {
return errorsmod.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", clientID)
if status := k.GetClientStatus(ctx, clientID); status != exported.Active {
return errorsmod.Wrapf(types.ErrClientNotActive, "cannot update client (%s) with status %s", clientID, status)
}

clientStore := k.ClientStore(ctx, clientID)
clientType, _, err := types.ParseClientIdentifier(clientID)
if err != nil {
return errorsmod.Wrapf(types.ErrClientNotFound, "clientID (%s)", clientID)
colin-axner marked this conversation as resolved.
Show resolved Hide resolved
}

if status := k.GetClientStatus(ctx, clientState, clientID); status != exported.Active {
return errorsmod.Wrapf(types.ErrClientNotActive, "cannot update client (%s) with status %s", clientID, status)
clientModule, found := k.router.GetRoute(clientID)
if !found {
return errorsmod.Wrap(types.ErrRouteNotFound, clientID)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

client ID is parsed 3 times here, I think there should be something that we can do to reduce it even a little

e.g. Status can be called on the clientModule and doesn't need this keeper helper, which should be used by 03-connection for example

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, doesn't this helper function check the params list?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emission of the client type in events and for telemetry is unnecessary in my opinion since it is contained in the client identifier. I think the issue I see is that the client type is in the identifier, but is not easily accessible. This is fixed potentially by making the client identifier a struct or removing unnecessary usage of the client type

}

if err := clientState.VerifyClientMessage(ctx, k.cdc, clientStore, clientMsg); err != nil {
if err := clientModule.VerifyClientMessage(ctx, clientID, clientMsg); err != nil {
return err
}

foundMisbehaviour := clientState.CheckForMisbehaviour(ctx, k.cdc, clientStore, clientMsg)
foundMisbehaviour := clientModule.CheckForMisbehaviour(ctx, clientID, clientMsg)
if foundMisbehaviour {
clientState.UpdateStateOnMisbehaviour(ctx, k.cdc, clientStore, clientMsg)
clientModule.UpdateStateOnMisbehaviour(ctx, clientID, clientMsg)

k.Logger(ctx).Info("client frozen due to misbehaviour", "client-id", clientID)

defer telemetry.IncrCounterWithLabels(
[]string{"ibc", "client", "misbehaviour"},
1,
[]metrics.Label{
telemetry.NewLabel(types.LabelClientType, clientState.ClientType()),
telemetry.NewLabel(types.LabelClientType, clientType),
telemetry.NewLabel(types.LabelClientID, clientID),
telemetry.NewLabel(types.LabelMsgType, "update"),
},
)

emitSubmitMisbehaviourEvent(ctx, clientID, clientState)
emitSubmitMisbehaviourEvent(ctx, clientID, clientType)

return nil
}

consensusHeights := clientState.UpdateState(ctx, k.cdc, clientStore, clientMsg)
consensusHeights := clientModule.UpdateState(ctx, clientID, clientMsg)

k.Logger(ctx).Info("client state updated", "client-id", clientID, "heights", consensusHeights)

defer telemetry.IncrCounterWithLabels(
[]string{"ibc", "client", "update"},
1,
[]metrics.Label{
telemetry.NewLabel(types.LabelClientType, clientState.ClientType()),
telemetry.NewLabel(types.LabelClientType, clientType),
telemetry.NewLabel(types.LabelClientID, clientID),
telemetry.NewLabel(types.LabelUpdateType, "msg"),
},
)

// emitting events in the keeper emits for both begin block and handler client updates
emitUpdateClientEvent(ctx, clientID, clientState.ClientType(), consensusHeights, k.cdc, clientMsg)
emitUpdateClientEvent(ctx, clientID, clientType, consensusHeights, k.cdc, clientMsg)

return nil
}
Expand All @@ -125,25 +132,27 @@ func (k Keeper) UpgradeClient(ctx sdk.Context, clientID string, upgradedClient e

clientStore := k.ClientStore(ctx, clientID)

if status := k.GetClientStatus(ctx, clientState, clientID); status != exported.Active {
if status := k.GetClientStatus(ctx, clientID); status != exported.Active {
return errorsmod.Wrapf(types.ErrClientNotActive, "cannot upgrade client (%s) with status %s", clientID, status)
}

// TODO: This code is removed in https://github.com/cosmos/ibc-go/pull/5827
// last height of current counterparty chain must be client's latest height
lastHeight := clientState.GetLatestHeight()
// lastHeight := k.GetLatestHeight(ctx, clientID)

if !upgradedClient.GetLatestHeight().GT(lastHeight) {
return errorsmod.Wrapf(ibcerrors.ErrInvalidHeight, "upgraded client height %s must be at greater than current client height %s",
upgradedClient.GetLatestHeight(), lastHeight)
}
// if !upgradedClient.GetLatestHeight().GT(lastHeight) {
// return errorsmod.Wrapf(ibcerrors.ErrInvalidHeight, "upgraded client height %s must be at greater than current client height %s",
// upgradedClient.GetLatestHeight(), lastHeight)
// }

if err := clientState.VerifyUpgradeAndUpdateState(ctx, k.cdc, clientStore,
upgradedClient, upgradedConsState, upgradeClientProof, upgradeConsensusStateProof,
); err != nil {
return errorsmod.Wrapf(err, "cannot upgrade client with ID %s", clientID)
}

k.Logger(ctx).Info("client state upgraded", "client-id", clientID, "height", upgradedClient.GetLatestHeight().String())
latestHeight := k.GetLatestHeight(ctx, clientID) // TODO: use clientModule when addressing this func in https://github.com/cosmos/ibc-go/pull/5827
k.Logger(ctx).Info("client state upgraded", "client-id", clientID, "height", latestHeight.String())

defer telemetry.IncrCounterWithLabels(
[]string{"ibc", "client", "upgrade"},
Expand All @@ -154,7 +163,7 @@ func (k Keeper) UpgradeClient(ctx sdk.Context, clientID string, upgradedClient e
},
)

emitUpgradeClientEvent(ctx, clientID, upgradedClient)
emitUpgradeClientEvent(ctx, clientID, upgradedClient.ClientType(), latestHeight)

return nil
}
Expand All @@ -167,34 +176,32 @@ func (k Keeper) UpgradeClient(ctx sdk.Context, clientID string, upgradedClient e
// the necessary consensus states from the substitute to the subject client
// store. The substitute must be Active and the subject must not be Active.
func (k Keeper) RecoverClient(ctx sdk.Context, subjectClientID, substituteClientID string) error {
subjectClientState, found := k.GetClientState(ctx, subjectClientID)
if !found {
return errorsmod.Wrapf(types.ErrClientNotFound, "subject client with ID %s", subjectClientID)
}

subjectClientStore := k.ClientStore(ctx, subjectClientID)

if status := k.GetClientStatus(ctx, subjectClientState, subjectClientID); status == exported.Active {
if status := k.GetClientStatus(ctx, subjectClientID); status == exported.Active {
return errorsmod.Wrapf(types.ErrInvalidRecoveryClient, "cannot recover %s subject client", exported.Active)
}

substituteClientState, found := k.GetClientState(ctx, substituteClientID)
if !found {
return errorsmod.Wrapf(types.ErrClientNotFound, "substitute client with ID %s", substituteClientID)
if status := k.GetClientStatus(ctx, substituteClientID); status != exported.Active {
return errorsmod.Wrapf(types.ErrClientNotActive, "substitute client is not %s, status is %s", exported.Active, status)
}

if subjectClientState.GetLatestHeight().GTE(substituteClientState.GetLatestHeight()) {
return errorsmod.Wrapf(types.ErrInvalidHeight, "subject client state latest height is greater or equal to substitute client state latest height (%s >= %s)", subjectClientState.GetLatestHeight(), substituteClientState.GetLatestHeight())
clientType, _, err := types.ParseClientIdentifier(subjectClientID)
if err != nil {
return errorsmod.Wrapf(types.ErrClientNotFound, "clientID (%s)", subjectClientID)
}

substituteClientStore := k.ClientStore(ctx, substituteClientID)
clientModule, found := k.router.GetRoute(subjectClientID)
if !found {
return errorsmod.Wrap(types.ErrRouteNotFound, subjectClientID)
}

if status := k.GetClientStatus(ctx, substituteClientState, substituteClientID); status != exported.Active {
return errorsmod.Wrapf(types.ErrClientNotActive, "substitute client is not %s, status is %s", exported.Active, status)
subjectLatestHeight := clientModule.LatestHeight(ctx, subjectClientID)
substituteLatestHeight := clientModule.LatestHeight(ctx, substituteClientID)
if subjectLatestHeight.GTE(substituteLatestHeight) {
return errorsmod.Wrapf(types.ErrInvalidHeight, "subject client state latest height is greater or equal to substitute client state latest height (%s >= %s)", subjectLatestHeight, substituteLatestHeight)
}

if err := subjectClientState.CheckSubstituteAndUpdateState(ctx, k.cdc, subjectClientStore, substituteClientStore, substituteClientState); err != nil {
return errorsmod.Wrap(err, "failed to validate substitute client")
if err := clientModule.RecoverClient(ctx, subjectClientID, substituteClientID); err != nil {
return err
}

k.Logger(ctx).Info("client recovered", "client-id", subjectClientID)
Expand All @@ -203,14 +210,14 @@ func (k Keeper) RecoverClient(ctx sdk.Context, subjectClientID, substituteClient
[]string{"ibc", "client", "update"},
1,
[]metrics.Label{
telemetry.NewLabel(types.LabelClientType, substituteClientState.ClientType()),
telemetry.NewLabel(types.LabelClientType, clientType),
telemetry.NewLabel(types.LabelClientID, subjectClientID),
telemetry.NewLabel(types.LabelUpdateType, "recovery"),
},
)

// emitting events in the keeper for recovering clients
emitRecoverClientEvent(ctx, subjectClientID, substituteClientState.ClientType())
emitRecoverClientEvent(ctx, subjectClientID, clientType)

return nil
}
Loading
Loading