@@ -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"
@@ -29,21 +24,23 @@ import (
29
24
// Keeper represents a type that grants read and write permissions to any client
30
25
// state information
31
26
type Keeper struct {
32
- storeKey storetypes.StoreKey
33
- cdc codec.BinaryCodec
34
- legacySubspace types.ParamSubspace
35
- stakingKeeper types.StakingKeeper
36
- upgradeKeeper types.UpgradeKeeper
27
+ storeKey storetypes.StoreKey
28
+ cdc codec.BinaryCodec
29
+ legacySubspace types.ParamSubspace
30
+ selfClientValidator types.SelfClientValidator
31
+ stakingKeeper types.StakingKeeper
32
+ upgradeKeeper types.UpgradeKeeper
37
33
}
38
34
39
35
// NewKeeper creates a new NewKeeper instance
40
36
func NewKeeper (cdc codec.BinaryCodec , key storetypes.StoreKey , legacySubspace types.ParamSubspace , sk types.StakingKeeper , uk types.UpgradeKeeper ) Keeper {
41
37
return Keeper {
42
- storeKey : key ,
43
- cdc : cdc ,
44
- legacySubspace : legacySubspace ,
45
- stakingKeeper : sk ,
46
- upgradeKeeper : uk ,
38
+ storeKey : key ,
39
+ cdc : cdc ,
40
+ legacySubspace : legacySubspace ,
41
+ selfClientValidator : NewTendermintClientValidator (sk ),
42
+ stakingKeeper : sk ,
43
+ upgradeKeeper : uk ,
47
44
}
48
45
}
49
46
@@ -63,6 +60,15 @@ func (k Keeper) UpdateLocalhostClient(ctx sdk.Context, clientState exported.Clie
63
60
return clientState .UpdateState (ctx , k .cdc , k .ClientStore (ctx , exported .LocalhostClientID ), nil )
64
61
}
65
62
63
+ // SetSelfClientValidator sets a custom self client validation function.
64
+ func (k * Keeper ) SetSelfClientValidator (selfClientValidator types.SelfClientValidator ) {
65
+ if selfClientValidator == nil {
66
+ panic (fmt .Errorf ("cannot set a nil self client validator" ))
67
+ }
68
+
69
+ k .selfClientValidator = selfClientValidator
70
+ }
71
+
66
72
// GenerateClientIdentifier returns the next client identifier.
67
73
func (k Keeper ) GenerateClientIdentifier (ctx sdk.Context , clientType string ) string {
68
74
nextClientSeq := k .GetNextClientSequence (ctx )
@@ -282,96 +288,15 @@ func (k Keeper) GetLatestClientConsensusState(ctx sdk.Context, clientID string)
282
288
// and returns the expected consensus state at that height.
283
289
// For now, can only retrieve self consensus states for the current revision
284
290
func (k Keeper ) GetSelfConsensusState (ctx sdk.Context , height exported.Height ) (exported.ConsensusState , error ) {
285
- selfHeight , ok := height .(types.Height )
286
- if ! ok {
287
- return nil , errorsmod .Wrapf (ibcerrors .ErrInvalidType , "expected %T, got %T" , types.Height {}, height )
288
- }
289
- // check that height revision matches chainID revision
290
- revision := types .ParseChainID (ctx .ChainID ())
291
- if revision != height .GetRevisionNumber () {
292
- return nil , errorsmod .Wrapf (types .ErrInvalidHeight , "chainID revision number does not match height revision number: expected %d, got %d" , revision , height .GetRevisionNumber ())
293
- }
294
- histInfo , err := k .stakingKeeper .GetHistoricalInfo (ctx , int64 (selfHeight .RevisionHeight ))
295
- if err != nil {
296
- return nil , errorsmod .Wrapf (err , "height %d" , selfHeight .RevisionHeight )
297
- }
298
-
299
- consensusState := & ibctm.ConsensusState {
300
- Timestamp : histInfo .Header .Time ,
301
- Root : commitmenttypes .NewMerkleRoot (histInfo .Header .GetAppHash ()),
302
- NextValidatorsHash : histInfo .Header .NextValidatorsHash ,
303
- }
304
-
305
- return consensusState , nil
291
+ return k .selfClientValidator .GetSelfConsensusState (ctx , height )
306
292
}
307
293
308
- // ValidateSelfClient validates the client parameters for a client of the running chain
309
- // This function is only used to validate the client state the counterparty stores for this chain
310
- // Client must be in same revision as the executing chain
294
+ // ValidateSelfClient validates the client parameters for a client of the running chain.
295
+ // This function is only used to validate the client state the counterparty stores for this chain.
296
+ // NOTE: If the client type is not of type Tendermint then delegate to a custom client validator function.
297
+ // This allows support for non-Tendermint clients, for example 08-wasm clients.
311
298
func (k Keeper ) ValidateSelfClient (ctx sdk.Context , clientState exported.ClientState ) error {
312
- tmClient , ok := clientState .(* ibctm.ClientState )
313
- if ! ok {
314
- return errorsmod .Wrapf (types .ErrInvalidClient , "client must be a Tendermint client, expected: %T, got: %T" ,
315
- & ibctm.ClientState {}, tmClient )
316
- }
317
-
318
- if ! tmClient .FrozenHeight .IsZero () {
319
- return types .ErrClientFrozen
320
- }
321
-
322
- if ctx .ChainID () != tmClient .ChainId {
323
- return errorsmod .Wrapf (types .ErrInvalidClient , "invalid chain-id. expected: %s, got: %s" ,
324
- ctx .ChainID (), tmClient .ChainId )
325
- }
326
-
327
- revision := types .ParseChainID (ctx .ChainID ())
328
-
329
- // client must be in the same revision as executing chain
330
- if tmClient .LatestHeight .RevisionNumber != revision {
331
- return errorsmod .Wrapf (types .ErrInvalidClient , "client is not in the same revision as the chain. expected revision: %d, got: %d" ,
332
- tmClient .LatestHeight .RevisionNumber , revision )
333
- }
334
-
335
- selfHeight := types .NewHeight (revision , uint64 (ctx .BlockHeight ()))
336
- if tmClient .LatestHeight .GTE (selfHeight ) {
337
- return errorsmod .Wrapf (types .ErrInvalidClient , "client has LatestHeight %d greater than or equal to chain height %d" ,
338
- tmClient .LatestHeight , selfHeight )
339
- }
340
-
341
- expectedProofSpecs := commitmenttypes .GetSDKSpecs ()
342
- if ! reflect .DeepEqual (expectedProofSpecs , tmClient .ProofSpecs ) {
343
- return errorsmod .Wrapf (types .ErrInvalidClient , "client has invalid proof specs. expected: %v got: %v" ,
344
- expectedProofSpecs , tmClient .ProofSpecs )
345
- }
346
-
347
- if err := light .ValidateTrustLevel (tmClient .TrustLevel .ToTendermint ()); err != nil {
348
- return errorsmod .Wrapf (types .ErrInvalidClient , "trust-level invalid: %v" , err )
349
- }
350
-
351
- expectedUbdPeriod , err := k .stakingKeeper .UnbondingTime (ctx )
352
- if err != nil {
353
- return errorsmod .Wrapf (err , "failed to retrieve unbonding period" )
354
- }
355
-
356
- if expectedUbdPeriod != tmClient .UnbondingPeriod {
357
- return errorsmod .Wrapf (types .ErrInvalidClient , "invalid unbonding period. expected: %s, got: %s" ,
358
- expectedUbdPeriod , tmClient .UnbondingPeriod )
359
- }
360
-
361
- if tmClient .UnbondingPeriod < tmClient .TrustingPeriod {
362
- return errorsmod .Wrapf (types .ErrInvalidClient , "unbonding period must be greater than trusting period. unbonding period (%d) < trusting period (%d)" ,
363
- tmClient .UnbondingPeriod , tmClient .TrustingPeriod )
364
- }
365
-
366
- if len (tmClient .UpgradePath ) != 0 {
367
- // For now, SDK IBC implementation assumes that upgrade path (if defined) is defined by SDK upgrade module
368
- expectedUpgradePath := []string {upgradetypes .StoreKey , upgradetypes .KeyUpgradedIBCState }
369
- if ! reflect .DeepEqual (expectedUpgradePath , tmClient .UpgradePath ) {
370
- return errorsmod .Wrapf (types .ErrInvalidClient , "upgrade path must be the upgrade path defined by upgrade module. expected %v, got %v" ,
371
- expectedUpgradePath , tmClient .UpgradePath )
372
- }
373
- }
374
- return nil
299
+ return k .selfClientValidator .ValidateSelfClient (ctx , clientState )
375
300
}
376
301
377
302
// GetUpgradePlan executes the upgrade keeper GetUpgradePlan function.
0 commit comments