Skip to content

Commit e2f37b8

Browse files
authored
Replace CheckHeaderAndUpdateState with new ClientState functions (#1208)
* refactor: replace CheckHeaderAndUpdateState with VerifyClientMessage, CheckForMisbehaviour, UpdateStateOnMisbehaviour, and UpdateState * add changelog entry * fix tests
1 parent d2be6d5 commit e2f37b8

File tree

9 files changed

+49
-63
lines changed

9 files changed

+49
-63
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
4343
### State Machine Breaking
4444

4545
### Improvements
46+
47+
* (02-client) [\#1208](https://github.com/cosmos/ibc-go/pull/1208) Replace `CheckHeaderAndUpdateState` usage in 02-client with calls to `VerifyClientMessage`, `CheckForMisbehaviour`, `UpdateStateOnMisbehaviour` and `UpdateState`.
4648
* (modules/light-clients/09-localhost) [\#1187](https://github.com/cosmos/ibc-go/pull/1187/) Removing localhost light client implementation as it is not functional.
4749
* [\#1186](https://github.com/cosmos/ibc-go/pull/1186/files) Removing `GetRoot` function from ConsensusState interface in `02-client`. `GetRoot` is unused by core IBC.
4850
* (modules/core/02-client) [\#1196](https://github.com/cosmos/ibc-go/pull/1196) Adding VerifyClientMessage to ClientState interface.

modules/core/02-client/keeper/client.go

Lines changed: 34 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func (k Keeper) CreateClient(
5454
}
5555

5656
// UpdateClient updates the consensus state and the state root from a provided header.
57-
func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.ClientMessage) error {
57+
func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, clientMsg exported.ClientMessage) error {
5858
clientState, found := k.GetClientState(ctx, clientID)
5959
if !found {
6060
return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", clientID)
@@ -66,54 +66,21 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.C
6666
return sdkerrors.Wrapf(types.ErrClientNotActive, "cannot update client (%s) with status %s", clientID, status)
6767
}
6868

69-
// Any writes made in CheckHeaderAndUpdateState are persisted on both valid updates and misbehaviour updates.
70-
// Light client implementations are responsible for writing the correct metadata (if any) in either case.
71-
newClientState, newConsensusState, err := clientState.CheckHeaderAndUpdateState(ctx, k.cdc, clientStore, header)
72-
if err != nil {
73-
return sdkerrors.Wrapf(err, "cannot update client with ID %s", clientID)
74-
}
75-
76-
// emit the full header in events
77-
var (
78-
headerStr string
79-
consensusHeight exported.Height
80-
)
81-
if header != nil {
82-
// Marshal the Header as an Any and encode the resulting bytes to hex.
83-
// This prevents the event value from containing invalid UTF-8 characters
84-
// which may cause data to be lost when JSON encoding/decoding.
85-
headerStr = hex.EncodeToString(types.MustMarshalClientMessage(k.cdc, header))
86-
// set default consensus height with header height
87-
consensusHeight = header.GetHeight()
88-
69+
if err := clientState.VerifyClientMessage(ctx, k.cdc, clientStore, clientMsg); err != nil {
70+
return err
8971
}
9072

91-
// set new client state regardless of if update is valid update or misbehaviour
92-
k.SetClientState(ctx, clientID, newClientState)
93-
// If client state is not frozen after clientState CheckHeaderAndUpdateState,
94-
// then update was valid. Write the update state changes, and set new consensus state.
95-
// Else the update was proof of misbehaviour and we must emit appropriate misbehaviour events.
96-
if status := newClientState.Status(ctx, clientStore, k.cdc); status != exported.Frozen {
97-
// if update is not misbehaviour then update the consensus state
98-
k.SetClientConsensusState(ctx, clientID, header.GetHeight(), newConsensusState)
99-
100-
k.Logger(ctx).Info("client state updated", "client-id", clientID, "height", consensusHeight.String())
73+
// Marshal the ClientMessage as an Any and encode the resulting bytes to hex.
74+
// This prevents the event value from containing invalid UTF-8 characters
75+
// which may cause data to be lost when JSON encoding/decoding.
76+
clientMsgStr := hex.EncodeToString(types.MustMarshalClientMessage(k.cdc, clientMsg))
10177

102-
defer func() {
103-
telemetry.IncrCounterWithLabels(
104-
[]string{"ibc", "client", "update"},
105-
1,
106-
[]metrics.Label{
107-
telemetry.NewLabel(types.LabelClientType, clientState.ClientType()),
108-
telemetry.NewLabel(types.LabelClientID, clientID),
109-
telemetry.NewLabel(types.LabelUpdateType, "msg"),
110-
},
111-
)
112-
}()
78+
// set default consensus height with header height
79+
consensusHeight := clientMsg.GetHeight()
11380

114-
// emitting events in the keeper emits for both begin block and handler client updates
115-
EmitUpdateClientEvent(ctx, clientID, newClientState, consensusHeight, headerStr)
116-
} else {
81+
foundMisbehaviour := clientState.CheckForMisbehaviour(ctx, k.cdc, clientStore, clientMsg)
82+
if foundMisbehaviour {
83+
clientState.UpdateStateOnMisbehaviour(ctx, k.cdc, clientStore, clientMsg)
11784

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

@@ -129,9 +96,30 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.C
12996
)
13097
}()
13198

132-
EmitSubmitMisbehaviourEventOnUpdate(ctx, clientID, newClientState, consensusHeight, headerStr)
99+
EmitSubmitMisbehaviourEventOnUpdate(ctx, clientID, clientState.ClientType(), consensusHeight, clientMsgStr)
100+
101+
return nil
133102
}
134103

104+
clientState.UpdateState(ctx, k.cdc, clientStore, clientMsg)
105+
106+
k.Logger(ctx).Info("client state updated", "client-id", clientID, "height", consensusHeight.String())
107+
108+
defer func() {
109+
telemetry.IncrCounterWithLabels(
110+
[]string{"ibc", "client", "update"},
111+
1,
112+
[]metrics.Label{
113+
telemetry.NewLabel(types.LabelClientType, clientState.ClientType()),
114+
telemetry.NewLabel(types.LabelClientID, clientID),
115+
telemetry.NewLabel(types.LabelUpdateType, "msg"),
116+
},
117+
)
118+
}()
119+
120+
// emitting events in the keeper emits for both begin block and handler client updates
121+
EmitUpdateClientEvent(ctx, clientID, clientState.ClientType(), consensusHeight, clientMsgStr)
122+
135123
return nil
136124
}
137125

modules/core/02-client/keeper/events.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ func EmitCreateClientEvent(ctx sdk.Context, clientID string, clientState exporte
2424
}
2525

2626
// EmitUpdateClientEvent emits an update client event
27-
func EmitUpdateClientEvent(ctx sdk.Context, clientID string, clientState exported.ClientState, consensusHeight exported.Height, headerStr string) {
27+
func EmitUpdateClientEvent(ctx sdk.Context, clientID string, clientType string, consensusHeight exported.Height, clientMsgStr string) {
2828
ctx.EventManager().EmitEvents(sdk.Events{
2929
sdk.NewEvent(
3030
types.EventTypeUpdateClient,
3131
sdk.NewAttribute(types.AttributeKeyClientID, clientID),
32-
sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()),
32+
sdk.NewAttribute(types.AttributeKeyClientType, clientType),
3333
sdk.NewAttribute(types.AttributeKeyConsensusHeight, consensusHeight.String()),
34-
sdk.NewAttribute(types.AttributeKeyHeader, headerStr),
34+
sdk.NewAttribute(types.AttributeKeyHeader, clientMsgStr),
3535
),
3636
sdk.NewEvent(
3737
sdk.EventTypeMessage,
@@ -80,12 +80,12 @@ func EmitSubmitMisbehaviourEvent(ctx sdk.Context, clientID string, clientState e
8080
}
8181

8282
// EmitSubmitMisbehaviourEventOnUpdate emits a client misbehaviour event on a client update event
83-
func EmitSubmitMisbehaviourEventOnUpdate(ctx sdk.Context, clientID string, clientState exported.ClientState, consensusHeight exported.Height, headerStr string) {
83+
func EmitSubmitMisbehaviourEventOnUpdate(ctx sdk.Context, clientID string, clientType string, consensusHeight exported.Height, headerStr string) {
8484
ctx.EventManager().EmitEvent(
8585
sdk.NewEvent(
8686
types.EventTypeSubmitMisbehaviour,
8787
sdk.NewAttribute(types.AttributeKeyClientID, clientID),
88-
sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()),
88+
sdk.NewAttribute(types.AttributeKeyClientType, clientType),
8989
sdk.NewAttribute(types.AttributeKeyConsensusHeight, consensusHeight.String()),
9090
sdk.NewAttribute(types.AttributeKeyHeader, headerStr),
9191
),

modules/core/02-client/legacy/v100/solomachine.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func (cs ClientState) CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCode
9595

9696
// UpdateStateOnMisbehaviour panics!
9797
func (cs *ClientState) UpdateStateOnMisbehaviour(
98-
_ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore,
98+
_ sdk.Context, _ codec.BinaryCodec, _ sdk.KVStore, _ exported.ClientMessage,
9999
) {
100100
panic("legacy solo machine is deprecated!")
101101
}

modules/core/exported/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ type ClientState interface {
5656
ExportMetadata(sdk.KVStore) []GenesisMetadata
5757

5858
// UpdateStateOnMisbehaviour should perform appropriate state changes on a client state given that misbehaviour has been detected and verified
59-
UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore)
59+
UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage)
6060

6161
// VerifyClientMessage verifies a ClientMessage. A ClientMessage could be a Header, Misbehaviour, or batch update.
6262
VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg ClientMessage) error
6363

64-
// UpdateState updates and stores as necessary any associated information for an IBC client, such as the ClientState and corresponding ConsensusState.
64+
// UpdateState updates and stores as necessary any associated information for an IBC client, such as the ClientState and corresponding ConsensusState.
6565
// An error is returned if ClientMessage is of type Misbehaviour
6666
UpdateState(sdk.Context, codec.BinaryCodec, sdk.KVStore, ClientMessage) error
6767

modules/light-clients/06-solomachine/types/update.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func (cs ClientState) CheckHeaderAndUpdateState(
2626

2727
foundMisbehaviour := cs.CheckForMisbehaviour(ctx, cdc, clientStore, msg)
2828
if foundMisbehaviour {
29-
cs.UpdateStateOnMisbehaviour(ctx, cdc, clientStore)
29+
cs.UpdateStateOnMisbehaviour(ctx, cdc, clientStore, msg)
3030
return &cs, cs.ConsensusState, nil
3131
}
3232

@@ -142,7 +142,7 @@ func (cs ClientState) CheckForMisbehaviour(_ sdk.Context, _ codec.BinaryCodec, _
142142

143143
// UpdateStateOnMisbehaviour updates state upon misbehaviour. This method should only be called on misbehaviour
144144
// as it does not perform any misbehaviour checks.
145-
func (cs ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore) {
145+
func (cs ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, _ exported.ClientMessage) {
146146
cs.IsFrozen = true
147147

148148
clientStore.Set(host.ClientStateKey(), clienttypes.MustMarshalClientState(cdc, &cs))

modules/light-clients/06-solomachine/types/update_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ func (suite *SoloMachineTestSuite) TestUpdateStateOnMisbehaviour() {
708708

709709
tc.malleate()
710710

711-
clientState.UpdateStateOnMisbehaviour(suite.chainA.GetContext(), suite.chainA.Codec, suite.store)
711+
clientState.UpdateStateOnMisbehaviour(suite.chainA.GetContext(), suite.chainA.Codec, suite.store, nil)
712712

713713
if tc.expPass {
714714
clientStateBz := suite.store.Get(host.ClientStateKey())

modules/light-clients/07-tendermint/types/update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ func (cs ClientState) CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCode
358358

359359
// UpdateStateOnMisbehaviour updates state upon misbehaviour, freezing the ClientState. This method should only be called when misbehaviour is detected
360360
// as it does not perform any misbehaviour checks.
361-
func (cs ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore) {
361+
func (cs ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, _ exported.ClientMessage) {
362362
cs.FrozenHeight = FrozenHeight
363363

364364
clientStore.Set(host.ClientStateKey(), clienttypes.MustMarshalClientState(cdc, &cs))

modules/light-clients/07-tendermint/types/update_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -792,11 +792,7 @@ func (suite *TendermintTestSuite) TestUpdateStateOnMisbehaviour() {
792792
clientState := path.EndpointA.GetClientState()
793793
clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), path.EndpointA.ClientID)
794794

795-
// TODO: remove casting when 'UpdateState' is an interface function.
796-
tmClientState, ok := clientState.(*types.ClientState)
797-
suite.Require().True(ok)
798-
799-
tmClientState.UpdateStateOnMisbehaviour(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore)
795+
clientState.UpdateStateOnMisbehaviour(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, nil)
800796

801797
if tc.expPass {
802798
clientStateBz := clientStore.Get(host.ClientStateKey())

0 commit comments

Comments
 (0)