Skip to content

Commit e069d1e

Browse files
colin-axnerseunlanlege
authored andcommitted
Replace CheckHeaderAndUpdateState with new ClientState functions (cosmos#1208)
* refactor: replace CheckHeaderAndUpdateState with VerifyClientMessage, CheckForMisbehaviour, UpdateStateOnMisbehaviour, and UpdateState * add changelog entry * fix tests
1 parent c95a74a commit e069d1e

File tree

9 files changed

+60
-107
lines changed

9 files changed

+60
-107
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

Lines changed: 16 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
11
package keeper
22

33
import (
4-
"encoding/hex"
5-
"fmt"
6-
"strconv"
7-
"strings"
8-
9-
"github.com/cosmos/cosmos-sdk/codec"
104
sdk "github.com/cosmos/cosmos-sdk/types"
11-
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
125

13-
"github.com/cosmos/ibc-go/v5/modules/core/02-client/types"
14-
"github.com/cosmos/ibc-go/v5/modules/core/exported"
6+
"github.com/cosmos/ibc-go/v3/modules/core/02-client/types"
7+
"github.com/cosmos/ibc-go/v3/modules/core/exported"
158
)
169

1710
// EmitCreateClientEvent emits a create client event
@@ -31,31 +24,13 @@ func EmitCreateClientEvent(ctx sdk.Context, clientID string, clientState exporte
3124
}
3225

3326
// EmitUpdateClientEvent emits an update client event
34-
func EmitUpdateClientEvent(ctx sdk.Context, clientID string, clientType string, consensusHeights []exported.Height, cdc codec.BinaryCodec, clientMsg exported.ClientMessage) {
35-
// Marshal the ClientMessage as an Any and encode the resulting bytes to hex.
36-
// This prevents the event value from containing invalid UTF-8 characters
37-
// which may cause data to be lost when JSON encoding/decoding.
38-
clientMsgStr := hex.EncodeToString(types.MustMarshalClientMessage(cdc, clientMsg))
39-
40-
var consensusHeightAttr string
41-
if len(consensusHeights) != 0 {
42-
consensusHeightAttr = consensusHeights[0].String()
43-
}
44-
45-
consensusHeightsAttr := make([]string, len(consensusHeights))
46-
for i, height := range consensusHeights {
47-
consensusHeightsAttr[i] = height.String()
48-
}
49-
27+
func EmitUpdateClientEvent(ctx sdk.Context, clientID string, clientType string, consensusHeight exported.Height, clientMsgStr string) {
5028
ctx.EventManager().EmitEvents(sdk.Events{
5129
sdk.NewEvent(
5230
types.EventTypeUpdateClient,
5331
sdk.NewAttribute(types.AttributeKeyClientID, clientID),
5432
sdk.NewAttribute(types.AttributeKeyClientType, clientType),
55-
// Deprecated: AttributeKeyConsensusHeight is deprecated and will be removed in a future release.
56-
// Please use AttributeKeyConsensusHeights instead.
57-
sdk.NewAttribute(types.AttributeKeyConsensusHeight, consensusHeightAttr),
58-
sdk.NewAttribute(types.AttributeKeyConsensusHeights, strings.Join(consensusHeightsAttr, ",")),
33+
sdk.NewAttribute(types.AttributeKeyConsensusHeight, consensusHeight.String()),
5934
sdk.NewAttribute(types.AttributeKeyHeader, clientMsgStr),
6035
),
6136
sdk.NewEvent(
@@ -82,23 +57,13 @@ func EmitUpgradeClientEvent(ctx sdk.Context, clientID string, clientState export
8257
}
8358

8459
// EmitUpdateClientProposalEvent emits an update client proposal event
85-
func EmitUpdateClientProposalEvent(ctx sdk.Context, clientID, clientType string) {
60+
func EmitUpdateClientProposalEvent(ctx sdk.Context, clientID string, clientState exported.ClientState) {
8661
ctx.EventManager().EmitEvent(
8762
sdk.NewEvent(
8863
types.EventTypeUpdateClientProposal,
8964
sdk.NewAttribute(types.AttributeKeySubjectClientID, clientID),
90-
sdk.NewAttribute(types.AttributeKeyClientType, clientType),
91-
),
92-
)
93-
}
94-
95-
// EmitUpgradeClientProposalEvent emits an upgrade client proposal event
96-
func EmitUpgradeClientProposalEvent(ctx sdk.Context, title string, height int64) {
97-
ctx.EventManager().EmitEvent(
98-
sdk.NewEvent(
99-
types.EventTypeUpgradeClientProposal,
100-
sdk.NewAttribute(types.AttributeKeyUpgradePlanTitle, title),
101-
sdk.NewAttribute(types.AttributeKeyUpgradePlanHeight, fmt.Sprintf("%d", height)),
65+
sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()),
66+
sdk.NewAttribute(types.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()),
10267
),
10368
)
10469
}
@@ -114,13 +79,15 @@ func EmitSubmitMisbehaviourEvent(ctx sdk.Context, clientID string, clientState e
11479
)
11580
}
11681

117-
// EmitUpgradeChainEvent emits an upgrade chain event.
118-
func EmitUpgradeChainEvent(ctx sdk.Context, height int64) {
119-
ctx.EventManager().EmitEvents(sdk.Events{
82+
// EmitSubmitMisbehaviourEventOnUpdate emits a client misbehaviour event on a client update event
83+
func EmitSubmitMisbehaviourEventOnUpdate(ctx sdk.Context, clientID string, clientType string, consensusHeight exported.Height, headerStr string) {
84+
ctx.EventManager().EmitEvent(
12085
sdk.NewEvent(
121-
types.EventTypeUpgradeChain,
122-
sdk.NewAttribute(types.AttributeKeyUpgradePlanHeight, strconv.FormatInt(height, 10)),
123-
sdk.NewAttribute(types.AttributeKeyUpgradeStore, upgradetypes.StoreKey), // which store to query proof of consensus state from
86+
types.EventTypeSubmitMisbehaviour,
87+
sdk.NewAttribute(types.AttributeKeyClientID, clientID),
88+
sdk.NewAttribute(types.AttributeKeyClientType, clientType),
89+
sdk.NewAttribute(types.AttributeKeyConsensusHeight, consensusHeight.String()),
90+
sdk.NewAttribute(types.AttributeKeyHeader, headerStr),
12491
),
125-
})
92+
)
12693
}

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)