@@ -3,7 +3,6 @@ package keeper
3
3
import (
4
4
"errors"
5
5
"fmt"
6
- "reflect"
7
6
"strings"
8
7
9
8
errorsmod "cosmossdk.io/errors"
@@ -15,12 +14,8 @@ import (
15
14
"github.com/cosmos/cosmos-sdk/codec"
16
15
sdk "github.com/cosmos/cosmos-sdk/types"
17
16
18
- "github.com/cometbft/cometbft/light"
19
-
20
17
"github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
21
- commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types"
22
18
host "github.com/cosmos/ibc-go/v8/modules/core/24-host"
23
- ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors"
24
19
"github.com/cosmos/ibc-go/v8/modules/core/exported"
25
20
ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint"
26
21
localhost "github.com/cosmos/ibc-go/v8/modules/light-clients/09-localhost"
@@ -32,8 +27,8 @@ type Keeper struct {
32
27
storeKey storetypes.StoreKey
33
28
cdc codec.BinaryCodec
34
29
router * types.Router
30
+ consensusHost types.ConsensusHost
35
31
legacySubspace types.ParamSubspace
36
- stakingKeeper types.StakingKeeper
37
32
upgradeKeeper types.UpgradeKeeper
38
33
}
39
34
@@ -47,8 +42,8 @@ func NewKeeper(cdc codec.BinaryCodec, key storetypes.StoreKey, legacySubspace ty
47
42
storeKey : key ,
48
43
cdc : cdc ,
49
44
router : router ,
45
+ consensusHost : ibctm .NewConsensusHost (sk ),
50
46
legacySubspace : legacySubspace ,
51
- stakingKeeper : sk ,
52
47
upgradeKeeper : uk ,
53
48
}
54
49
}
@@ -88,6 +83,15 @@ func (k Keeper) UpdateLocalhostClient(ctx sdk.Context, clientState exported.Clie
88
83
return clientModule .UpdateState (ctx , exported .LocalhostClientID , nil )
89
84
}
90
85
86
+ // SetSelfConsensusHost sets a custom ConsensusHost for self client state and consensus state validation.
87
+ func (k * Keeper ) SetSelfConsensusHost (consensusHost types.ConsensusHost ) {
88
+ if consensusHost == nil {
89
+ panic (fmt .Errorf ("cannot set a nil self consensus host" ))
90
+ }
91
+
92
+ k .consensusHost = consensusHost
93
+ }
94
+
91
95
// GenerateClientIdentifier returns the next client identifier.
92
96
func (k Keeper ) GenerateClientIdentifier (ctx sdk.Context , clientType string ) string {
93
97
nextClientSeq := k .GetNextClientSequence (ctx )
@@ -99,7 +103,7 @@ func (k Keeper) GenerateClientIdentifier(ctx sdk.Context, clientType string) str
99
103
}
100
104
101
105
// GetClientState gets a particular client from the store
102
- func (k Keeper ) GetClientState (ctx sdk.Context , clientID string ) (exported.ClientState , bool ) {
106
+ func (k * Keeper ) GetClientState (ctx sdk.Context , clientID string ) (exported.ClientState , bool ) {
103
107
store := k .ClientStore (ctx , clientID )
104
108
bz := store .Get (host .ClientStateKey ())
105
109
if len (bz ) == 0 {
@@ -111,13 +115,13 @@ func (k Keeper) GetClientState(ctx sdk.Context, clientID string) (exported.Clien
111
115
}
112
116
113
117
// SetClientState sets a particular Client to the store
114
- func (k Keeper ) SetClientState (ctx sdk.Context , clientID string , clientState exported.ClientState ) {
118
+ func (k * Keeper ) SetClientState (ctx sdk.Context , clientID string , clientState exported.ClientState ) {
115
119
store := k .ClientStore (ctx , clientID )
116
120
store .Set (host .ClientStateKey (), k .MustMarshalClientState (clientState ))
117
121
}
118
122
119
123
// GetClientConsensusState gets the stored consensus state from a client at a given height.
120
- func (k Keeper ) GetClientConsensusState (ctx sdk.Context , clientID string , height exported.Height ) (exported.ConsensusState , bool ) {
124
+ func (k * Keeper ) GetClientConsensusState (ctx sdk.Context , clientID string , height exported.Height ) (exported.ConsensusState , bool ) {
121
125
store := k .ClientStore (ctx , clientID )
122
126
bz := store .Get (host .ConsensusStateKey (height ))
123
127
if len (bz ) == 0 {
@@ -308,96 +312,15 @@ func (k Keeper) GetLatestClientConsensusState(ctx sdk.Context, clientID string)
308
312
// and returns the expected consensus state at that height.
309
313
// For now, can only retrieve self consensus states for the current revision
310
314
func (k Keeper ) GetSelfConsensusState (ctx sdk.Context , height exported.Height ) (exported.ConsensusState , error ) {
311
- selfHeight , ok := height .(types.Height )
312
- if ! ok {
313
- return nil , errorsmod .Wrapf (ibcerrors .ErrInvalidType , "expected %T, got %T" , types.Height {}, height )
314
- }
315
- // check that height revision matches chainID revision
316
- revision := types .ParseChainID (ctx .ChainID ())
317
- if revision != height .GetRevisionNumber () {
318
- return nil , errorsmod .Wrapf (types .ErrInvalidHeight , "chainID revision number does not match height revision number: expected %d, got %d" , revision , height .GetRevisionNumber ())
319
- }
320
- histInfo , err := k .stakingKeeper .GetHistoricalInfo (ctx , int64 (selfHeight .RevisionHeight ))
321
- if err != nil {
322
- return nil , errorsmod .Wrapf (err , "height %d" , selfHeight .RevisionHeight )
323
- }
324
-
325
- consensusState := & ibctm.ConsensusState {
326
- Timestamp : histInfo .Header .Time ,
327
- Root : commitmenttypes .NewMerkleRoot (histInfo .Header .GetAppHash ()),
328
- NextValidatorsHash : histInfo .Header .NextValidatorsHash ,
329
- }
330
-
331
- return consensusState , nil
315
+ return k .consensusHost .GetSelfConsensusState (ctx , height )
332
316
}
333
317
334
- // ValidateSelfClient validates the client parameters for a client of the running chain
335
- // This function is only used to validate the client state the counterparty stores for this chain
336
- // Client must be in same revision as the executing chain
318
+ // ValidateSelfClient validates the client parameters for a client of the running chain.
319
+ // This function is only used to validate the client state the counterparty stores for this chain.
320
+ // NOTE: If the client type is not of type Tendermint then delegate to a custom client validator function.
321
+ // This allows support for non-Tendermint clients, for example 08-wasm clients.
337
322
func (k Keeper ) ValidateSelfClient (ctx sdk.Context , clientState exported.ClientState ) error {
338
- tmClient , ok := clientState .(* ibctm.ClientState )
339
- if ! ok {
340
- return errorsmod .Wrapf (types .ErrInvalidClient , "client must be a Tendermint client, expected: %T, got: %T" ,
341
- & ibctm.ClientState {}, tmClient )
342
- }
343
-
344
- if ! tmClient .FrozenHeight .IsZero () {
345
- return types .ErrClientFrozen
346
- }
347
-
348
- if ctx .ChainID () != tmClient .ChainId {
349
- return errorsmod .Wrapf (types .ErrInvalidClient , "invalid chain-id. expected: %s, got: %s" ,
350
- ctx .ChainID (), tmClient .ChainId )
351
- }
352
-
353
- revision := types .ParseChainID (ctx .ChainID ())
354
-
355
- // client must be in the same revision as executing chain
356
- if tmClient .LatestHeight .RevisionNumber != revision {
357
- return errorsmod .Wrapf (types .ErrInvalidClient , "client is not in the same revision as the chain. expected revision: %d, got: %d" ,
358
- tmClient .LatestHeight .RevisionNumber , revision )
359
- }
360
-
361
- selfHeight := types .NewHeight (revision , uint64 (ctx .BlockHeight ()))
362
- if tmClient .LatestHeight .GTE (selfHeight ) {
363
- return errorsmod .Wrapf (types .ErrInvalidClient , "client has LatestHeight %d greater than or equal to chain height %d" ,
364
- tmClient .LatestHeight , selfHeight )
365
- }
366
-
367
- expectedProofSpecs := commitmenttypes .GetSDKSpecs ()
368
- if ! reflect .DeepEqual (expectedProofSpecs , tmClient .ProofSpecs ) {
369
- return errorsmod .Wrapf (types .ErrInvalidClient , "client has invalid proof specs. expected: %v got: %v" ,
370
- expectedProofSpecs , tmClient .ProofSpecs )
371
- }
372
-
373
- if err := light .ValidateTrustLevel (tmClient .TrustLevel .ToTendermint ()); err != nil {
374
- return errorsmod .Wrapf (types .ErrInvalidClient , "trust-level invalid: %v" , err )
375
- }
376
-
377
- expectedUbdPeriod , err := k .stakingKeeper .UnbondingTime (ctx )
378
- if err != nil {
379
- return errorsmod .Wrapf (err , "failed to retrieve unbonding period" )
380
- }
381
-
382
- if expectedUbdPeriod != tmClient .UnbondingPeriod {
383
- return errorsmod .Wrapf (types .ErrInvalidClient , "invalid unbonding period. expected: %s, got: %s" ,
384
- expectedUbdPeriod , tmClient .UnbondingPeriod )
385
- }
386
-
387
- if tmClient .UnbondingPeriod < tmClient .TrustingPeriod {
388
- return errorsmod .Wrapf (types .ErrInvalidClient , "unbonding period must be greater than trusting period. unbonding period (%d) < trusting period (%d)" ,
389
- tmClient .UnbondingPeriod , tmClient .TrustingPeriod )
390
- }
391
-
392
- if len (tmClient .UpgradePath ) != 0 {
393
- // For now, SDK IBC implementation assumes that upgrade path (if defined) is defined by SDK upgrade module
394
- expectedUpgradePath := []string {upgradetypes .StoreKey , upgradetypes .KeyUpgradedIBCState }
395
- if ! reflect .DeepEqual (expectedUpgradePath , tmClient .UpgradePath ) {
396
- return errorsmod .Wrapf (types .ErrInvalidClient , "upgrade path must be the upgrade path defined by upgrade module. expected %v, got %v" ,
397
- expectedUpgradePath , tmClient .UpgradePath )
398
- }
399
- }
400
- return nil
323
+ return k .consensusHost .ValidateSelfClient (ctx , clientState )
401
324
}
402
325
403
326
// GetUpgradePlan executes the upgrade keeper GetUpgradePlan function.
0 commit comments