Implement ADR 026 (#7029)

* Add allow_governance_override_after_expiry flag to tendermint NewCreateClientCmd

* 1) Add LatestTimestamp to ClientState struct by adding a new attribute latest_timestamp to the message ClientState in proto/ibc/tendermint/tendermint.proto
2) Autogenerate x/ibc/07-tendermint/types/tendermint.pb.go by running 'make proto-gen'. Strangely, as a side effect x/distribution/types/genesis.pb.go, x/evidence/types/genesis.pb.go were also modified by the command 'make proto-gen'
3) Add Expired() function

* Fix tests

* 1) Add allow_governance_override_after_expiry flag to tendemint clientStatus
2) Add allow_governance_override_after_misbehaviour flag to tendermint ClientStatus

* Cosmetic changes

* Fix tests

* Add Unfreeze function

* Add new ClientUpdateProposal type

* Add minor fixes

* Add NewClientUpdateProposalHandler unit tests

* Fix proto-lint-docker

* Delete x/ibc/07-tendermint/tendermint_test.go

* Follow convention to put signer last in msg function signature

* 1) Add GetLatestTimestamp function  to ClientStatus interface
2) Change Expired() signature to Expired(now time.Time)

* 1) Add override flag to UpdateClient function
2) Fix tests

* Refactor HandleClientUpdateProposal

* 1) Extend exported Header interface with MarshalBinaryBare and UnmarshalBinaryBare methods
2) Move ClientUpdateProposal message to from ibc.proto to client.proto
3) Refactoring code
4) Add override flag to UpdateClient method
5) Fix tests

* 1) Uncomment tests and clean up code
2) Add basic validation of the header (ValidateBasic) when the override flag is true

* Cosmetic changes

* Add TODO comments

* Fix header MarshalBinaryBare, UnmarshalBinaryBare by using protobuf encoding/decoding

* Fix proto comments

* Fix override logic

* undo gettimestamp for solo machine and localhost

* add update after proposal func, some major refactoring in progress, various issues addressed

* fix tendermint proposal update handling

* run make proto-gen

* remove timestamp from tendemint client

* fix build issue for tm types

* apply various review comments

* add tests for 02-client functionality

* self review fixes

* typo

* update tests slightly

* update tendermint proposal handling tests

* Update x/ibc/02-client/keeper/proposal.go

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/ibc/07-tendermint/types/proposal_handle.go

Co-authored-by: Aditya <adityasripal@gmail.com>

* Update x/ibc/07-tendermint/types/proposal_handle.go

Co-authored-by: Aditya <adityasripal@gmail.com>

* apply most of @fedekunze and some of @AdityaSripal suggestions

* convert test to bools

* update docs and increase code cov

* fix build

* fix typo, remove omitempty

* add switch

* apply @fedekunze latest suggestions

* fix lint

* Update x/ibc/02-client/keeper/proposal_test.go

Co-authored-by: Christopher Goes <cwgoes@pluranimity.org>
Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Colin Axner <colinaxner@berkeley.edu>
Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>
Co-authored-by: Aditya <adityasripal@gmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
dauTT 2020-09-04 22:59:22 +02:00 committed by GitHub
parent bae1399ebc
commit b52ffa08e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 1869 additions and 298 deletions

View File

@ -106,6 +106,7 @@ func local_request_ReflectionService_ListImplementations_0(ctx context.Context,
// RegisterReflectionServiceHandlerServer registers the http handlers for service ReflectionService to "mux".
// UnaryRPC :call ReflectionServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterReflectionServiceHandlerFromEndpoint instead.
func RegisterReflectionServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ReflectionServiceServer) error {
mux.Handle("GET", pattern_ReflectionService_ListAllInterfaces_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -70,6 +70,7 @@ func local_request_SimulateService_Simulate_0(ctx context.Context, marshaler run
// RegisterSimulateServiceHandlerServer registers the http handlers for service SimulateService to "mux".
// UnaryRPC :call SimulateServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterSimulateServiceHandlerFromEndpoint instead.
func RegisterSimulateServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server SimulateServiceServer) error {
mux.Handle("POST", pattern_SimulateService_Simulate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -26,6 +26,21 @@ message ClientConsensusStates {
[(gogoproto.moretags) = "yaml:\"consensus_states\""];
}
// ClientUpdateProposal is a governance proposal. If it passes, the client is
// updated with the provided header. The update may fail if the header is not
// valid given certain conditions specified by the client implementation.
message ClientUpdateProposal {
option (gogoproto.goproto_getters) = false;
// the title of the update proposal
string title = 1;
// the description of the proposal
string description = 2;
// the client identifier for the client to be updated if the proposal passes
string client_id = 3 [(gogoproto.moretags) = "yaml:\"client_id\""];
// the header used to update the client if the proposal passes
google.protobuf.Any header = 4;
}
// MsgCreateClient defines a message to create an IBC client
message MsgCreateClient {
// client unique identifier

View File

@ -15,6 +15,10 @@ message ClientState {
[(gogoproto.moretags) = "yaml:\"frozen_sequence\""];
ConsensusState consensus_state = 2
[(gogoproto.moretags) = "yaml:\"consensus_state\""];
// when set to true, will allow governance to update a solo machine client.
// The client will be unfrozen if it is frozen.
bool allow_update_after_proposal = 3
[(gogoproto.moretags) = "yaml:\"allow_update_after_proposal\""];
}
// ConsensusState defines a solo machine consensus state

View File

@ -54,6 +54,15 @@ message ClientState {
// Proof specifications used in verifying counterparty state
repeated ics23.ProofSpec proof_specs = 8
[(gogoproto.moretags) = "yaml:\"proof_specs\""];
// This flag, when set to true, will allow governance to recover a client
// which has expired
bool allow_update_after_expiry = 9
[(gogoproto.moretags) = "yaml:\"allow_update_after_expiry\""];
// This flag, when set to true, will allow governance to unfreeze a client
// whose chain has experienced a misbehaviour event
bool allow_update_after_misbehaviour = 10
[(gogoproto.moretags) = "yaml:\"allow_update_after_misbehaviour\""];
}
// ConsensusState defines the consensus state from Tendermint.

View File

@ -52,6 +52,7 @@ import (
transfer "github.com/cosmos/cosmos-sdk/x/ibc-transfer"
ibctransferkeeper "github.com/cosmos/cosmos-sdk/x/ibc-transfer/keeper"
ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc-transfer/types"
ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/02-client"
porttypes "github.com/cosmos/cosmos-sdk/x/ibc/05-port/types"
ibchost "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
ibckeeper "github.com/cosmos/cosmos-sdk/x/ibc/keeper"
@ -244,17 +245,6 @@ func NewSimApp(
)
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath)
// register the proposal types
govRouter := govtypes.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
app.GovKeeper = govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, govRouter,
)
// register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper = *stakingKeeper.SetHooks(
@ -266,6 +256,18 @@ func NewSimApp(
appCodec, keys[ibchost.StoreKey], app.StakingKeeper, scopedIBCKeeper,
)
// register the proposal types
govRouter := govtypes.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)).
AddRoute(ibchost.RouterKey, ibcclient.NewClientUpdateProposalHandler(app.IBCKeeper.ClientKeeper))
app.GovKeeper = govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, govRouter,
)
// Create Transfer Keepers
app.TransferKeeper = ibctransferkeeper.NewKeeper(
appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName),

View File

@ -106,6 +106,7 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Account_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -272,6 +272,7 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Balance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -488,6 +488,7 @@ func local_request_Query_CommunityPool_0(ctx context.Context, marshaler runtime.
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -124,6 +124,7 @@ func local_request_Query_AllEvidence_0(ctx context.Context, marshaler runtime.Ma
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Evidence_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -528,6 +528,7 @@ func local_request_Query_TallyResult_0(ctx context.Context, marshaler runtime.Ma
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Proposal_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -142,6 +142,7 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_DenomTrace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -5,6 +5,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/keeper"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
)
@ -93,3 +94,16 @@ func HandleMsgSubmitMisbehaviour(ctx sdk.Context, k keeper.Keeper, msg *types.Ms
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
}
// NewClientUpdateProposalHandler defines the client update proposal handler
func NewClientUpdateProposalHandler(k keeper.Keeper) govtypes.Handler {
return func(ctx sdk.Context, content govtypes.Content) error {
switch c := content.(type) {
case *types.ClientUpdateProposal:
return k.ClientUpdateProposal(ctx, c)
default:
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ibc proposal content type: %T", c)
}
}
}

View File

@ -0,0 +1,76 @@
package client_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
client "github.com/cosmos/cosmos-sdk/x/ibc/02-client"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
)
func (suite *ClientTestSuite) TestNewClientUpdateProposalHandler() {
var (
content govtypes.Content
err error
)
testCases := []struct {
name string
malleate func()
expPass bool
}{
{
"valid update client proposal", func() {
clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint)
clientState := suite.chainA.GetClientState(clientA)
tmClientState, ok := clientState.(*ibctmtypes.ClientState)
suite.Require().True(ok)
tmClientState.AllowUpdateAfterMisbehaviour = true
tmClientState.FrozenHeight = tmClientState.LatestHeight
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClientState)
// use next header for chainB to update the client on chainA
header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA)
suite.Require().NoError(err)
content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientA, header)
suite.Require().NoError(err)
}, true,
},
{
"nil proposal", func() {
content = nil
}, false,
},
{
"unsupported proposal type", func() {
content = distributiontypes.NewCommunityPoolSpendProposal(ibctesting.Title, ibctesting.Description, suite.chainA.SenderAccount.GetAddress(), sdk.NewCoins(sdk.NewCoin("communityfunds", sdk.NewInt(10))))
}, false,
},
}
for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
suite.SetupTest() // reset
tc.malleate()
proposalHandler := client.NewClientUpdateProposalHandler(suite.chainA.App.IBCKeeper.ClientKeeper)
err = proposalHandler(suite.chainA.GetContext(), content)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}

View File

@ -37,7 +37,7 @@ func (k Keeper) CreateClient(
return clientState, nil
}
// UpdateClient updates the consensus state and the state root from a provided header
// UpdateClient updates the consensus state and the state root from a provided header.
func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.Header) (exported.ClientState, error) {
clientType, found := k.GetClientType(ctx, clientID)
if !found {

View File

@ -36,11 +36,11 @@ func (suite *KeeperTestSuite) TestCreateClient() {
i := i
if tc.expPanic {
suite.Require().Panics(func() {
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
suite.keeper.CreateClient(suite.ctx, tc.clientID, clientState, suite.consensusState)
}, "Msg %d didn't panic: %s", i, tc.msg)
} else {
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
if tc.expPass {
suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.msg)
}
@ -77,7 +77,7 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
expPass bool
}{
{"valid update", func() error {
clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
_, err := suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
// store intermediate consensus state to check that trustedHeight does not need to be highest consensus state before header height
@ -96,7 +96,7 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
return err
}, true},
{"valid past update", func() error {
clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
_, err := suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
suite.Require().NoError(err)
@ -143,7 +143,7 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
return nil
}, false},
{"consensus state not found", func() error {
clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
suite.keeper.SetClientType(suite.ctx, testClientID, exported.Tendermint)
updateHeader = createFutureUpdateFn(suite)
@ -159,7 +159,7 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
return nil
}, false},
{"valid past update before client was frozen", func() error {
clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
clientState.FrozenHeight = types.NewHeight(0, testClientHeight.EpochHeight-1)
_, err := suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
suite.Require().NoError(err)
@ -180,7 +180,7 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
return nil
}, true},
{"invalid header", func() error {
clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
_, err := suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
suite.Require().NoError(err)
updateHeader = createPastUpdateFn(suite)
@ -291,7 +291,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
func() error {
suite.consensusState.NextValidatorsHash = bothValsHash
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
_, err := suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
return err
@ -308,7 +308,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
func() error {
suite.consensusState.NextValidatorsHash = valsHash
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
_, err := suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
// store intermediate consensus state to check that trustedHeight does not need to be highest consensus state before header height
@ -336,7 +336,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
func() error {
suite.consensusState.NextValidatorsHash = valsHash
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
_, err := suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
// store trusted consensus state for Header2
@ -364,7 +364,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
func() error {
suite.consensusState.NextValidatorsHash = valsHash
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
_, err := suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
// intermediate consensus state at height + 3 is not created
return err
@ -381,7 +381,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
func() error {
suite.consensusState.NextValidatorsHash = valsHash
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
_, err := suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
// intermediate consensus state at height + 3 is not created
return err
@ -404,7 +404,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
func() error {
suite.consensusState.NextValidatorsHash = bothValsHash
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
_, err := suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
clientState.FrozenHeight = types.NewHeight(0, 1)
@ -423,7 +423,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
ClientId: testClientID,
},
func() error {
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
if err != nil {
return err
}

View File

@ -42,7 +42,7 @@ func (suite *KeeperTestSuite) TestQueryClientState() {
{
"success",
func() {
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs(), false, false)
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
var err error
@ -208,7 +208,7 @@ func (suite *KeeperTestSuite) TestQueryConsensusState() {
{
"success latest height",
func() {
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
cs := ibctmtypes.NewConsensusState(
suite.consensusState.Timestamp, commitmenttypes.NewMerkleRoot([]byte("hash1")), suite.consensusState.Height, nil,
)

View File

@ -111,7 +111,7 @@ func TestKeeperTestSuite(t *testing.T) {
}
func (suite *KeeperTestSuite) TestSetClientState() {
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs(), false, false)
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
retrievedState, found := suite.keeper.GetClientState(suite.ctx, testClientID)
@ -146,7 +146,7 @@ func (suite *KeeperTestSuite) TestValidateSelfClient() {
}{
{
"success",
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false),
true,
},
{
@ -156,37 +156,37 @@ func (suite *KeeperTestSuite) TestValidateSelfClient() {
},
{
"frozen client",
&ibctmtypes.ClientState{testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, testClientHeight, commitmenttypes.GetSDKSpecs()},
&ibctmtypes.ClientState{testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false},
false,
},
{
"incorrect chainID",
ibctmtypes.NewClientState("gaiatestnet", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState("gaiatestnet", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false),
false,
},
{
"invalid client height",
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.NewHeight(0, testClientHeight.EpochHeight+10), commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.NewHeight(0, testClientHeight.EpochHeight+10), commitmenttypes.GetSDKSpecs(), false, false),
false,
},
{
"invalid proof specs",
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, nil),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, nil, false, false),
false,
},
{
"invalid trust level",
ibctmtypes.NewClientState(testChainID, ibctmtypes.Fraction{0, 1}, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testChainID, ibctmtypes.Fraction{0, 1}, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false),
false,
},
{
"invalid unbonding period",
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+10, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+10, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false),
false,
},
{
"invalid trusting period",
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, ubdPeriod+10, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, ubdPeriod+10, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false),
false,
},
}
@ -209,9 +209,9 @@ func (suite KeeperTestSuite) TestGetAllClients() {
testClientID2, testClientID3, testClientID,
}
expClients := []exported.ClientState{
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs(), false, false),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs(), false, false),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs(), false, false),
}
for i := range expClients {
@ -233,9 +233,9 @@ func (suite KeeperTestSuite) TestGetAllGenesisClients() {
testClientID2, testClientID3, testClientID,
}
expClients := []exported.ClientState{
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs(), false, false),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs(), false, false),
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.Height{}, commitmenttypes.GetSDKSpecs(), false, false),
}
expGenClients := make([]types.IdentifiedClientState, len(expClients))
@ -283,7 +283,7 @@ func (suite KeeperTestSuite) TestGetConsensusState() {
func (suite KeeperTestSuite) TestConsensusStateHelpers() {
// initial setup
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), false, false)
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, suite.consensusState)

View File

@ -0,0 +1,55 @@
package keeper
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
)
// ClientUpdateProposal will try to update the client with the new header if and only if
// the proposal passes. The localhost client is not allowed to be modified with a proposal.
func (k Keeper) ClientUpdateProposal(ctx sdk.Context, p *types.ClientUpdateProposal) error {
clientType, found := k.GetClientType(ctx, p.ClientId)
if !found {
return sdkerrors.Wrapf(types.ErrClientTypeNotFound, "cannot update client with ID %s", p.ClientId)
}
if clientType == exported.Localhost || p.ClientId == exported.ClientTypeLocalHost {
return sdkerrors.Wrap(types.ErrInvalidUpdateClientProposal, "cannot update localhost client with proposal")
}
clientState, found := k.GetClientState(ctx, p.ClientId)
if !found {
return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", p.ClientId)
}
header, err := types.UnpackHeader(p.Header)
if err != nil {
return err
}
clientState, consensusState, err := clientState.CheckProposedHeaderAndUpdateState(ctx, k.cdc, k.ClientStore(ctx, p.ClientId), header)
if err != nil {
return err
}
k.SetClientState(ctx, p.ClientId, clientState)
k.SetClientConsensusState(ctx, p.ClientId, header.GetHeight(), consensusState)
k.Logger(ctx).Info("client updated after governance proposal passed", "client-id", p.ClientId, "height", clientState.GetLatestHeight())
// emitting events in the keeper for proposal updates to clients
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeUpdateClientProposal,
sdk.NewAttribute(types.AttributeKeyClientID, p.ClientId),
sdk.NewAttribute(types.AttributeKeyClientType, clientType.String()),
sdk.NewAttribute(types.AttributeKeyConsensusHeight, fmt.Sprintf("%d", header.GetHeight())),
),
)
return nil
}

View File

@ -0,0 +1,95 @@
package keeper_test
import (
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
)
func (suite *KeeperTestSuite) TestClientUpdateProposal() {
var (
content *types.ClientUpdateProposal
err error
)
testCases := []struct {
name string
malleate func()
expPass bool
}{
{
"valid update client proposal", func() {
clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint)
clientState := suite.chainA.GetClientState(clientA)
tmClientState, ok := clientState.(*ibctmtypes.ClientState)
suite.Require().True(ok)
tmClientState.AllowUpdateAfterMisbehaviour = true
tmClientState.FrozenHeight = tmClientState.LatestHeight
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClientState)
// use next header for chainB to update the client on chainA
header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA)
suite.Require().NoError(err)
content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientA, header)
suite.Require().NoError(err)
}, true,
},
{
"client type does not exist", func() {
content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, ibctesting.InvalidID, &ibctmtypes.Header{})
suite.Require().NoError(err)
}, false,
},
{
"cannot update localhost", func() {
content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, exported.Localhost.String(), &ibctmtypes.Header{})
suite.Require().NoError(err)
}, false,
},
{
"client does not exist", func() {
// bypass ClientType check
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientType(suite.chainA.GetContext(), ibctesting.InvalidID, exported.Tendermint)
content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, ibctesting.InvalidID, &ibctmtypes.Header{})
suite.Require().NoError(err)
}, false,
},
{
"cannot unpack header, header is nil", func() {
clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint)
content = &clienttypes.ClientUpdateProposal{ibctesting.Title, ibctesting.Description, clientA, nil}
}, false,
},
{
"update fails", func() {
header := &ibctmtypes.Header{}
clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint)
content, err = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientA, header)
suite.Require().NoError(err)
}, false,
},
}
for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
suite.SetupTest() // reset
tc.malleate()
err = suite.chainA.App.IBCKeeper.ClientKeeper.ClientUpdateProposal(suite.chainA.GetContext(), content)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}

View File

@ -137,6 +137,53 @@ func (m *ClientConsensusStates) GetConsensusStates() []*types.Any {
return nil
}
// ClientUpdateProposal is a governance proposal. If it passes, the client is
// updated with the provided header. The update may fail if the header is not
// valid given certain conditions specified by the client implementation.
type ClientUpdateProposal struct {
// the title of the update proposal
Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"`
// the description of the proposal
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
// the client identifier for the client to be updated if the proposal passes
ClientId string `protobuf:"bytes,3,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"`
// the header used to update the client if the proposal passes
Header *types.Any `protobuf:"bytes,4,opt,name=header,proto3" json:"header,omitempty"`
}
func (m *ClientUpdateProposal) Reset() { *m = ClientUpdateProposal{} }
func (m *ClientUpdateProposal) String() string { return proto.CompactTextString(m) }
func (*ClientUpdateProposal) ProtoMessage() {}
func (*ClientUpdateProposal) Descriptor() ([]byte, []int) {
return fileDescriptor_226f80e576f20abd, []int{2}
}
func (m *ClientUpdateProposal) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ClientUpdateProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ClientUpdateProposal.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ClientUpdateProposal) XXX_Merge(src proto.Message) {
xxx_messageInfo_ClientUpdateProposal.Merge(m, src)
}
func (m *ClientUpdateProposal) XXX_Size() int {
return m.Size()
}
func (m *ClientUpdateProposal) XXX_DiscardUnknown() {
xxx_messageInfo_ClientUpdateProposal.DiscardUnknown(m)
}
var xxx_messageInfo_ClientUpdateProposal proto.InternalMessageInfo
// MsgCreateClient defines a message to create an IBC client
type MsgCreateClient struct {
// client unique identifier
@ -154,7 +201,7 @@ func (m *MsgCreateClient) Reset() { *m = MsgCreateClient{} }
func (m *MsgCreateClient) String() string { return proto.CompactTextString(m) }
func (*MsgCreateClient) ProtoMessage() {}
func (*MsgCreateClient) Descriptor() ([]byte, []int) {
return fileDescriptor_226f80e576f20abd, []int{2}
return fileDescriptor_226f80e576f20abd, []int{3}
}
func (m *MsgCreateClient) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -226,7 +273,7 @@ func (m *MsgUpdateClient) Reset() { *m = MsgUpdateClient{} }
func (m *MsgUpdateClient) String() string { return proto.CompactTextString(m) }
func (*MsgUpdateClient) ProtoMessage() {}
func (*MsgUpdateClient) Descriptor() ([]byte, []int) {
return fileDescriptor_226f80e576f20abd, []int{3}
return fileDescriptor_226f80e576f20abd, []int{4}
}
func (m *MsgUpdateClient) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -291,7 +338,7 @@ func (m *MsgSubmitMisbehaviour) Reset() { *m = MsgSubmitMisbehaviour{} }
func (m *MsgSubmitMisbehaviour) String() string { return proto.CompactTextString(m) }
func (*MsgSubmitMisbehaviour) ProtoMessage() {}
func (*MsgSubmitMisbehaviour) Descriptor() ([]byte, []int) {
return fileDescriptor_226f80e576f20abd, []int{4}
return fileDescriptor_226f80e576f20abd, []int{5}
}
func (m *MsgSubmitMisbehaviour) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -360,7 +407,7 @@ type Height struct {
func (m *Height) Reset() { *m = Height{} }
func (*Height) ProtoMessage() {}
func (*Height) Descriptor() ([]byte, []int) {
return fileDescriptor_226f80e576f20abd, []int{5}
return fileDescriptor_226f80e576f20abd, []int{6}
}
func (m *Height) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -392,6 +439,7 @@ var xxx_messageInfo_Height proto.InternalMessageInfo
func init() {
proto.RegisterType((*IdentifiedClientState)(nil), "ibc.client.IdentifiedClientState")
proto.RegisterType((*ClientConsensusStates)(nil), "ibc.client.ClientConsensusStates")
proto.RegisterType((*ClientUpdateProposal)(nil), "ibc.client.ClientUpdateProposal")
proto.RegisterType((*MsgCreateClient)(nil), "ibc.client.MsgCreateClient")
proto.RegisterType((*MsgUpdateClient)(nil), "ibc.client.MsgUpdateClient")
proto.RegisterType((*MsgSubmitMisbehaviour)(nil), "ibc.client.MsgSubmitMisbehaviour")
@ -401,40 +449,44 @@ func init() {
func init() { proto.RegisterFile("ibc/client/client.proto", fileDescriptor_226f80e576f20abd) }
var fileDescriptor_226f80e576f20abd = []byte{
// 525 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0x3f, 0x8f, 0x12, 0x41,
0x1c, 0x65, 0xe0, 0x42, 0xee, 0x06, 0x22, 0x97, 0x15, 0x04, 0x31, 0xd9, 0x25, 0x53, 0x51, 0xc8,
0xae, 0x87, 0x8d, 0xa1, 0x03, 0x1a, 0x49, 0xc4, 0x98, 0xbd, 0x58, 0x68, 0x4c, 0x2e, 0xbb, 0xb3,
0x73, 0xbb, 0x13, 0xd9, 0x1d, 0xb2, 0x33, 0x6b, 0xe4, 0x1b, 0x18, 0x2b, 0x4b, 0x0b, 0x8b, 0x2b,
0xfd, 0x10, 0xda, 0xdb, 0x79, 0xa5, 0xd5, 0xc6, 0xc0, 0x37, 0xa0, 0xb4, 0x32, 0xcc, 0x2c, 0x1e,
0x5c, 0x4e, 0x8a, 0x3b, 0x0b, 0xab, 0x99, 0xdf, 0xbf, 0xf7, 0x7b, 0xef, 0x65, 0x32, 0xb0, 0x4e,
0x5d, 0x6c, 0xe1, 0x09, 0x25, 0x91, 0xc8, 0x0e, 0x73, 0x1a, 0x33, 0xc1, 0x34, 0x48, 0x5d, 0x6c,
0xaa, 0x4c, 0xb3, 0xea, 0x33, 0x9f, 0xc9, 0xb4, 0xb5, 0xba, 0xa9, 0x8e, 0xe6, 0x5d, 0x9f, 0x31,
0x7f, 0x42, 0x2c, 0x19, 0xb9, 0xc9, 0xa9, 0xe5, 0x44, 0x33, 0x55, 0x42, 0x9f, 0x00, 0xac, 0x8d,
0x3c, 0x12, 0x09, 0x7a, 0x4a, 0x89, 0x37, 0x94, 0x28, 0xc7, 0xc2, 0x11, 0x44, 0x3b, 0x82, 0x07,
0x0a, 0xf4, 0x84, 0x7a, 0x0d, 0xd0, 0x02, 0xed, 0x83, 0x41, 0x75, 0x99, 0x1a, 0x87, 0x33, 0x27,
0x9c, 0xf4, 0xd0, 0x9f, 0x12, 0xb2, 0xf7, 0xd5, 0x7d, 0xe4, 0x69, 0xcf, 0x60, 0x39, 0xcb, 0xf3,
0x15, 0x44, 0x23, 0xdf, 0x02, 0xed, 0x52, 0xb7, 0x6a, 0xaa, 0xf5, 0xe6, 0x7a, 0xbd, 0xd9, 0x8f,
0x66, 0x83, 0xfa, 0x32, 0x35, 0x6e, 0x6f, 0x61, 0xc9, 0x19, 0x64, 0x97, 0xf0, 0x05, 0x09, 0xf4,
0x19, 0xc0, 0x9a, 0x22, 0x35, 0x64, 0x11, 0x27, 0x11, 0x4f, 0xb8, 0x2c, 0xf0, 0xeb, 0xd0, 0x7b,
0x05, 0x0f, 0xf1, 0x1a, 0x45, 0x6d, 0xe3, 0x8d, 0x7c, 0xab, 0xf0, 0x57, 0x8a, 0xf7, 0x96, 0xa9,
0x51, 0xcf, 0xf0, 0x2e, 0xcd, 0x21, 0xbb, 0x82, 0xb7, 0x09, 0xa1, 0x2f, 0x79, 0x58, 0x19, 0x73,
0x7f, 0x18, 0x13, 0x47, 0x10, 0xc5, 0xf9, 0xbf, 0xf0, 0x50, 0x7b, 0x01, 0x2b, 0x97, 0xe8, 0x37,
0x0a, 0x3b, 0x40, 0x9b, 0xcb, 0xd4, 0xb8, 0x73, 0xa5, 0x6a, 0x64, 0xdf, 0xda, 0x16, 0xad, 0x8d,
0x60, 0x91, 0x53, 0x3f, 0x22, 0x71, 0x63, 0xaf, 0x05, 0xda, 0xe5, 0xc1, 0xd1, 0xaf, 0xd4, 0xe8,
0xf8, 0x54, 0x04, 0x89, 0x6b, 0x62, 0x16, 0x5a, 0x98, 0xf1, 0x90, 0xf1, 0xec, 0xe8, 0x70, 0xef,
0xb5, 0x25, 0x66, 0x53, 0xc2, 0xcd, 0x3e, 0xc6, 0x7d, 0xcf, 0x8b, 0x09, 0xe7, 0x76, 0x06, 0x80,
0xbe, 0x02, 0x69, 0xdf, 0xf3, 0xa9, 0x77, 0x23, 0xfb, 0xee, 0xc3, 0x62, 0x40, 0x1c, 0x8f, 0xc4,
0xbb, 0x8c, 0xb3, 0xb3, 0x9e, 0x0d, 0xfe, 0x85, 0x9b, 0xf2, 0xff, 0x0e, 0x60, 0x6d, 0xcc, 0xfd,
0xe3, 0xc4, 0x0d, 0xa9, 0x18, 0x53, 0xee, 0x92, 0xc0, 0x79, 0x43, 0x59, 0x12, 0x5f, 0x47, 0xc5,
0x23, 0x58, 0x0e, 0x37, 0x20, 0x76, 0x6a, 0xd9, 0xea, 0xfc, 0x97, 0x8a, 0xde, 0x03, 0x58, 0x7c,
0x4c, 0xa8, 0x1f, 0x08, 0xad, 0x07, 0xcb, 0x64, 0xca, 0x70, 0x70, 0x12, 0x25, 0xa1, 0x4b, 0x62,
0xa9, 0x62, 0x6f, 0xf3, 0xf9, 0x6d, 0x56, 0x91, 0x5d, 0x92, 0xe1, 0x53, 0x19, 0x5d, 0xcc, 0x06,
0x12, 0x4b, 0x6a, 0xb9, 0x62, 0x56, 0x55, 0xd7, 0xb3, 0x6a, 0x6f, 0x6f, 0xff, 0xdd, 0x99, 0x91,
0xfb, 0x78, 0x66, 0xe4, 0x06, 0x4f, 0xbe, 0xcd, 0x75, 0x70, 0x3e, 0xd7, 0xc1, 0xcf, 0xb9, 0x0e,
0x3e, 0x2c, 0xf4, 0xdc, 0xf9, 0x42, 0xcf, 0xfd, 0x58, 0xe8, 0xb9, 0x97, 0xdd, 0x9d, 0xea, 0xde,
0x5a, 0xab, 0x6f, 0xf3, 0x41, 0xb7, 0x93, 0xfd, 0x9c, 0x52, 0xad, 0x5b, 0x94, 0x0e, 0x3e, 0xfc,
0x1d, 0x00, 0x00, 0xff, 0xff, 0x0c, 0x85, 0x19, 0xfc, 0x54, 0x05, 0x00, 0x00,
// 588 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xb1, 0x8f, 0x12, 0x4f,
0x14, 0x66, 0x38, 0x7e, 0xe4, 0x18, 0xc8, 0x8f, 0xcb, 0x0a, 0x82, 0x98, 0xec, 0x92, 0xad, 0xae,
0x90, 0x5d, 0x0f, 0x1b, 0x43, 0x07, 0x34, 0x92, 0x88, 0xb9, 0xec, 0xc5, 0x42, 0x63, 0x72, 0xd9,
0x9d, 0x9d, 0xdb, 0x9d, 0xc8, 0xee, 0x6c, 0x76, 0x66, 0x8d, 0xfc, 0x07, 0xc6, 0xca, 0xd2, 0xc2,
0xe2, 0x4a, 0xff, 0x01, 0x3b, 0xed, 0xed, 0xbc, 0xd2, 0x8a, 0x18, 0xf8, 0x0f, 0x28, 0xad, 0x0c,
0x33, 0x8b, 0xc0, 0xe5, 0x38, 0x0d, 0x5a, 0x58, 0xed, 0xbc, 0xf7, 0xe6, 0x7d, 0xef, 0xfb, 0xbe,
0x07, 0x03, 0x6b, 0xc4, 0x41, 0x26, 0x1a, 0x11, 0x1c, 0xf2, 0xf4, 0x63, 0x44, 0x31, 0xe5, 0x54,
0x81, 0xc4, 0x41, 0x86, 0xcc, 0x34, 0x2a, 0x1e, 0xf5, 0xa8, 0x48, 0x9b, 0x8b, 0x93, 0xbc, 0xd1,
0xb8, 0xe5, 0x51, 0xea, 0x8d, 0xb0, 0x29, 0x22, 0x27, 0x39, 0x33, 0xed, 0x70, 0x2c, 0x4b, 0xfa,
0x3b, 0x00, 0xab, 0x03, 0x17, 0x87, 0x9c, 0x9c, 0x11, 0xec, 0xf6, 0x05, 0xca, 0x09, 0xb7, 0x39,
0x56, 0x8e, 0x60, 0x41, 0x82, 0x9e, 0x12, 0xb7, 0x0e, 0x9a, 0xe0, 0xb0, 0xd0, 0xab, 0xcc, 0x27,
0xda, 0xc1, 0xd8, 0x0e, 0x46, 0x1d, 0xfd, 0x67, 0x49, 0xb7, 0xf6, 0xe5, 0x79, 0xe0, 0x2a, 0xc7,
0xb0, 0x94, 0xe6, 0xd9, 0x02, 0xa2, 0x9e, 0x6d, 0x82, 0xc3, 0x62, 0xbb, 0x62, 0xc8, 0xf1, 0xc6,
0x72, 0xbc, 0xd1, 0x0d, 0xc7, 0xbd, 0xda, 0x7c, 0xa2, 0xdd, 0xd8, 0xc0, 0x12, 0x3d, 0xba, 0x55,
0x44, 0x2b, 0x12, 0xfa, 0x7b, 0x00, 0xab, 0x92, 0x54, 0x9f, 0x86, 0x0c, 0x87, 0x2c, 0x61, 0xa2,
0xc0, 0x76, 0xa1, 0xf7, 0x0c, 0x1e, 0xa0, 0x25, 0x8a, 0x9c, 0xc6, 0xea, 0xd9, 0xe6, 0xde, 0x56,
0x8a, 0xb7, 0xe7, 0x13, 0xad, 0x96, 0xe2, 0x5d, 0xea, 0xd3, 0xad, 0x32, 0xda, 0x24, 0xa4, 0x7f,
0x00, 0xb0, 0x22, 0xa9, 0x3e, 0x8e, 0x5c, 0x9b, 0xe3, 0xe3, 0x98, 0x46, 0x94, 0xd9, 0x23, 0xa5,
0x02, 0xff, 0xe3, 0x84, 0x8f, 0xb0, 0x64, 0x69, 0xc9, 0x40, 0x69, 0xc2, 0xa2, 0x8b, 0x19, 0x8a,
0x49, 0xc4, 0x09, 0x0d, 0x85, 0x55, 0x05, 0x6b, 0x3d, 0xb5, 0xa9, 0x70, 0xef, 0xb7, 0x14, 0xde,
0x81, 0x79, 0x1f, 0xdb, 0x2e, 0x8e, 0xeb, 0xb9, 0xed, 0xd6, 0x5b, 0xe9, 0x9d, 0x4e, 0xee, 0xd5,
0xb9, 0x96, 0xd1, 0x3f, 0x66, 0x61, 0x79, 0xc8, 0xbc, 0x7e, 0x8c, 0x6d, 0x8e, 0xa5, 0x80, 0x7f,
0x62, 0xf7, 0xca, 0x13, 0x58, 0xbe, 0x64, 0xbb, 0x70, 0x61, 0x1b, 0x68, 0x63, 0x3e, 0xd1, 0x6e,
0x5e, 0xb9, 0x2d, 0xdd, 0xfa, 0x7f, 0x73, 0x59, 0xca, 0x00, 0xe6, 0x19, 0xf1, 0xc2, 0xd4, 0xa7,
0x52, 0xef, 0xe8, 0xfb, 0x44, 0x6b, 0x79, 0x84, 0xfb, 0x89, 0x63, 0x20, 0x1a, 0x98, 0x88, 0xb2,
0x80, 0xb2, 0xf4, 0xd3, 0x62, 0xee, 0x73, 0x93, 0x8f, 0x23, 0xcc, 0x8c, 0x2e, 0x42, 0x5d, 0xd7,
0x8d, 0x31, 0x63, 0x56, 0x0a, 0xa0, 0x7f, 0x02, 0xc2, 0x3e, 0xb9, 0xf3, 0xdd, 0xed, 0x5b, 0x6d,
0x2e, 0xfb, 0xeb, 0xcd, 0xad, 0xf1, 0xdf, 0xfb, 0x53, 0xfe, 0x5f, 0x00, 0xac, 0x0e, 0x99, 0x77,
0x92, 0x38, 0x01, 0xe1, 0x43, 0xc2, 0x1c, 0xec, 0xdb, 0x2f, 0x08, 0x4d, 0xe2, 0x5d, 0x54, 0xdc,
0x87, 0xa5, 0x60, 0x0d, 0xe2, 0x5a, 0x2d, 0x1b, 0x37, 0xff, 0xa6, 0xa2, 0xd7, 0x00, 0xe6, 0x1f,
0x60, 0xe2, 0xf9, 0x5c, 0xe9, 0xc0, 0x12, 0x8e, 0x28, 0xf2, 0x4f, 0xc3, 0x24, 0x70, 0x70, 0x2c,
0x54, 0xe4, 0xd6, 0x7f, 0x7e, 0xeb, 0x55, 0xdd, 0x2a, 0x8a, 0xf0, 0x91, 0x88, 0x56, 0xbd, 0xbe,
0xc0, 0x12, 0x5a, 0xae, 0xe8, 0x95, 0xd5, 0x65, 0xaf, 0x9c, 0xdb, 0xd9, 0x5f, 0xfc, 0xb3, 0xde,
0x9e, 0x6b, 0x99, 0xde, 0xc3, 0xcf, 0x53, 0x15, 0x5c, 0x4c, 0x55, 0xf0, 0x6d, 0xaa, 0x82, 0x37,
0x33, 0x35, 0x73, 0x31, 0x53, 0x33, 0x5f, 0x67, 0x6a, 0xe6, 0x69, 0xfb, 0x5a, 0x75, 0x2f, 0xcd,
0xc5, 0x73, 0x7f, 0xb7, 0xdd, 0x4a, 0x5f, 0x7c, 0xa1, 0xd6, 0xc9, 0x0b, 0x07, 0xef, 0xfd, 0x08,
0x00, 0x00, 0xff, 0xff, 0x57, 0xd4, 0xed, 0x68, 0x0c, 0x06, 0x00, 0x00,
}
func (m *IdentifiedClientState) Marshal() (dAtA []byte, err error) {
@ -523,6 +575,62 @@ func (m *ClientConsensusStates) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *ClientUpdateProposal) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ClientUpdateProposal) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *ClientUpdateProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.Header != nil {
{
size, err := m.Header.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintClient(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x22
}
if len(m.ClientId) > 0 {
i -= len(m.ClientId)
copy(dAtA[i:], m.ClientId)
i = encodeVarintClient(dAtA, i, uint64(len(m.ClientId)))
i--
dAtA[i] = 0x1a
}
if len(m.Description) > 0 {
i -= len(m.Description)
copy(dAtA[i:], m.Description)
i = encodeVarintClient(dAtA, i, uint64(len(m.Description)))
i--
dAtA[i] = 0x12
}
if len(m.Title) > 0 {
i -= len(m.Title)
copy(dAtA[i:], m.Title)
i = encodeVarintClient(dAtA, i, uint64(len(m.Title)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *MsgCreateClient) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -762,6 +870,31 @@ func (m *ClientConsensusStates) Size() (n int) {
return n
}
func (m *ClientUpdateProposal) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Title)
if l > 0 {
n += 1 + l + sovClient(uint64(l))
}
l = len(m.Description)
if l > 0 {
n += 1 + l + sovClient(uint64(l))
}
l = len(m.ClientId)
if l > 0 {
n += 1 + l + sovClient(uint64(l))
}
if m.Header != nil {
l = m.Header.Size()
n += 1 + l + sovClient(uint64(l))
}
return n
}
func (m *MsgCreateClient) Size() (n int) {
if m == nil {
return 0
@ -1090,6 +1223,191 @@ func (m *ClientConsensusStates) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *ClientUpdateProposal) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowClient
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ClientUpdateProposal: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ClientUpdateProposal: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowClient
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthClient
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthClient
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Title = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowClient
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthClient
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthClient
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Description = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowClient
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthClient
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthClient
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ClientId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowClient
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthClient
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthClient
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Header == nil {
m.Header = &types.Any{}
}
if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipClient(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthClient
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthClient
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *MsgCreateClient) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0

View File

@ -33,7 +33,7 @@ func TestPackClientState(t *testing.T) {
},
{
"tendermint client",
ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs()),
ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false),
true,
},
{

View File

@ -26,4 +26,6 @@ var (
ErrFailedPacketAckAbsenceVerification = sdkerrors.Register(SubModuleName, 19, "packet acknowledgement absence verification failed")
ErrFailedNextSeqRecvVerification = sdkerrors.Register(SubModuleName, 20, "next sequence receive verification failed")
ErrSelfConsensusStateNotFound = sdkerrors.Register(SubModuleName, 21, "self consensus state not found")
ErrUpdateClientFailed = sdkerrors.Register(SubModuleName, 22, "unable to update light client")
ErrInvalidUpdateClientProposal = sdkerrors.Register(SubModuleName, 23, "invalid update client proposal")
)

View File

@ -15,9 +15,10 @@ const (
// IBC client events vars
var (
EventTypeCreateClient = "create_client"
EventTypeUpdateClient = "update_client"
EventTypeSubmitMisbehaviour = "client_misbehaviour"
EventTypeCreateClient = "create_client"
EventTypeUpdateClient = "update_client"
EventTypeSubmitMisbehaviour = "client_misbehaviour"
EventTypeUpdateClientProposal = "update_client_proposal"
AttributeValueCategory = fmt.Sprintf("%s_%s", host.ModuleName, SubModuleName)
)

View File

@ -51,7 +51,7 @@ func TestValidateGenesis(t *testing.T) {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
clientID, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs()),
clientID, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false),
),
types.NewIdentifiedClientState(
exported.ClientTypeLocalHost, localhosttypes.NewClientState("chainID", clientHeight),
@ -76,7 +76,7 @@ func TestValidateGenesis(t *testing.T) {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
"/~@$*", ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs()),
"/~@$*", ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false),
),
types.NewIdentifiedClientState(
exported.ClientTypeLocalHost, localhosttypes.NewClientState("chainID", clientHeight),
@ -101,7 +101,7 @@ func TestValidateGenesis(t *testing.T) {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs()),
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false),
),
types.NewIdentifiedClientState(exported.ClientTypeLocalHost, localhosttypes.NewClientState("chaindID", types.Height{})),
},
@ -115,7 +115,7 @@ func TestValidateGenesis(t *testing.T) {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs()),
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false),
),
types.NewIdentifiedClientState(
exported.ClientTypeLocalHost, localhosttypes.NewClientState("chaindID", clientHeight),
@ -140,7 +140,7 @@ func TestValidateGenesis(t *testing.T) {
genState: types.NewGenesisState(
[]types.IdentifiedClientState{
types.NewIdentifiedClientState(
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs()),
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false),
),
types.NewIdentifiedClientState(
exported.ClientTypeLocalHost, localhosttypes.NewClientState("chaindID", clientHeight),

View File

@ -52,7 +52,7 @@ func (suite *TypesTestSuite) TestMarshalMsgCreateClient() {
},
{
"tendermint client", func() {
tendermintClient := ibctmtypes.NewClientState(suite.chain.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs())
tendermintClient := ibctmtypes.NewClientState(suite.chain.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false)
msg, err = types.NewMsgCreateClient("tendermint", tendermintClient, suite.chain.CreateTMClientHeader().ConsensusState(), suite.chain.SenderAccount.GetAddress())
suite.Require().NoError(err)
},
@ -104,7 +104,7 @@ func (suite *TypesTestSuite) TestMsgCreateClient_ValidateBasic() {
{
"valid - tendermint client",
func() {
tendermintClient := ibctmtypes.NewClientState(suite.chain.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs())
tendermintClient := ibctmtypes.NewClientState(suite.chain.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false)
msg, err = types.NewMsgCreateClient("tendermint", tendermintClient, suite.chain.CreateTMClientHeader().ConsensusState(), suite.chain.SenderAccount.GetAddress())
suite.Require().NoError(err)
},
@ -128,7 +128,7 @@ func (suite *TypesTestSuite) TestMsgCreateClient_ValidateBasic() {
{
"failed to unpack consensus state",
func() {
tendermintClient := ibctmtypes.NewClientState(suite.chain.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs())
tendermintClient := ibctmtypes.NewClientState(suite.chain.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false)
msg, err = types.NewMsgCreateClient("tendermint", tendermintClient, suite.chain.CreateTMClientHeader().ConsensusState(), suite.chain.SenderAccount.GetAddress())
suite.Require().NoError(err)
msg.ConsensusState = nil

View File

@ -0,0 +1,55 @@
package types
import (
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
)
const (
// ProposalTypeClientUpdate defines the type for a ClientUpdateProposal
ProposalTypeClientUpdate = "ClientUpdate"
)
var _ govtypes.Content = &ClientUpdateProposal{}
// NewClientUpdateProposal creates a new client update proposal.
func NewClientUpdateProposal(title, description, clientID string, header exported.Header) (*ClientUpdateProposal, error) {
any, err := PackHeader(header)
if err != nil {
return nil, err
}
return &ClientUpdateProposal{
Title: title,
Description: description,
ClientId: clientID,
Header: any,
}, nil
}
// GetTitle returns the title of a client update proposal.
func (cup *ClientUpdateProposal) GetTitle() string { return cup.Title }
// GetDescription returns the description of a client update proposal.
func (cup *ClientUpdateProposal) GetDescription() string { return cup.Description }
// GetDescription returns the routing key of a client update proposal.
func (cup *ClientUpdateProposal) ProposalRoute() string { return RouterKey }
// ProposalType returns the type of a client update proposal.
func (cup *ClientUpdateProposal) ProposalType() string { return ProposalTypeClientUpdate }
// ValidateBasic runs basic stateless validity checks
func (cup *ClientUpdateProposal) ValidateBasic() error {
err := govtypes.ValidateAbstract(cup)
if err != nil {
return err
}
header, err := UnpackHeader(cup.Header)
if err != nil {
return err
}
return header.ValidateBasic()
}

View File

@ -0,0 +1,77 @@
package types_test
import (
"testing"
"github.com/stretchr/testify/require"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
)
func TestNewUpdateClientProposal(t *testing.T) {
p, err := types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientID, &ibctmtypes.Header{})
require.NoError(t, err)
require.NotNil(t, p)
p, err = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, clientID, nil)
require.Error(t, err)
require.Nil(t, p)
}
func TestValidateBasic(t *testing.T) {
// use solo machine header for testing
solomachine := ibctesting.NewSolomachine(t, clientID)
smHeader := solomachine.CreateHeader()
header, err := types.PackHeader(smHeader)
require.NoError(t, err)
// use a different pointer so we don't modify 'header'
smInvalidHeader := solomachine.CreateHeader()
// a sequence of 0 will fail basic validation
smInvalidHeader.Sequence = 0
invalidHeader, err := types.PackHeader(smInvalidHeader)
require.NoError(t, err)
testCases := []struct {
name string
proposal govtypes.Content
expPass bool
}{
{
"success",
&types.ClientUpdateProposal{ibctesting.Title, ibctesting.Description, clientID, header},
true,
},
{
"fails validate abstract - empty title",
&types.ClientUpdateProposal{"", ibctesting.Description, clientID, header},
false,
},
{
"fails to unpack header",
&types.ClientUpdateProposal{ibctesting.Title, ibctesting.Description, clientID, nil},
false,
},
{
"fails header validate basic",
&types.ClientUpdateProposal{ibctesting.Title, ibctesting.Description, clientID, invalidHeader},
false,
},
}
for _, tc := range testCases {
err := tc.proposal.ValidateBasic()
if tc.expPass {
require.NoError(t, err, tc.name)
} else {
require.Error(t, err, tc.name)
}
}
}

View File

@ -312,6 +312,7 @@ func local_request_Query_ConsensusStates_0(ctx context.Context, marshaler runtim
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_ClientState_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -107,7 +107,7 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() {
signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht")
clientState := ibctmtypes.NewClientState(
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(),
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false,
)
// Pack consensus state into any to test unpacking error
@ -119,7 +119,7 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() {
// invalidClientState fails validateBasic
invalidClient := ibctmtypes.NewClientState(
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(),
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), false, false,
)
testMsgs := []*types.MsgConnectionOpenTry{
@ -179,7 +179,7 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() {
func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() {
signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht")
clientState := ibctmtypes.NewClientState(
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(),
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false,
)
// Pack consensus state into any to test unpacking error
@ -190,7 +190,7 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() {
// invalidClientState fails validateBasic
invalidClient := ibctmtypes.NewClientState(
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(),
chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), false, false,
)
testMsgs := []*types.MsgConnectionOpenAck{

View File

@ -330,6 +330,7 @@ func local_request_Query_ConnectionConsensusState_0(ctx context.Context, marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Connection_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -900,6 +900,7 @@ func local_request_Query_NextSequenceReceive_0(ctx context.Context, marshaler ru
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Channel_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -23,8 +23,10 @@ import (
)
const (
flagTrustLevel = "trust-level"
flagProofSpecs = "proof-specs"
flagTrustLevel = "trust-level"
flagProofSpecs = "proof-specs"
flagAllowUpdateAfterExpiry = "allow_update_after_expiry"
flagAllowUpdateAfterMisbehaviour = "allow_update_after_misbehaviour"
)
// NewCreateClientCmd defines the command to create a new IBC Client as defined
@ -111,6 +113,9 @@ func NewCreateClientCmd() *cobra.Command {
}
}
allowUpdateAfterExpiry, _ := cmd.Flags().GetBool(flagAllowUpdateAfterExpiry)
allowUpdateAfterMisbehaviour, _ := cmd.Flags().GetBool(flagAllowUpdateAfterMisbehaviour)
// validate header
if err := header.ValidateBasic(); err != nil {
return err
@ -118,7 +123,8 @@ func NewCreateClientCmd() *cobra.Command {
height := header.GetHeight().(clienttypes.Height)
clientState := types.NewClientState(
header.GetHeader().GetChainID(), trustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, specs,
header.GetHeader().GetChainID(), trustLevel, trustingPeriod, ubdPeriod, maxClockDrift,
height, specs, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour,
)
consensusState := header.ConsensusState()
@ -140,6 +146,8 @@ func NewCreateClientCmd() *cobra.Command {
cmd.Flags().String(flagTrustLevel, "default", "light client trust level fraction for header updates")
cmd.Flags().String(flagProofSpecs, "default", "proof specs format to be used for verification")
cmd.Flags().Bool(flagAllowUpdateAfterExpiry, false, "allow governance proposal to update client after expiry")
cmd.Flags().Bool(flagAllowUpdateAfterMisbehaviour, false, "allow governance proposal to update client after misbehaviour")
flags.AddTxFlagsToCmd(cmd)
return cmd

View File

@ -25,16 +25,19 @@ func NewClientState(
chainID string, trustLevel Fraction,
trustingPeriod, ubdPeriod, maxClockDrift time.Duration,
latestHeight clienttypes.Height, specs []*ics23.ProofSpec,
allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour bool,
) *ClientState {
return &ClientState{
ChainId: chainID,
TrustLevel: trustLevel,
TrustingPeriod: trustingPeriod,
UnbondingPeriod: ubdPeriod,
MaxClockDrift: maxClockDrift,
LatestHeight: latestHeight,
FrozenHeight: clienttypes.Height{},
ProofSpecs: specs,
ChainId: chainID,
TrustLevel: trustLevel,
TrustingPeriod: trustingPeriod,
UnbondingPeriod: ubdPeriod,
MaxClockDrift: maxClockDrift,
LatestHeight: latestHeight,
FrozenHeight: clienttypes.Height{},
ProofSpecs: specs,
AllowUpdateAfterExpiry: allowUpdateAfterExpiry,
AllowUpdateAfterMisbehaviour: allowUpdateAfterMisbehaviour,
}
}
@ -64,6 +67,13 @@ func (cs ClientState) GetFrozenHeight() exported.Height {
return cs.FrozenHeight
}
// IsExpired returns whether or not the client has passed the trusting period since the last
// update (in which case no headers are considered valid).
func (cs ClientState) IsExpired(latestTimestamp, now time.Time) bool {
expirationTime := latestTimestamp.Add(cs.TrustingPeriod)
return !expirationTime.After(now)
}
// Validate performs a basic validation of the client state fields.
func (cs ClientState) Validate() error {
if strings.TrimSpace(cs.ChainId) == "" {
@ -90,7 +100,6 @@ func (cs ClientState) Validate() error {
"trusting period (%s) should be < unbonding period (%s)", cs.TrustingPeriod, cs.UnbondingPeriod,
)
}
// Validate ProofSpecs
if cs.ProofSpecs == nil {
return sdkerrors.Wrap(ErrInvalidProofSpecs, "proof specs cannot be nil for tm client")
}

View File

@ -32,52 +32,52 @@ func (suite *TendermintTestSuite) TestValidate() {
}{
{
name: "valid client",
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
expPass: true,
},
{
name: "invalid chainID",
clientState: types.NewClientState(" ", types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(" ", types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
expPass: false,
},
{
name: "invalid trust level",
clientState: types.NewClientState(chainID, types.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
expPass: false,
},
{
name: "invalid trusting period",
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
expPass: false,
},
{
name: "invalid unbonding period",
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
expPass: false,
},
{
name: "invalid max clock drift",
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, 0, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, 0, height, commitmenttypes.GetSDKSpecs(), false, false),
expPass: false,
},
{
name: "invalid height",
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.Height{}, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.Height{}, commitmenttypes.GetSDKSpecs(), false, false),
expPass: false,
},
{
name: "trusting period not less than unbonding period",
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
expPass: false,
},
{
name: "proof specs is nil",
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, nil),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, nil, false, false),
expPass: false,
},
{
name: "proof specs contains nil",
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, []*ics23.ProofSpec{ics23.TendermintSpec, nil}),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, []*ics23.ProofSpec{ics23.TendermintSpec, nil}, false, false),
expPass: false,
},
}
@ -113,7 +113,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
// },
{
name: "ApplyPrefix failed",
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
consensusState: types.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
},
@ -122,7 +122,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
},
{
name: "latest client height < height",
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
consensusState: types.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
},
@ -140,7 +140,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
},
{
name: "proof verification failed",
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
consensusState: types.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
NextValidatorsHash: suite.valsHash,

View File

@ -6,7 +6,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
)
// RegisterInterfaces registers the tendermint concrete evidence and client-related
// RegisterInterfaces registers the tendermint concrete client-related
// implementations and interfaces.
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
registry.RegisterImplementations(

View File

@ -49,7 +49,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
}{
{
"valid misbehavior misbehaviour",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
@ -63,7 +63,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"valid misbehavior at height greater than last consensusState",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), heightMinus1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), heightMinus1, bothValsHash),
&types.Misbehaviour{
@ -77,7 +77,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"invalid misbehavior misbehaviour from different chain",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
@ -91,7 +91,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"valid misbehavior misbehaviour with different trusted heights",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), heightMinus1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), heightMinus3, suite.valsHash),
&types.Misbehaviour{
@ -105,7 +105,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"consensus state's valset hash different from misbehaviour should still pass",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, suite.valsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, suite.valsHash),
&types.Misbehaviour{
@ -119,7 +119,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"invalid misbehavior misbehaviour with trusted height different from trusted consensus state",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), heightMinus1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), heightMinus3, suite.valsHash),
&types.Misbehaviour{
@ -133,7 +133,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"invalid misbehavior misbehaviour with trusted validators different from trusted consensus state",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), heightMinus1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), heightMinus3, suite.valsHash),
&types.Misbehaviour{
@ -147,7 +147,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"already frozen client state",
types.ClientState{FrozenHeight: clienttypes.NewHeight(0, 1)},
&types.ClientState{FrozenHeight: clienttypes.NewHeight(0, 1)},
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
@ -161,7 +161,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"trusted consensus state does not exist",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
nil, // consensus state for trusted height - 1 does not exist in store
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
@ -175,7 +175,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"invalid tendermint misbehaviour",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
nil,
@ -184,7 +184,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"rejected misbehaviour due to expired age duration",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
@ -198,7 +198,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"rejected misbehaviour due to expired block duration",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(0, uint64(epochHeight+simapp.DefaultConsensusParams.Evidence.MaxAgeNumBlocks+1)), commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(0, uint64(epochHeight+simapp.DefaultConsensusParams.Evidence.MaxAgeNumBlocks+1)), commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
@ -212,7 +212,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"provided height > header height",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
@ -226,7 +226,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"unbonding period expired",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(time.Time{}, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), heightMinus1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
@ -240,7 +240,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"trusted validators is incorrect for given consensus state",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
@ -254,7 +254,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"first valset has too much change",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
@ -268,7 +268,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"second valset has too much change",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
@ -282,7 +282,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"both valsets have too much change",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{

View File

@ -0,0 +1,127 @@
package types
import (
"time"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
)
// CheckProposedHeaderAndUpdateState will try to update the client with the new header if and
// only if the proposal passes and one of the following two conditions is satisfied:
// 1) AllowUpdateAfterExpiry=true and Expire(ctx.BlockTime) = true
// 2) AllowUpdateAfterMisbehaviour and IsFrozen() = true
// In case 2) before trying to update the client, the client will be unfrozen by resetting
// the FrozenHeight to the zero Height. If AllowUpdateAfterMisbehaviour is set to true,
// expired clients will also be updated even if AllowUpdateAfterExpiry is set to false.
// Note, that even if the update happens, it may not be successful. The header may fail
// validation checks and an error will be returned in that case.
func (cs ClientState) CheckProposedHeaderAndUpdateState(
ctx sdk.Context, cdc codec.BinaryMarshaler, clientStore sdk.KVStore,
header exported.Header,
) (exported.ClientState, exported.ConsensusState, error) {
tmHeader, ok := header.(*Header)
if !ok {
return nil, nil, sdkerrors.Wrapf(
clienttypes.ErrInvalidHeader, "expected type %T, got %T", &Header{}, header,
)
}
// get consensus state corresponding to client state to check if the client is expired
consensusState, err := GetConsensusState(clientStore, cdc, cs.GetLatestHeight())
if err != nil {
return nil, nil, sdkerrors.Wrapf(
err, "could not get consensus state from clientstore at height: %d", cs.GetLatestHeight(),
)
}
switch {
case cs.IsFrozen():
if !cs.AllowUpdateAfterMisbehaviour {
return nil, nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client is not allowed to be unfrozen")
}
// unfreeze the client
cs.FrozenHeight = clienttypes.Height{}
// if the client is expired we unexpire the client using softer validation, otherwise
// full validation on the header is performed.
if cs.IsExpired(consensusState.Timestamp, ctx.BlockTime()) {
return cs.unexpireClient(consensusState, tmHeader, ctx.BlockTime())
}
// NOTE: the client may be frozen again since the misbehaviour evidence may
// not be expired yet
return cs.CheckHeaderAndUpdateState(ctx, cdc, clientStore, header)
case cs.AllowUpdateAfterExpiry && cs.IsExpired(consensusState.Timestamp, ctx.BlockTime()):
return cs.unexpireClient(consensusState, tmHeader, ctx.BlockTime())
default:
return nil, nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client cannot be updated with proposal")
}
}
// unexpireClient checks if the proposed header is sufficient to update an expired client.
// The client is updated if no error occurs.
func (cs ClientState) unexpireClient(
consensusState *ConsensusState, header *Header, currentTimestamp time.Time,
) (exported.ClientState, exported.ConsensusState, error) {
// the client is expired and either AllowUpdateAfterMisbehaviour or AllowUpdateAfterExpiry
// is set to true so light validation of the header is executed
if err := cs.checkProposedHeader(consensusState, header, currentTimestamp); err != nil {
return nil, nil, err
}
newClientState, consensusState := update(&cs, header)
return newClientState, consensusState, nil
}
// checkProposedHeader checks if the Tendermint header is valid for updating a client after
// a passed proposal.
// It returns an error if:
// - the header provided is not parseable to tendermint types
// - header height is less than or equal to the latest client state height
// - signed tendermint header is invalid
// - header timestamp is less than or equal to the latest consensus state timestamp
// - header timestamp is expired
// NOTE: header.ValidateBasic is called in the 02-client proposal handler. Additional checks
// on the validator set and the validator set hash are done in header.ValidateBasic.
func (cs ClientState) checkProposedHeader(consensusState *ConsensusState, header *Header, currentTimestamp time.Time) error {
tmSignedHeader, err := tmtypes.SignedHeaderFromProto(header.SignedHeader)
if err != nil {
return sdkerrors.Wrap(err, "signed header in not tendermint signed header type")
}
if !header.GetTime().After(consensusState.Timestamp) {
return sdkerrors.Wrapf(
clienttypes.ErrInvalidHeader,
"header timestamp is less than or equal to latest consensus state timestamp (%s ≤ %s)", header.GetTime(), consensusState.Timestamp)
}
// assert header height is newer than latest client state
if header.GetHeight().LTE(cs.GetLatestHeight()) {
return sdkerrors.Wrapf(
clienttypes.ErrInvalidHeader,
"header height ≤ consensus state height (%s ≤ %s)", header.GetHeight(), cs.GetLatestHeight(),
)
}
if err := tmSignedHeader.ValidateBasic(cs.GetChainID()); err != nil {
return sdkerrors.Wrap(err, "signed header failed basic validation")
}
if cs.IsExpired(header.GetTime(), currentTimestamp) {
return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "header timestamp is already expired")
}
return nil
}

View File

@ -0,0 +1,356 @@
package types_test
import (
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
)
var (
frozenHeight = clienttypes.NewHeight(0, 1)
)
// sanity checks
func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateStateBasic() {
clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint)
clientState := suite.chainA.GetClientState(clientA).(*types.ClientState)
clientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
// use nil header
cs, consState, err := clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, nil)
suite.Require().Error(err)
suite.Require().Nil(cs)
suite.Require().Nil(consState)
clientState.LatestHeight = clientState.LatestHeight.Increment()
// consensus state for latest height does not exist
cs, consState, err = clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, suite.chainA.LastHeader)
suite.Require().Error(err)
suite.Require().Nil(cs)
suite.Require().Nil(consState)
}
// to expire clients, time needs to be fast forwarded on both chainA and chainB.
// this is to prevent headers from failing when attempting to update later.
func (suite *TendermintTestSuite) TestCheckProposedHeaderAndUpdateState() {
testCases := []struct {
name string
AllowUpdateAfterExpiry bool
AllowUpdateAfterMisbehaviour bool
FreezeClient bool
ExpireClient bool
expPassUnfreeze bool // expected result using a header that passes stronger validation
expPassUnexpire bool // expected result using a header that passes weaker validation
}{
{
name: "not allowed to be updated, not frozen or expired",
AllowUpdateAfterExpiry: false,
AllowUpdateAfterMisbehaviour: false,
FreezeClient: false,
ExpireClient: false,
expPassUnfreeze: false,
expPassUnexpire: false,
},
{
name: "not allowed to be updated, client is frozen",
AllowUpdateAfterExpiry: false,
AllowUpdateAfterMisbehaviour: false,
FreezeClient: true,
ExpireClient: false,
expPassUnfreeze: false,
expPassUnexpire: false,
},
{
name: "not allowed to be updated, client is expired",
AllowUpdateAfterExpiry: false,
AllowUpdateAfterMisbehaviour: false,
FreezeClient: false,
ExpireClient: true,
expPassUnfreeze: false,
expPassUnexpire: false,
},
{
name: "not allowed to be updated, client is frozen and expired",
AllowUpdateAfterExpiry: false,
AllowUpdateAfterMisbehaviour: false,
FreezeClient: true,
ExpireClient: true,
expPassUnfreeze: false,
expPassUnexpire: false,
},
{
name: "allowed to be updated only after misbehaviour, not frozen or expired",
AllowUpdateAfterExpiry: false,
AllowUpdateAfterMisbehaviour: true,
FreezeClient: false,
ExpireClient: false,
expPassUnfreeze: false,
expPassUnexpire: false,
},
{
name: "PASS: allowed to be updated only after misbehaviour, client is frozen",
AllowUpdateAfterExpiry: false,
AllowUpdateAfterMisbehaviour: true,
FreezeClient: true,
ExpireClient: false,
expPassUnfreeze: true,
expPassUnexpire: false,
},
{
name: "allowed to be updated only after misbehaviour, client is expired",
AllowUpdateAfterExpiry: false,
AllowUpdateAfterMisbehaviour: true,
FreezeClient: false,
ExpireClient: true,
expPassUnfreeze: false,
expPassUnexpire: false,
},
{
name: "allowed to be updated only after misbehaviour, client is frozen and expired",
AllowUpdateAfterExpiry: false,
AllowUpdateAfterMisbehaviour: true,
FreezeClient: true,
ExpireClient: true,
expPassUnfreeze: true,
expPassUnexpire: true,
},
{
name: "allowed to be updated only after expiry, not frozen or expired",
AllowUpdateAfterExpiry: true,
AllowUpdateAfterMisbehaviour: false,
FreezeClient: false,
ExpireClient: false,
expPassUnfreeze: false,
expPassUnexpire: false,
},
{
name: "allowed to be updated only after expiry, client is frozen",
AllowUpdateAfterExpiry: true,
AllowUpdateAfterMisbehaviour: false,
FreezeClient: true,
ExpireClient: false,
expPassUnfreeze: false,
expPassUnexpire: false,
},
{
name: "PASS: allowed to be updated only after expiry, client is expired",
AllowUpdateAfterExpiry: true,
AllowUpdateAfterMisbehaviour: false,
FreezeClient: false,
ExpireClient: true,
expPassUnfreeze: true,
expPassUnexpire: true,
},
{
name: "allowed to be updated only after expiry, client is frozen and expired",
AllowUpdateAfterExpiry: true,
AllowUpdateAfterMisbehaviour: false,
FreezeClient: true,
ExpireClient: true,
expPassUnfreeze: false,
expPassUnexpire: false,
},
{
name: "allowed to be updated after expiry and misbehaviour, not frozen or expired",
AllowUpdateAfterExpiry: true,
AllowUpdateAfterMisbehaviour: true,
FreezeClient: false,
ExpireClient: false,
expPassUnfreeze: false,
expPassUnexpire: false,
},
{
name: "PASS: allowed to be updated after expiry and misbehaviour, client is frozen",
AllowUpdateAfterExpiry: true,
AllowUpdateAfterMisbehaviour: true,
FreezeClient: true,
ExpireClient: false,
expPassUnfreeze: true,
expPassUnexpire: false,
},
{
name: "PASS: allowed to be updated after expiry and misbehaviour, client is expired",
AllowUpdateAfterExpiry: true,
AllowUpdateAfterMisbehaviour: true,
FreezeClient: false,
ExpireClient: true,
expPassUnfreeze: true,
expPassUnexpire: true,
},
{
name: "PASS: allowed to be updated after expiry and misbehaviour, client is frozen and expired",
AllowUpdateAfterExpiry: true,
AllowUpdateAfterMisbehaviour: true,
FreezeClient: true,
ExpireClient: true,
expPassUnfreeze: true,
expPassUnexpire: true,
},
}
for _, tc := range testCases {
tc := tc
// for each test case a header used for unexpiring clients and unfreezing
// a client are each tested to ensure that unexpiry headers cannot update
// a client when a unfreezing header is required.
suite.Run(tc.name, func() {
// start by testing unexpiring the client
suite.SetupTest() // reset
// construct client state based on test case parameters
clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint)
clientState := suite.chainA.GetClientState(clientA).(*types.ClientState)
clientState.AllowUpdateAfterExpiry = tc.AllowUpdateAfterExpiry
clientState.AllowUpdateAfterMisbehaviour = tc.AllowUpdateAfterMisbehaviour
if tc.FreezeClient {
clientState.FrozenHeight = frozenHeight
}
if tc.ExpireClient {
suite.chainA.ExpireClient(clientState.TrustingPeriod)
suite.chainB.ExpireClient(clientState.TrustingPeriod)
suite.coordinator.CommitBlock(suite.chainA, suite.chainB)
}
// use next header for chainB to unfreeze client on chainA
unfreezeClientHeader, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA)
suite.Require().NoError(err)
clientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
cs, consState, err := clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, unfreezeClientHeader)
if tc.expPassUnfreeze {
suite.Require().NoError(err)
suite.Require().Equal(clienttypes.Height{}, cs.GetFrozenHeight())
suite.Require().NotNil(consState)
} else {
suite.Require().Error(err)
suite.Require().Nil(cs)
suite.Require().Nil(consState)
}
// use next header for chainB to unexpire clients but with empty trusted heights
// and validators. Update chainB time so header won't be expired.
unexpireClientHeader, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA)
suite.Require().NoError(err)
unexpireClientHeader.TrustedHeight = clienttypes.Height{}
unexpireClientHeader.TrustedValidators = nil
clientStore = suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
cs, consState, err = clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, unexpireClientHeader)
if tc.expPassUnexpire {
suite.Require().NoError(err)
suite.Require().NotNil(cs)
suite.Require().NotNil(consState)
} else {
suite.Require().Error(err)
suite.Require().Nil(cs)
suite.Require().Nil(consState)
}
})
}
}
// test softer validation on headers used for unexpiring clients
func (suite *TendermintTestSuite) TestCheckProposedHeader() {
var (
header *types.Header
clientState *types.ClientState
clientA string
err error
)
testCases := []struct {
name string
malleate func()
expPass bool
}{
{
"success", func() {}, true,
},
{
"invalid signed header", func() {
header.SignedHeader = nil
}, false,
},
{
"header time is less than or equal to consensus state timestamp", func() {
consensusState, found := suite.chainA.GetConsensusState(clientA, clientState.GetLatestHeight())
suite.Require().True(found)
consensusState.(*types.ConsensusState).Timestamp = header.GetTime()
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientA, clientState.GetLatestHeight(), consensusState)
// update block time so client is expired
suite.chainA.ExpireClient(clientState.TrustingPeriod)
suite.chainB.ExpireClient(clientState.TrustingPeriod)
suite.coordinator.CommitBlock(suite.chainA, suite.chainB)
}, false,
},
{
"header height is not newer than client state", func() {
consensusState, found := suite.chainA.GetConsensusState(clientA, clientState.GetLatestHeight())
suite.Require().True(found)
clientState.LatestHeight = header.GetHeight().(clienttypes.Height)
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientA, clientState.GetLatestHeight(), consensusState)
}, false,
},
{
"signed header failed validate basic - wrong chain ID", func() {
clientState.ChainId = ibctesting.InvalidID
}, false,
},
{
"header is already expired", func() {
// expire client
suite.chainA.ExpireClient(clientState.TrustingPeriod)
suite.chainB.ExpireClient(clientState.TrustingPeriod)
suite.coordinator.CommitBlock(suite.chainA, suite.chainB)
}, false,
},
}
for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
suite.SetupTest() // reset
clientA, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint)
clientState = suite.chainA.GetClientState(clientA).(*types.ClientState)
clientState.AllowUpdateAfterExpiry = true
clientState.AllowUpdateAfterMisbehaviour = false
// expire client
suite.chainA.ExpireClient(clientState.TrustingPeriod)
suite.chainB.ExpireClient(clientState.TrustingPeriod)
suite.coordinator.CommitBlock(suite.chainA, suite.chainB)
// use next header for chainB to unexpire clients but with empty trusted heights
// and validators.
header, err = suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientA)
suite.Require().NoError(err)
header.TrustedHeight = clienttypes.Height{}
header.TrustedValidators = nil
tc.malleate()
clientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
cs, consState, err := clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, header)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(cs)
suite.Require().NotNil(consState)
} else {
suite.Require().Error(err)
suite.Require().Nil(cs)
suite.Require().Nil(consState)
}
})
}
}

View File

@ -51,6 +51,12 @@ type ClientState struct {
LatestHeight types.Height `protobuf:"bytes,7,opt,name=latest_height,json=latestHeight,proto3" json:"latest_height" yaml:"latest_height"`
// Proof specifications used in verifying counterparty state
ProofSpecs []*_go.ProofSpec `protobuf:"bytes,8,rep,name=proof_specs,json=proofSpecs,proto3" json:"proof_specs,omitempty" yaml:"proof_specs"`
// This flag, when set to true, will allow governance to recover a client
// which has expired
AllowUpdateAfterExpiry bool `protobuf:"varint,9,opt,name=allow_update_after_expiry,json=allowUpdateAfterExpiry,proto3" json:"allow_update_after_expiry,omitempty" yaml:"allow_update_after_expiry"`
// This flag, when set to true, will allow governance to unfreeze a client
// whose chain has experienced a misbehaviour event
AllowUpdateAfterMisbehaviour bool `protobuf:"varint,10,opt,name=allow_update_after_misbehaviour,json=allowUpdateAfterMisbehaviour,proto3" json:"allow_update_after_misbehaviour,omitempty" yaml:"allow_update_after_misbehaviour"`
}
func (m *ClientState) Reset() { *m = ClientState{} }
@ -309,68 +315,72 @@ func init() {
func init() { proto.RegisterFile("ibc/tendermint/tendermint.proto", fileDescriptor_76a953d5a747dd66) }
var fileDescriptor_76a953d5a747dd66 = []byte{
// 963 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0xcd, 0x4e, 0x23, 0x47,
0x10, 0xf6, 0x0f, 0x0b, 0xa6, 0x6d, 0x03, 0xe9, 0x25, 0xac, 0x71, 0x58, 0x8f, 0xd5, 0xb9, 0x70,
0xd9, 0x99, 0xc5, 0xbb, 0x4a, 0x24, 0x8e, 0xc3, 0x2a, 0x82, 0x28, 0x2b, 0x91, 0x21, 0x9b, 0x44,
0x91, 0xa2, 0xd1, 0x78, 0xa6, 0x6d, 0xb7, 0x98, 0x99, 0xb6, 0xa6, 0xdb, 0xc8, 0xe4, 0x09, 0x92,
0xdb, 0x2a, 0xa7, 0x3d, 0x26, 0x6f, 0x91, 0x47, 0xd8, 0x53, 0xc4, 0x31, 0x27, 0x27, 0x82, 0x37,
0xf0, 0x31, 0xa7, 0xa8, 0x7f, 0xe6, 0xc7, 0x86, 0x08, 0xf6, 0x82, 0xbb, 0xab, 0xbe, 0xef, 0xab,
0xee, 0xea, 0xaa, 0x1a, 0x80, 0x41, 0xfa, 0xbe, 0xc5, 0x71, 0x1c, 0xe0, 0x24, 0x22, 0x31, 0x2f,
0x2c, 0xcd, 0x71, 0x42, 0x39, 0x85, 0x1b, 0xa4, 0xef, 0x9b, 0xb9, 0xb5, 0xdd, 0x2d, 0x82, 0x2f,
0xc7, 0x98, 0x59, 0x17, 0x5e, 0x48, 0x02, 0x8f, 0xd3, 0x44, 0x31, 0xda, 0x7b, 0xb7, 0x10, 0xf2,
0xaf, 0xf6, 0x3e, 0xf6, 0x69, 0x3c, 0x20, 0xd4, 0x1a, 0x27, 0x94, 0x0e, 0x52, 0x63, 0x67, 0x48,
0xe9, 0x30, 0xc4, 0x96, 0xdc, 0xf5, 0x27, 0x03, 0x2b, 0x98, 0x24, 0x1e, 0x27, 0x34, 0xd6, 0x7e,
0x63, 0xd9, 0xcf, 0x49, 0x84, 0x19, 0xf7, 0xa2, 0xb1, 0x06, 0x3c, 0x11, 0xd7, 0xf0, 0x43, 0x82,
0x63, 0xae, 0x7f, 0x52, 0xa6, 0x74, 0xd0, 0x28, 0x22, 0x3c, 0x92, 0xce, 0x6c, 0xa9, 0x01, 0xdb,
0x43, 0x3a, 0xa4, 0x72, 0x69, 0x89, 0x95, 0xb2, 0xa2, 0x3f, 0x1e, 0x81, 0xfa, 0x91, 0xd4, 0x39,
0xe3, 0x1e, 0xc7, 0x70, 0x17, 0xd4, 0xfc, 0x91, 0x47, 0x62, 0x97, 0x04, 0xad, 0x72, 0xb7, 0xbc,
0xbf, 0xee, 0xac, 0xc9, 0xfd, 0x49, 0x00, 0xdf, 0x80, 0x3a, 0x4f, 0x26, 0x8c, 0xbb, 0x21, 0xbe,
0xc0, 0x61, 0xab, 0xd2, 0x2d, 0xef, 0xd7, 0x7b, 0x2d, 0x73, 0x31, 0x6d, 0xe6, 0x17, 0x89, 0xe7,
0x8b, 0x0b, 0xd9, 0xed, 0xf7, 0x33, 0xa3, 0x34, 0x9f, 0x19, 0xf0, 0xd2, 0x8b, 0xc2, 0x43, 0x54,
0xa0, 0x22, 0x07, 0xc8, 0xdd, 0x57, 0x62, 0x03, 0x07, 0x60, 0x53, 0xee, 0x48, 0x3c, 0x74, 0xc7,
0x38, 0x21, 0x34, 0x68, 0x55, 0xa5, 0xf4, 0xae, 0xa9, 0x92, 0x61, 0xa6, 0xc9, 0x30, 0x5f, 0xe9,
0x64, 0xd9, 0x48, 0x6b, 0xef, 0x14, 0xb4, 0x73, 0x3e, 0x7a, 0xf7, 0xb7, 0x51, 0x76, 0x36, 0x52,
0xeb, 0xa9, 0x34, 0x42, 0x02, 0xb6, 0x26, 0x71, 0x9f, 0xc6, 0x41, 0x21, 0xd0, 0xca, 0x7d, 0x81,
0x3e, 0xd5, 0x81, 0x9e, 0xa8, 0x40, 0xcb, 0x02, 0x2a, 0xd2, 0x66, 0x66, 0xd6, 0xa1, 0x30, 0xd8,
0x8c, 0xbc, 0xa9, 0xeb, 0x87, 0xd4, 0x3f, 0x77, 0x83, 0x84, 0x0c, 0x78, 0xeb, 0xd1, 0x07, 0x5e,
0x69, 0x89, 0xaf, 0x02, 0x35, 0x23, 0x6f, 0x7a, 0x24, 0x8c, 0xaf, 0x84, 0x0d, 0xbe, 0x01, 0xcd,
0x41, 0x42, 0x7f, 0xc2, 0xb1, 0x3b, 0xc2, 0x64, 0x38, 0xe2, 0xad, 0x55, 0x19, 0x04, 0xca, 0x27,
0xd1, 0xc5, 0x71, 0x2c, 0x3d, 0xf6, 0x9e, 0x56, 0xdf, 0x56, 0xea, 0x0b, 0x34, 0xe4, 0x34, 0xd4,
0x5e, 0x61, 0x85, 0x6c, 0xe8, 0x71, 0xcc, 0x78, 0x2a, 0xbb, 0xf6, 0x50, 0xd9, 0x05, 0x1a, 0x72,
0x1a, 0x6a, 0xaf, 0x65, 0x4f, 0x40, 0x5d, 0xb6, 0x82, 0xcb, 0xc6, 0xd8, 0x67, 0xad, 0x5a, 0xb7,
0xba, 0x5f, 0xef, 0x6d, 0x99, 0xc4, 0x67, 0xbd, 0x17, 0xe6, 0xa9, 0xf0, 0x9c, 0x8d, 0xb1, 0x6f,
0xef, 0xe4, 0x25, 0x53, 0x80, 0x23, 0x07, 0x8c, 0x53, 0x08, 0x3b, 0x5c, 0xf9, 0xf9, 0x37, 0xa3,
0x84, 0xfe, 0xac, 0x80, 0x8d, 0x23, 0x1a, 0x33, 0x1c, 0xb3, 0x09, 0x53, 0xd5, 0x6b, 0x83, 0xf5,
0xac, 0x61, 0x64, 0xf9, 0xd6, 0x7b, 0xed, 0x5b, 0x29, 0xff, 0x26, 0x45, 0xd8, 0x35, 0x71, 0xfc,
0xb7, 0x22, 0xb3, 0x39, 0x0d, 0xbe, 0x04, 0x2b, 0x09, 0xa5, 0x5c, 0xd7, 0x77, 0x5b, 0xdd, 0x3a,
0x6f, 0xa6, 0xd7, 0x38, 0x39, 0x0f, 0xb1, 0x43, 0x29, 0xb7, 0x57, 0x04, 0xdd, 0x91, 0x68, 0xf8,
0x1c, 0xac, 0xea, 0x6c, 0x55, 0xff, 0x37, 0x5b, 0x0a, 0xaf, 0x71, 0xf0, 0x97, 0x32, 0xd8, 0x8e,
0xf1, 0x94, 0xbb, 0xd9, 0x58, 0x61, 0xee, 0xc8, 0x63, 0x23, 0x59, 0x94, 0x0d, 0xfb, 0xbb, 0xf9,
0xcc, 0xf8, 0x44, 0xe5, 0xe1, 0x2e, 0x14, 0xfa, 0x77, 0x66, 0xbc, 0x1c, 0x12, 0x3e, 0x9a, 0xf4,
0xc5, 0xe9, 0xee, 0x9e, 0x6c, 0x56, 0x48, 0xfa, 0xcc, 0xea, 0x5f, 0x72, 0xcc, 0xcc, 0x63, 0x3c,
0xb5, 0xc5, 0xc2, 0x81, 0x42, 0xee, 0xdb, 0x4c, 0xed, 0xd8, 0x63, 0x23, 0x9d, 0xd0, 0xdf, 0x2b,
0xa0, 0xf1, 0x9a, 0xb0, 0x3e, 0x1e, 0x79, 0x17, 0x84, 0x4e, 0x12, 0x78, 0x00, 0xd6, 0xd5, 0x0d,
0xb2, 0x69, 0x60, 0x6f, 0xcf, 0x67, 0xc6, 0x96, 0x3a, 0x56, 0xe6, 0x42, 0x4e, 0x4d, 0xad, 0x4f,
0x02, 0x68, 0x16, 0xe6, 0x47, 0x45, 0x32, 0x1e, 0xcf, 0x67, 0xc6, 0xa6, 0x66, 0x68, 0x0f, 0xca,
0x87, 0xca, 0xd7, 0xa0, 0x36, 0xc2, 0x5e, 0x80, 0x13, 0xf7, 0x40, 0x67, 0x6e, 0x67, 0x79, 0xa2,
0x1c, 0x4b, 0xbf, 0xdd, 0xb9, 0x9e, 0x19, 0x6b, 0x6a, 0x7d, 0x90, 0x4b, 0xa6, 0x64, 0xe4, 0xac,
0xa9, 0xe5, 0x41, 0x41, 0xb2, 0xa7, 0x1b, 0xfc, 0x01, 0x92, 0xbd, 0x5b, 0x92, 0xbd, 0x4c, 0xb2,
0x77, 0x58, 0x13, 0xf9, 0x79, 0x27, 0x72, 0xf4, 0x6b, 0x15, 0xac, 0x2a, 0x06, 0xf4, 0x40, 0x93,
0x91, 0x61, 0x8c, 0x03, 0x57, 0xc1, 0x74, 0xc1, 0x75, 0x8a, 0x81, 0xd4, 0x07, 0xe1, 0x4c, 0xc2,
0x74, 0xd0, 0xbd, 0xab, 0x99, 0x51, 0xce, 0x7b, 0x66, 0x41, 0x02, 0x39, 0x0d, 0x56, 0xc0, 0xc2,
0x1f, 0x41, 0x33, 0x7b, 0x77, 0x97, 0xe1, 0xb4, 0x28, 0xef, 0x08, 0x91, 0x3d, 0xe8, 0x19, 0xe6,
0x76, 0x2b, 0x97, 0x5f, 0xa0, 0x23, 0xa7, 0x71, 0x51, 0xc0, 0xc1, 0xef, 0x81, 0x1a, 0x92, 0x32,
0xfe, 0x3d, 0xc5, 0xfb, 0x54, 0xb7, 0xfa, 0xc7, 0x85, 0x91, 0x9b, 0xf1, 0x90, 0xd3, 0xd4, 0x06,
0xdd, 0xec, 0x21, 0x80, 0x29, 0x22, 0x2f, 0x5c, 0xfd, 0x1a, 0xf7, 0x9d, 0xfe, 0xe9, 0x7c, 0x66,
0xec, 0x2e, 0x46, 0xc9, 0x35, 0x90, 0xf3, 0x91, 0x36, 0xe6, 0x25, 0x8c, 0xbe, 0x04, 0xb5, 0xf4,
0xb3, 0x03, 0xf7, 0xc0, 0x7a, 0x3c, 0x89, 0x70, 0x22, 0x3c, 0xf2, 0x45, 0xaa, 0x4e, 0x6e, 0x80,
0x5d, 0x50, 0x0f, 0x70, 0x4c, 0x23, 0x12, 0x4b, 0x7f, 0x45, 0xfa, 0x8b, 0x26, 0xfb, 0xf4, 0xfd,
0x75, 0xa7, 0x7c, 0x75, 0xdd, 0x29, 0xff, 0x73, 0xdd, 0x29, 0xbf, 0xbd, 0xe9, 0x94, 0xae, 0x6e,
0x3a, 0xa5, 0xbf, 0x6e, 0x3a, 0xa5, 0x1f, 0x3e, 0x2b, 0xb4, 0x9b, 0x4f, 0x59, 0x44, 0x99, 0xfe,
0x79, 0xc6, 0x82, 0x73, 0x6b, 0x6a, 0x89, 0x0f, 0xf0, 0xf3, 0xcf, 0x9f, 0x2d, 0xff, 0x53, 0xd0,
0x5f, 0x95, 0x93, 0xe7, 0xc5, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x86, 0x4d, 0xba, 0x76, 0x82,
0x08, 0x00, 0x00,
// 1039 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x4f, 0x6f, 0xe3, 0x44,
0x14, 0x6f, 0xda, 0xd2, 0xa6, 0x93, 0xf4, 0x0f, 0xb3, 0xa5, 0xeb, 0x96, 0x6c, 0x1c, 0x0d, 0x08,
0x55, 0x48, 0x6b, 0x6f, 0xb3, 0x2b, 0x90, 0x7a, 0xc3, 0x5d, 0x50, 0x8b, 0x58, 0xa9, 0xb8, 0x14,
0x10, 0x12, 0xb2, 0x1c, 0x7b, 0x92, 0x8c, 0x6a, 0x7b, 0x8c, 0x67, 0x52, 0x52, 0x3e, 0x01, 0x48,
0x1c, 0x56, 0x9c, 0xf6, 0x08, 0xdf, 0x66, 0x4f, 0xa8, 0x47, 0x4e, 0x06, 0xb5, 0xdf, 0x20, 0x47,
0x4e, 0xc8, 0x33, 0xe3, 0x3f, 0x49, 0x5b, 0x75, 0xb9, 0xb4, 0x33, 0xef, 0xf7, 0xe7, 0xd9, 0x6f,
0xde, 0x3c, 0x07, 0xe8, 0xa4, 0xe7, 0x99, 0x1c, 0x47, 0x3e, 0x4e, 0x42, 0x12, 0xf1, 0xca, 0xd2,
0x88, 0x13, 0xca, 0x29, 0x5c, 0x23, 0x3d, 0xcf, 0x28, 0xa3, 0x3b, 0x9d, 0x2a, 0xf9, 0x22, 0xc6,
0xcc, 0x3c, 0x77, 0x03, 0xe2, 0xbb, 0x9c, 0x26, 0x52, 0xb1, 0xd3, 0xba, 0xc1, 0x10, 0x7f, 0x15,
0xfa, 0xc0, 0xa3, 0x51, 0x9f, 0x50, 0x33, 0x4e, 0x28, 0xed, 0xe7, 0xc1, 0xf6, 0x80, 0xd2, 0x41,
0x80, 0x4d, 0xb1, 0xeb, 0x8d, 0xfa, 0xa6, 0x3f, 0x4a, 0x5c, 0x4e, 0x68, 0xa4, 0x70, 0x7d, 0x16,
0xe7, 0x24, 0xc4, 0x8c, 0xbb, 0x61, 0xac, 0x08, 0x0f, 0xb3, 0xd7, 0xf0, 0x02, 0x82, 0x23, 0xae,
0xfe, 0xe5, 0x4a, 0x01, 0xd0, 0x30, 0x24, 0x3c, 0x14, 0x60, 0xb1, 0x54, 0x84, 0xcd, 0x01, 0x1d,
0x50, 0xb1, 0x34, 0xb3, 0x95, 0x8c, 0xa2, 0x5f, 0x97, 0x41, 0xe3, 0x40, 0xf8, 0x9c, 0x70, 0x97,
0x63, 0xb8, 0x0d, 0xea, 0xde, 0xd0, 0x25, 0x91, 0x43, 0x7c, 0xad, 0xd6, 0xa9, 0xed, 0xae, 0xd8,
0xcb, 0x62, 0x7f, 0xe4, 0xc3, 0x53, 0xd0, 0xe0, 0xc9, 0x88, 0x71, 0x27, 0xc0, 0xe7, 0x38, 0xd0,
0xe6, 0x3b, 0xb5, 0xdd, 0x46, 0x57, 0x33, 0xa6, 0xcb, 0x66, 0x7c, 0x96, 0xb8, 0x5e, 0xf6, 0x42,
0xd6, 0xce, 0xeb, 0x54, 0x9f, 0x9b, 0xa4, 0x3a, 0xbc, 0x70, 0xc3, 0x60, 0x1f, 0x55, 0xa4, 0xc8,
0x06, 0x62, 0xf7, 0x45, 0xb6, 0x81, 0x7d, 0xb0, 0x2e, 0x76, 0x24, 0x1a, 0x38, 0x31, 0x4e, 0x08,
0xf5, 0xb5, 0x05, 0x61, 0xbd, 0x6d, 0xc8, 0x62, 0x18, 0x79, 0x31, 0x8c, 0xe7, 0xaa, 0x58, 0x16,
0x52, 0xde, 0x5b, 0x15, 0xef, 0x52, 0x8f, 0x5e, 0xfd, 0xad, 0xd7, 0xec, 0xb5, 0x3c, 0x7a, 0x2c,
0x82, 0x90, 0x80, 0x8d, 0x51, 0xd4, 0xa3, 0x91, 0x5f, 0x49, 0xb4, 0x78, 0x5f, 0xa2, 0xf7, 0x54,
0xa2, 0x87, 0x32, 0xd1, 0xac, 0x81, 0xcc, 0xb4, 0x5e, 0x84, 0x55, 0x2a, 0x0c, 0xd6, 0x43, 0x77,
0xec, 0x78, 0x01, 0xf5, 0xce, 0x1c, 0x3f, 0x21, 0x7d, 0xae, 0xbd, 0xf5, 0x3f, 0x5f, 0x69, 0x46,
0x2f, 0x13, 0xad, 0x86, 0xee, 0xf8, 0x20, 0x0b, 0x3e, 0xcf, 0x62, 0xf0, 0x14, 0xac, 0xf6, 0x13,
0xfa, 0x13, 0x8e, 0x9c, 0x21, 0x26, 0x83, 0x21, 0xd7, 0x96, 0x44, 0x12, 0x28, 0x8e, 0x44, 0x35,
0xc7, 0xa1, 0x40, 0xac, 0x96, 0x72, 0xdf, 0x94, 0xee, 0x53, 0x32, 0x64, 0x37, 0xe5, 0x5e, 0x72,
0x33, 0xdb, 0xc0, 0xe5, 0x98, 0xf1, 0xdc, 0x76, 0xf9, 0x4d, 0x6d, 0xa7, 0x64, 0xc8, 0x6e, 0xca,
0xbd, 0xb2, 0x3d, 0x02, 0x0d, 0x71, 0x15, 0x1c, 0x16, 0x63, 0x8f, 0x69, 0xf5, 0xce, 0xc2, 0x6e,
0xa3, 0xbb, 0x61, 0x10, 0x8f, 0x75, 0x9f, 0x1a, 0xc7, 0x19, 0x72, 0x12, 0x63, 0xcf, 0xda, 0x2a,
0x5b, 0xa6, 0x42, 0x47, 0x36, 0x88, 0x73, 0x0a, 0x83, 0x0e, 0xd8, 0x76, 0x83, 0x80, 0xfe, 0xe8,
0x8c, 0x62, 0xdf, 0xe5, 0xd8, 0x71, 0xfb, 0x1c, 0x27, 0x0e, 0x1e, 0xc7, 0x24, 0xb9, 0xd0, 0x56,
0x3a, 0xb5, 0xdd, 0xba, 0xf5, 0xfe, 0x24, 0xd5, 0x3b, 0xd2, 0xe6, 0x4e, 0x2a, 0xb2, 0xb7, 0x04,
0x76, 0x2a, 0xa0, 0x4f, 0x32, 0xe4, 0x53, 0x01, 0xc0, 0x1f, 0x80, 0x7e, 0x8b, 0x2a, 0x24, 0xac,
0x87, 0x87, 0xee, 0x39, 0xa1, 0xa3, 0x44, 0x03, 0x22, 0xcd, 0x87, 0x93, 0x54, 0xff, 0xe0, 0xce,
0x34, 0x55, 0x01, 0xb2, 0x5b, 0xb3, 0xc9, 0x5e, 0x54, 0xe0, 0xfd, 0xc5, 0x9f, 0x7f, 0xd7, 0xe7,
0xd0, 0x9f, 0xf3, 0x60, 0xed, 0x80, 0x46, 0x0c, 0x47, 0x6c, 0xc4, 0xe4, 0x8d, 0xb4, 0xc0, 0x4a,
0x31, 0x04, 0xc4, 0x95, 0x6c, 0x74, 0x77, 0x6e, 0xb4, 0xd1, 0x57, 0x39, 0xc3, 0xaa, 0x67, 0x47,
0xf2, 0x32, 0xeb, 0x96, 0x52, 0x06, 0x9f, 0x81, 0xc5, 0x84, 0x52, 0xae, 0xee, 0xec, 0x8e, 0x3c,
0xc9, 0x72, 0x40, 0xbc, 0xc0, 0xc9, 0x59, 0x80, 0x6d, 0x4a, 0xb9, 0xb5, 0x98, 0xc9, 0x6d, 0xc1,
0x86, 0x4f, 0xc0, 0x92, 0xea, 0x80, 0x85, 0x3b, 0x3b, 0x40, 0xf2, 0x15, 0x0f, 0xfe, 0x52, 0x03,
0x9b, 0x11, 0x1e, 0x73, 0xa7, 0x18, 0x95, 0xcc, 0x19, 0xba, 0x6c, 0x28, 0x2e, 0x5a, 0xd3, 0xfa,
0x66, 0x92, 0xea, 0xef, 0xca, 0x6a, 0xdd, 0xc6, 0x42, 0xff, 0xa6, 0xfa, 0xb3, 0x01, 0xe1, 0xc3,
0x51, 0x2f, 0x7b, 0xba, 0xdb, 0xa7, 0xb5, 0x19, 0x90, 0x1e, 0x33, 0x7b, 0x17, 0x1c, 0x33, 0xe3,
0x10, 0x8f, 0xad, 0x6c, 0x61, 0xc3, 0xcc, 0xee, 0xeb, 0xc2, 0xed, 0xd0, 0x65, 0x43, 0x55, 0xd0,
0x3f, 0xe6, 0x41, 0xb3, 0x5a, 0x67, 0xb8, 0x07, 0x56, 0xe4, 0x1b, 0x14, 0x13, 0xce, 0xda, 0x9c,
0xa4, 0xfa, 0x86, 0x7c, 0xac, 0x02, 0x42, 0x76, 0x5d, 0xae, 0x8f, 0x7c, 0x68, 0x54, 0x66, 0xe2,
0xbc, 0x50, 0x3c, 0x98, 0xa4, 0xfa, 0xba, 0x52, 0x28, 0x04, 0x95, 0x83, 0xf2, 0x4b, 0x50, 0x1f,
0x62, 0xd7, 0xc7, 0x89, 0xb3, 0xa7, 0x2a, 0xb7, 0x35, 0x3b, 0x25, 0x0f, 0x05, 0x6e, 0xb5, 0xaf,
0x52, 0x7d, 0x59, 0xae, 0xf7, 0x4a, 0xcb, 0x5c, 0x8c, 0xec, 0x65, 0xb9, 0xdc, 0xab, 0x58, 0x76,
0xd5, 0xd0, 0x7a, 0x03, 0xcb, 0xee, 0x0d, 0xcb, 0x6e, 0x61, 0xd9, 0xdd, 0xaf, 0x67, 0xf5, 0x79,
0x95, 0xd5, 0xe8, 0xb7, 0x05, 0xb0, 0x24, 0x15, 0xd0, 0x05, 0xab, 0x8c, 0x0c, 0x22, 0xec, 0x3b,
0x92, 0xa6, 0x1a, 0xae, 0x5d, 0x4d, 0x24, 0x3f, 0x72, 0x27, 0x82, 0xa6, 0x92, 0xb6, 0x2e, 0x53,
0xbd, 0x56, 0xce, 0x81, 0x29, 0x0b, 0x64, 0x37, 0x59, 0x85, 0x0b, 0xbf, 0x07, 0xab, 0xc5, 0xb9,
0x3b, 0x0c, 0xe7, 0x4d, 0x79, 0x4b, 0x8a, 0xe2, 0x40, 0x4f, 0x30, 0xb7, 0xb4, 0xd2, 0x7e, 0x4a,
0x8e, 0xec, 0xe6, 0x79, 0x85, 0x07, 0xbf, 0x05, 0x72, 0xf0, 0x8b, 0xfc, 0xf7, 0x34, 0xef, 0x23,
0x35, 0xbe, 0xde, 0xa9, 0x7c, 0x46, 0x0a, 0x1d, 0xb2, 0x57, 0x55, 0x40, 0x0d, 0xb0, 0x00, 0xc0,
0x9c, 0x51, 0x36, 0xae, 0x3a, 0x8d, 0xfb, 0x9e, 0xfe, 0xd1, 0x24, 0xd5, 0xb7, 0xa7, 0xb3, 0x94,
0x1e, 0xc8, 0x7e, 0x5b, 0x05, 0xcb, 0x16, 0x46, 0x9f, 0x83, 0x7a, 0xfe, 0x29, 0x85, 0x2d, 0xb0,
0x12, 0x8d, 0x42, 0x9c, 0x64, 0x88, 0x38, 0x91, 0x05, 0xbb, 0x0c, 0xc0, 0x0e, 0x68, 0xf8, 0x38,
0xa2, 0x21, 0x89, 0x04, 0x3e, 0x2f, 0xf0, 0x6a, 0xc8, 0x3a, 0x7e, 0x7d, 0xd5, 0xae, 0x5d, 0x5e,
0xb5, 0x6b, 0xff, 0x5c, 0xb5, 0x6b, 0x2f, 0xaf, 0xdb, 0x73, 0x97, 0xd7, 0xed, 0xb9, 0xbf, 0xae,
0xdb, 0x73, 0xdf, 0x7d, 0x54, 0xb9, 0x6e, 0x1e, 0x65, 0x21, 0x65, 0xea, 0xdf, 0x63, 0xe6, 0x9f,
0x99, 0x63, 0x33, 0xfb, 0x51, 0xf1, 0xe4, 0xe3, 0xc7, 0xb3, 0x3f, 0x74, 0x7a, 0x4b, 0x62, 0xf2,
0x3c, 0xfd, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xae, 0xae, 0x92, 0x56, 0x09, 0x00, 0x00,
}
func (m *ClientState) Marshal() (dAtA []byte, err error) {
@ -393,6 +403,26 @@ func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if m.AllowUpdateAfterMisbehaviour {
i--
if m.AllowUpdateAfterMisbehaviour {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x50
}
if m.AllowUpdateAfterExpiry {
i--
if m.AllowUpdateAfterExpiry {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x48
}
if len(m.ProofSpecs) > 0 {
for iNdEx := len(m.ProofSpecs) - 1; iNdEx >= 0; iNdEx-- {
{
@ -731,6 +761,12 @@ func (m *ClientState) Size() (n int) {
n += 1 + l + sovTendermint(uint64(l))
}
}
if m.AllowUpdateAfterExpiry {
n += 2
}
if m.AllowUpdateAfterMisbehaviour {
n += 2
}
return n
}
@ -1115,6 +1151,46 @@ func (m *ClientState) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 9:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field AllowUpdateAfterExpiry", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTendermint
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.AllowUpdateAfterExpiry = bool(v != 0)
case 10:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field AllowUpdateAfterMisbehaviour", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTendermint
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.AllowUpdateAfterMisbehaviour = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipTendermint(dAtA[iNdEx:])

View File

@ -45,7 +45,7 @@ func (cs ClientState) CheckHeaderAndUpdateState(
)
}
// Get consensus bytes from clientStore
// get consensus state from clientStore
tmConsState, err := GetConsensusState(clientStore, cdc, tmHeader.TrustedHeight)
if err != nil {
return nil, nil, sdkerrors.Wrapf(

View File

@ -50,7 +50,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "successful update with next height and same validator set",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, suite.valSet, suite.valSet, signers)
currentTime = suite.now
@ -60,7 +60,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "successful update with future height and different validator set",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, epochHeight+5, epochHeight, suite.headerTime, bothValSet, suite.valSet, bothSigners)
currentTime = suite.now
@ -70,7 +70,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "successful update with next height and different validator set",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, bothValSet.Hash())
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, bothValSet, bothValSet, bothSigners)
currentTime = suite.now
@ -80,7 +80,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "successful update for a previous height",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), heightMinus3, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, epochHeight-1, epochHeight-3, suite.headerTime, bothValSet, suite.valSet, bothSigners)
currentTime = suite.now
@ -90,7 +90,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "unsuccessful update with incorrect header chain-id",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader("ethermint", int64(height.EpochHeight+1), int64(height.EpochHeight), suite.headerTime, suite.valSet, suite.valSet, signers)
currentTime = suite.now
@ -100,7 +100,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "unsuccessful update with next height: update header mismatches nextValSetHash",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, bothValSet, suite.valSet, bothSigners)
currentTime = suite.now
@ -110,7 +110,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "unsuccessful update with next height: update header mismatches different nextValSetHash",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, bothValSet.Hash())
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, suite.valSet, bothValSet, signers)
currentTime = suite.now
@ -120,7 +120,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "unsuccessful update with future height: too much change in validator set",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, epochHeight+5, epochHeight, suite.headerTime, altValSet, suite.valSet, altSigners)
currentTime = suite.now
@ -130,7 +130,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "unsuccessful updates, passed in incorrect trusted validators for given consensus state",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, epochHeight+5, epochHeight, suite.headerTime, bothValSet, bothValSet, bothSigners)
currentTime = suite.now
@ -140,7 +140,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "unsuccessful update: trusting period has passed since last client timestamp",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, suite.valSet, suite.valSet, signers)
// make current time pass trusting period from last timestamp on clientstate
@ -151,7 +151,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "unsuccessful update: header timestamp is past current timestamp",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers)
currentTime = suite.now
@ -161,7 +161,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "unsuccessful update: header timestamp is not past last client timestamp",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.clientTime, suite.valSet, suite.valSet, signers)
currentTime = suite.now
@ -171,7 +171,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "header basic validation failed",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, suite.valSet, suite.valSet, signers)
// cause new header to fail validatebasic by changing commit height to mismatch header height
@ -183,7 +183,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
{
name: "header height < consensus height",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, heightPlus5, commitmenttypes.GetSDKSpecs())
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, heightPlus5, commitmenttypes.GetSDKSpecs(), false, false)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
// Make new header at height less than latest client state
newHeader = types.CreateTestHeader(chainID, epochHeight-1, epochHeight, suite.headerTime, suite.valSet, suite.valSet, signers)

View File

@ -90,6 +90,14 @@ func (cs ClientState) CheckMisbehaviourAndUpdateState(
return nil, sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "cannot submit misbehaviour to localhost client")
}
// CheckProposedHeaderAndUpdateState returns an error. The localhost cannot be modified by
// proposals.
func (cs ClientState) CheckProposedHeaderAndUpdateState(
ctx sdk.Context, _ codec.BinaryMarshaler, _ sdk.KVStore, _ exported.Header,
) (exported.ClientState, exported.ConsensusState, error) {
return nil, nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "cannot update localhost client with a proposal")
}
// VerifyClientState verifies that the localhost client state is stored locally
func (cs ClientState) VerifyClientState(
store sdk.KVStore, cdc codec.BinaryMarshaler, _ exported.Root,

View File

@ -128,6 +128,21 @@ func (suite *LocalhostTestSuite) TestCheckHeaderAndUpdateState() {
suite.Require().Equal(suite.ctx.BlockHeader().ChainID, clientState.ChainId)
}
func (suite *LocalhostTestSuite) TestMisbehaviourAndUpdateState() {
clientState := types.NewClientState("chainID", clientHeight)
cs, err := clientState.CheckMisbehaviourAndUpdateState(suite.ctx, nil, nil, nil)
suite.Require().Error(err)
suite.Require().Nil(cs)
}
func (suite *LocalhostTestSuite) TestProposedHeaderAndUpdateState() {
clientState := types.NewClientState("chainID", clientHeight)
cs, consState, err := clientState.CheckProposedHeaderAndUpdateState(suite.ctx, nil, nil, nil)
suite.Require().Error(err)
suite.Require().Nil(cs)
suite.Require().Nil(consState)
}
func (suite *LocalhostTestSuite) TestVerifyConnectionState() {
counterparty := connectiontypes.NewCounterparty("clientB", testConnectionID, commitmenttypes.NewMerklePrefix([]byte("ibc")))
conn1 := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, []string{"1.0.0"})

View File

@ -24,6 +24,7 @@ type ClientState interface {
CheckHeaderAndUpdateState(sdk.Context, codec.BinaryMarshaler, sdk.KVStore, Header) (ClientState, ConsensusState, error)
CheckMisbehaviourAndUpdateState(sdk.Context, codec.BinaryMarshaler, sdk.KVStore, Misbehaviour) (ClientState, error)
CheckProposedHeaderAndUpdateState(sdk.Context, codec.BinaryMarshaler, sdk.KVStore, Header) (ClientState, ConsensusState, error)
// State verification functions

View File

@ -37,7 +37,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
ClientGenesis: clienttypes.NewGenesisState(
[]clienttypes.IdentifiedClientState{
clienttypes.NewIdentifiedClientState(
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs()),
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false),
),
clienttypes.NewIdentifiedClientState(
exported.ClientTypeLocalHost, localhosttypes.NewClientState("chaindID", clientHeight),
@ -97,7 +97,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
ClientGenesis: clienttypes.NewGenesisState(
[]clienttypes.IdentifiedClientState{
clienttypes.NewIdentifiedClientState(
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs()),
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false),
),
clienttypes.NewIdentifiedClientState(
exported.ClientTypeLocalHost, localhosttypes.NewClientState("(chaindID)", clienttypes.Height{}),
@ -166,7 +166,7 @@ func (suite *IBCTestSuite) TestInitGenesis() {
ClientGenesis: clienttypes.NewGenesisState(
[]clienttypes.IdentifiedClientState{
clienttypes.NewIdentifiedClientState(
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs()),
clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), false, false),
),
clienttypes.NewIdentifiedClientState(
exported.ClientTypeLocalHost, localhosttypes.NewClientState("chaindID", clientHeight),

View File

@ -9,6 +9,7 @@ import (
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/version"
@ -16,9 +17,13 @@ import (
"github.com/cosmos/cosmos-sdk/x/ibc/light-clients/solomachine/types"
)
const (
flagAllowUpdateAfterProposal = "allow_update_after_proposal"
)
// NewCreateClientCmd defines the command to create a new solo machine client.
func NewCreateClientCmd() *cobra.Command {
return &cobra.Command{
cmd := &cobra.Command{
Use: "create [client-id] [path/to/consensus_state.json]",
Short: "create new solo machine client",
Long: "create a new solo machine client with the specified identifier and consensus state",
@ -47,7 +52,9 @@ func NewCreateClientCmd() *cobra.Command {
}
}
clientState := types.NewClientState(consensusState)
allowUpdateAfterProposal, _ := cmd.Flags().GetBool(flagAllowUpdateAfterProposal)
clientState := types.NewClientState(consensusState, allowUpdateAfterProposal)
msg, err := clienttypes.NewMsgCreateClient(clientID, clientState, consensusState, clientCtx.GetFromAddress())
if err != nil {
return err
@ -60,6 +67,11 @@ func NewCreateClientCmd() *cobra.Command {
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
cmd.Flags().Bool(flagAllowUpdateAfterProposal, false, "allow governance proposal to update client")
flags.AddTxFlagsToCmd(cmd)
return cmd
}
// NewUpdateClientCmd defines the command to update a solo machine client.

View File

@ -15,10 +15,11 @@ import (
var _ exported.ClientState = (*ClientState)(nil)
// NewClientState creates a new ClientState instance.
func NewClientState(consensusState *ConsensusState) *ClientState {
func NewClientState(consensusState *ConsensusState, allowUpdateAfterProposal bool) *ClientState {
return &ClientState{
FrozenSequence: 0,
ConsensusState: consensusState,
FrozenSequence: 0,
ConsensusState: consensusState,
AllowUpdateAfterProposal: allowUpdateAfterProposal,
}
}

View File

@ -40,17 +40,17 @@ func (suite *SoloMachineTestSuite) TestClientStateValidateBasic() {
},
{
"sequence is zero",
types.NewClientState(&types.ConsensusState{0, suite.solomachine.ConsensusState().PublicKey, suite.solomachine.Time}),
types.NewClientState(&types.ConsensusState{0, suite.solomachine.ConsensusState().PublicKey, suite.solomachine.Time}, false),
false,
},
{
"timstamp is zero",
types.NewClientState(&types.ConsensusState{1, suite.solomachine.ConsensusState().PublicKey, 0}),
types.NewClientState(&types.ConsensusState{1, suite.solomachine.ConsensusState().PublicKey, 0}, false),
false,
},
{
"pubkey is empty",
types.NewClientState(&types.ConsensusState{suite.solomachine.Sequence, nil, suite.solomachine.Time}),
types.NewClientState(&types.ConsensusState{suite.solomachine.Sequence, nil, suite.solomachine.Time}, false),
false,
},
}
@ -117,14 +117,14 @@ func (suite *SoloMachineTestSuite) TestVerifyClientState() {
},
{
"client is frozen",
&types.ClientState{1, suite.solomachine.ConsensusState()},
&types.ClientState{1, suite.solomachine.ConsensusState(), false},
prefix,
proof,
false,
},
{
"consensus state in client state is nil",
types.NewClientState(nil),
types.NewClientState(nil, false),
prefix,
proof,
false,
@ -136,7 +136,7 @@ func (suite *SoloMachineTestSuite) TestVerifyClientState() {
Sequence: suite.solomachine.Sequence - 1,
Timestamp: suite.solomachine.Time,
PublicKey: suite.solomachine.ConsensusState().PublicKey,
}),
}, false),
prefix,
proof,
false,
@ -148,7 +148,7 @@ func (suite *SoloMachineTestSuite) TestVerifyClientState() {
Sequence: suite.solomachine.Sequence,
Timestamp: suite.solomachine.Time + 1,
PublicKey: suite.solomachine.ConsensusState().PublicKey,
}),
}, false),
prefix,
proof,
false,
@ -242,14 +242,14 @@ func (suite *SoloMachineTestSuite) TestVerifyClientConsensusState() {
},
{
"client is frozen",
&types.ClientState{1, suite.solomachine.ConsensusState()},
&types.ClientState{1, suite.solomachine.ConsensusState(), false},
prefix,
proof,
false,
},
{
"consensus state in client state is nil",
types.NewClientState(nil),
types.NewClientState(nil, false),
prefix,
proof,
false,
@ -261,7 +261,7 @@ func (suite *SoloMachineTestSuite) TestVerifyClientConsensusState() {
Sequence: suite.solomachine.Sequence - 1,
Timestamp: suite.solomachine.Time,
PublicKey: suite.solomachine.ConsensusState().PublicKey,
}),
}, false),
prefix,
proof,
false,
@ -273,7 +273,7 @@ func (suite *SoloMachineTestSuite) TestVerifyClientConsensusState() {
Sequence: suite.solomachine.Sequence,
Timestamp: suite.solomachine.Time + 1,
PublicKey: suite.solomachine.ConsensusState().PublicKey,
}),
}, false),
prefix,
proof,
false,
@ -363,7 +363,7 @@ func (suite *SoloMachineTestSuite) TestVerifyConnectionState() {
},
{
"client is frozen",
&types.ClientState{1, suite.solomachine.ConsensusState()},
&types.ClientState{1, suite.solomachine.ConsensusState(), false},
prefix,
proof,
false,
@ -446,7 +446,7 @@ func (suite *SoloMachineTestSuite) TestVerifyChannelState() {
},
{
"client is frozen",
&types.ClientState{1, suite.solomachine.ConsensusState()},
&types.ClientState{1, suite.solomachine.ConsensusState(), false},
prefix,
proof,
false,
@ -526,7 +526,7 @@ func (suite *SoloMachineTestSuite) TestVerifyPacketCommitment() {
},
{
"client is frozen",
&types.ClientState{1, suite.solomachine.ConsensusState()},
&types.ClientState{1, suite.solomachine.ConsensusState(), false},
prefix,
proof,
false,
@ -606,7 +606,7 @@ func (suite *SoloMachineTestSuite) TestVerifyPacketAcknowledgement() {
},
{
"client is frozen",
&types.ClientState{1, suite.solomachine.ConsensusState()},
&types.ClientState{1, suite.solomachine.ConsensusState(), false},
prefix,
proof,
false,
@ -685,7 +685,7 @@ func (suite *SoloMachineTestSuite) TestVerifyPacketAcknowledgementAbsence() {
},
{
"client is frozen",
&types.ClientState{1, suite.solomachine.ConsensusState()},
&types.ClientState{1, suite.solomachine.ConsensusState(), false},
prefix,
proof,
false,
@ -765,7 +765,7 @@ func (suite *SoloMachineTestSuite) TestVerifyNextSeqRecv() {
},
{
"client is frozen",
&types.ClientState{1, suite.solomachine.ConsensusState()},
&types.ClientState{1, suite.solomachine.ConsensusState(), false},
prefix,
proof,
false,

View File

@ -38,7 +38,7 @@ func (suite *SoloMachineTestSuite) TestCheckMisbehaviourAndUpdateState() {
{
"wrong client state type",
func() {
clientState = ibctmtypes.ClientState{}
clientState = &ibctmtypes.ClientState{}
misbehaviour = suite.solomachine.CreateMisbehaviour()
},
false,

View File

@ -0,0 +1,53 @@
package types
import (
"reflect"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
)
// CheckProposedHeaderAndUpdateState updates the consensus state to the header's sequence and
// public key. An error is returned if the client has been disallowed to be updated by a
// governance proposal, the header cannot be casted to a solo machine header, or the current
// public key equals the new public key.
func (cs ClientState) CheckProposedHeaderAndUpdateState(
ctx sdk.Context, cdc codec.BinaryMarshaler, clientStore sdk.KVStore,
header exported.Header,
) (exported.ClientState, exported.ConsensusState, error) {
if !cs.AllowUpdateAfterProposal {
return nil, nil, sdkerrors.Wrapf(
clienttypes.ErrUpdateClientFailed,
"solo machine client is not allowed to updated with a proposal",
)
}
smHeader, ok := header.(*Header)
if !ok {
return nil, nil, sdkerrors.Wrapf(
clienttypes.ErrInvalidHeader, "header type %T, expected %T", header, &Header{},
)
}
if reflect.DeepEqual(cs.ConsensusState.GetPubKey(), smHeader.GetPubKey()) {
return nil, nil, sdkerrors.Wrapf(
clienttypes.ErrInvalidHeader, "new public key in header equals current public key",
)
}
clientState := &cs
consensusState := &ConsensusState{
Sequence: smHeader.Sequence,
PublicKey: smHeader.NewPublicKey,
}
clientState.ConsensusState = consensusState
clientState.FrozenSequence = 0
return clientState, consensusState, nil
}

View File

@ -0,0 +1,72 @@
package types_test
import (
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/light-clients/solomachine/types"
)
func (suite *SoloMachineTestSuite) TestCheckProposedHeaderAndUpdateState() {
var header exported.Header
testCases := []struct {
name string
malleate func()
expPass bool
}{
{
"valid header", func() {
header = suite.solomachine.CreateHeader()
}, true,
},
{
"nil header", func() {
header = &ibctmtypes.Header{}
}, false,
},
{
"header does not update public key", func() {
header = &types.Header{
Sequence: 1,
NewPublicKey: suite.solomachine.ConsensusState().PublicKey,
}
}, false,
},
}
for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
suite.SetupTest()
clientState := suite.solomachine.ClientState()
tc.malleate()
clientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), suite.solomachine.ClientID)
// all cases should always fail if the client has 'AllowUpdateAfterProposal' set to false
clientState.AllowUpdateAfterProposal = false
cs, consState, err := clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, header)
suite.Require().Error(err)
suite.Require().Nil(cs)
suite.Require().Nil(consState)
clientState.AllowUpdateAfterProposal = true
cs, consState, err = clientState.CheckProposedHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), clientStore, header)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(header.(*types.Header).GetPubKey(), consState.(*types.ConsensusState).GetPubKey())
suite.Require().Equal(cs.(*types.ClientState).ConsensusState, consState)
suite.Require().Equal(header.GetHeight().GetEpochHeight(), consState.(*types.ConsensusState).Sequence)
} else {
suite.Require().Error(err)
suite.Require().Nil(cs)
suite.Require().Nil(consState)
}
})
}
}

View File

@ -30,6 +30,9 @@ type ClientState struct {
// frozen sequence of the solo machine
FrozenSequence uint64 `protobuf:"varint,1,opt,name=frozen_sequence,json=frozenSequence,proto3" json:"frozen_sequence,omitempty" yaml:"frozen_sequence"`
ConsensusState *ConsensusState `protobuf:"bytes,2,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty" yaml:"consensus_state"`
// when set to true, will allow governance to update a solo machine client.
// The client will be unfrozen if it is frozen.
AllowUpdateAfterProposal bool `protobuf:"varint,3,opt,name=allow_update_after_proposal,json=allowUpdateAfterProposal,proto3" json:"allow_update_after_proposal,omitempty" yaml:"allow_update_after_proposal"`
}
func (m *ClientState) Reset() { *m = ClientState{} }
@ -283,45 +286,48 @@ func init() {
}
var fileDescriptor_6cc2ee18f7f86d4e = []byte{
// 597 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcf, 0x8a, 0xd3, 0x5e,
0x14, 0x6e, 0x3a, 0x65, 0x68, 0xef, 0xf4, 0xd7, 0x99, 0x5f, 0xe8, 0x48, 0x2d, 0x43, 0x32, 0x04,
0xc4, 0xd9, 0x4c, 0x42, 0x74, 0xd7, 0x9d, 0xa9, 0x0b, 0xff, 0x20, 0x4a, 0x3a, 0x0b, 0x51, 0x21,
0xdc, 0x24, 0x77, 0xda, 0xcb, 0x34, 0xf7, 0xc6, 0xdc, 0x9b, 0xd6, 0xfa, 0x04, 0x2e, 0x5d, 0xba,
0xf4, 0x05, 0x04, 0x1f, 0x43, 0x10, 0x64, 0x96, 0xae, 0x8a, 0xb4, 0x6f, 0xd0, 0x27, 0x90, 0x26,
0xb7, 0x69, 0x12, 0x06, 0x8b, 0xe0, 0x2a, 0xe7, 0x9c, 0x9c, 0xfb, 0x9d, 0xef, 0x3b, 0xe7, 0x70,
0x80, 0x89, 0x5d, 0xcf, 0x18, 0xe3, 0xe1, 0x88, 0x7b, 0x63, 0x8c, 0x08, 0x67, 0x06, 0xa3, 0x63,
0x1a, 0x40, 0x6f, 0x84, 0x09, 0x32, 0x26, 0x66, 0xde, 0xd5, 0xc3, 0x88, 0x72, 0x2a, 0xab, 0xd8,
0xf5, 0xf4, 0xfc, 0x13, 0x3d, 0x9f, 0x33, 0x31, 0xbb, 0x77, 0x3d, 0xca, 0x02, 0xca, 0x0c, 0x17,
0x32, 0x64, 0x78, 0xd1, 0x2c, 0xe4, 0xd4, 0x98, 0x98, 0x2e, 0xe2, 0xd0, 0x14, 0x6e, 0x8a, 0xd4,
0x6d, 0x0f, 0xe9, 0x90, 0x26, 0xa6, 0xb1, 0xb6, 0xd2, 0xa8, 0xf6, 0x43, 0x02, 0x07, 0xfd, 0x04,
0x79, 0xc0, 0x21, 0x47, 0x72, 0x1f, 0x1c, 0x5e, 0x46, 0xf4, 0x3d, 0x22, 0x0e, 0x43, 0x6f, 0x63,
0x44, 0x3c, 0xd4, 0x91, 0x4e, 0xa5, 0xb3, 0x9a, 0xd5, 0x5d, 0xcd, 0xd5, 0x5b, 0x33, 0x18, 0x8c,
0x7b, 0x5a, 0x29, 0x41, 0xb3, 0x5b, 0x69, 0x64, 0x20, 0x02, 0x32, 0x07, 0x87, 0x1e, 0x25, 0x0c,
0x11, 0x16, 0x33, 0x87, 0xad, 0x71, 0x3b, 0xd5, 0x53, 0xe9, 0xec, 0xe0, 0x9e, 0xa1, 0xef, 0x90,
0xa3, 0xf7, 0x37, 0xef, 0x12, 0x3a, 0xf9, 0xaa, 0x25, 0x44, 0xcd, 0x6e, 0x79, 0x85, 0xdc, 0x5e,
0xed, 0xc3, 0x67, 0xb5, 0xa2, 0x7d, 0x91, 0x40, 0xab, 0x08, 0x22, 0x77, 0x41, 0xbd, 0x28, 0xc6,
0xce, 0x7c, 0xf9, 0x35, 0x00, 0x61, 0xec, 0x8e, 0xb1, 0xe7, 0x5c, 0xa1, 0x99, 0x60, 0x79, 0x47,
0x4f, 0x7b, 0xaa, 0xaf, 0x7b, 0xaa, 0x8b, 0x26, 0x8a, 0x9e, 0xea, 0x2f, 0x92, 0xec, 0xa7, 0x68,
0x66, 0x1d, 0xaf, 0xe6, 0xea, 0xff, 0x29, 0xb7, 0x2d, 0x84, 0x66, 0x37, 0xc2, 0x4d, 0x86, 0x7c,
0x02, 0x1a, 0x1c, 0x07, 0x88, 0x71, 0x18, 0x84, 0x9d, 0xbd, 0xa4, 0xf2, 0x36, 0x20, 0xf8, 0x7e,
0x95, 0xc0, 0xfe, 0x23, 0x04, 0x7d, 0x14, 0xfd, 0x91, 0xe7, 0x09, 0x68, 0x30, 0x3c, 0x24, 0x90,
0xc7, 0x51, 0xda, 0xcc, 0xa6, 0xbd, 0x0d, 0xc8, 0x97, 0xa0, 0x45, 0xd0, 0xd4, 0xc9, 0x29, 0xd9,
0xfb, 0x1b, 0x25, 0xb7, 0x57, 0x73, 0xf5, 0x38, 0x55, 0x52, 0x84, 0xd1, 0xec, 0x26, 0x41, 0xd3,
0x2c, 0x51, 0x50, 0xfe, 0x5e, 0x05, 0xcd, 0x67, 0x98, 0xb9, 0x68, 0x04, 0x27, 0x98, 0xc6, 0x91,
0x6c, 0x82, 0x46, 0x3a, 0x4e, 0x07, 0xfb, 0x09, 0xf3, 0x86, 0xd5, 0x5e, 0xcd, 0xd5, 0x23, 0x31,
0xb8, 0xcd, 0x2f, 0xcd, 0xae, 0xa7, 0xf6, 0x63, 0xbf, 0xa0, 0xb5, 0x5a, 0xd2, 0x1a, 0x82, 0xff,
0x32, 0x69, 0x0e, 0x25, 0x48, 0x88, 0x31, 0x77, 0x2e, 0xcf, 0x60, 0xf3, 0xea, 0x01, 0xf1, 0x1f,
0x42, 0x0e, 0xad, 0xce, 0x6a, 0xae, 0xb6, 0x53, 0x16, 0x05, 0x44, 0xcd, 0x6e, 0x66, 0xfe, 0x73,
0x52, 0xaa, 0xc8, 0xa7, 0xb4, 0x53, 0xfb, 0xa7, 0x15, 0xf9, 0x94, 0xe6, 0x2b, 0x5e, 0x4c, 0x69,
0xaf, 0xbe, 0xee, 0xe4, 0xa7, 0x75, 0x37, 0x9f, 0x80, 0xa3, 0x32, 0x4a, 0x71, 0xda, 0x52, 0x79,
0xda, 0x32, 0xa8, 0xf9, 0x90, 0x43, 0xb1, 0x06, 0x89, 0x2d, 0x26, 0xf3, 0x12, 0xb4, 0x2f, 0x36,
0xfb, 0x85, 0xfc, 0x0c, 0x76, 0x07, 0x5e, 0x61, 0x4d, 0xab, 0x37, 0xae, 0xa9, 0xf5, 0xe6, 0xdb,
0x42, 0x91, 0xae, 0x17, 0x8a, 0xf4, 0x6b, 0xa1, 0x48, 0x1f, 0x97, 0x4a, 0xe5, 0x7a, 0xa9, 0x54,
0x7e, 0x2e, 0x95, 0xca, 0x2b, 0x6b, 0x88, 0xf9, 0x28, 0x76, 0x75, 0x8f, 0x06, 0x86, 0xb8, 0x45,
0xe9, 0xe7, 0x9c, 0xf9, 0x57, 0xc6, 0x3b, 0x23, 0xbb, 0x79, 0xe7, 0x37, 0x1d, 0x3d, 0x3e, 0x0b,
0x11, 0x73, 0xf7, 0x93, 0x63, 0x74, 0xff, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x13, 0x3a, 0xae,
0x05, 0x21, 0x05, 0x00, 0x00,
// 649 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcf, 0x6e, 0xd3, 0x4e,
0x10, 0x8e, 0xd3, 0xa8, 0x4a, 0xb6, 0xf9, 0xa5, 0xfd, 0x59, 0x29, 0x0a, 0xa1, 0x8a, 0x2b, 0x4b,
0x40, 0x2f, 0xb5, 0x65, 0xb8, 0xf5, 0x56, 0x97, 0x03, 0x7f, 0x84, 0xa8, 0xdc, 0x22, 0x21, 0x40,
0xb2, 0xd6, 0xf6, 0x34, 0x59, 0xd5, 0xd9, 0x35, 0xde, 0x75, 0x42, 0x78, 0x02, 0x8e, 0x1c, 0x39,
0xf2, 0x02, 0x48, 0x5c, 0x78, 0x07, 0x24, 0x2e, 0x3d, 0x72, 0x8a, 0x50, 0xfb, 0x06, 0x79, 0x02,
0x14, 0xef, 0x26, 0x8d, 0xa3, 0xaa, 0x15, 0x12, 0x27, 0xef, 0xce, 0x8c, 0xbf, 0xfd, 0xbe, 0xf9,
0x46, 0x83, 0x1c, 0x12, 0x84, 0x76, 0x4c, 0xba, 0x3d, 0x11, 0xc6, 0x04, 0xa8, 0xe0, 0x36, 0x67,
0x31, 0xeb, 0xe3, 0xb0, 0x47, 0x28, 0xd8, 0x03, 0x67, 0xf1, 0x6a, 0x25, 0x29, 0x13, 0x4c, 0x37,
0x48, 0x10, 0x5a, 0x8b, 0xbf, 0x58, 0x8b, 0x35, 0x03, 0xa7, 0x7d, 0x3f, 0x64, 0xbc, 0xcf, 0xb8,
0x1d, 0x60, 0x0e, 0x76, 0x98, 0x8e, 0x12, 0xc1, 0xec, 0x81, 0x13, 0x80, 0xc0, 0x8e, 0xba, 0x4a,
0xa4, 0x76, 0xb3, 0xcb, 0xba, 0x2c, 0x3f, 0xda, 0xd3, 0x93, 0x8c, 0x9a, 0xdf, 0xcb, 0x68, 0xed,
0x20, 0x47, 0x3e, 0x12, 0x58, 0x80, 0x7e, 0x80, 0xd6, 0x4f, 0x52, 0xf6, 0x01, 0xa8, 0xcf, 0xe1,
0x5d, 0x06, 0x34, 0x84, 0x96, 0xb6, 0xad, 0xed, 0x54, 0xdc, 0xf6, 0x64, 0x6c, 0xdc, 0x1a, 0xe1,
0x7e, 0xbc, 0x67, 0x2e, 0x15, 0x98, 0x5e, 0x43, 0x46, 0x8e, 0x54, 0x40, 0x17, 0x68, 0x3d, 0x64,
0x94, 0x03, 0xe5, 0x19, 0xf7, 0xf9, 0x14, 0xb7, 0x55, 0xde, 0xd6, 0x76, 0xd6, 0x1e, 0xd8, 0xd6,
0x0d, 0x72, 0xac, 0x83, 0xd9, 0x7f, 0x39, 0x9d, 0xc5, 0x57, 0x97, 0x10, 0x4d, 0xaf, 0x11, 0x16,
0x6a, 0x75, 0x40, 0x77, 0x70, 0x1c, 0xb3, 0xa1, 0x9f, 0x25, 0x11, 0x16, 0xe0, 0xe3, 0x13, 0x01,
0xa9, 0x9f, 0xa4, 0x2c, 0x61, 0x1c, 0xc7, 0xad, 0x95, 0x6d, 0x6d, 0xa7, 0xea, 0xde, 0x9b, 0x8c,
0x0d, 0x53, 0x02, 0x5e, 0x53, 0x6c, 0x7a, 0xad, 0x3c, 0xfb, 0x32, 0x4f, 0xee, 0x4f, 0x73, 0x87,
0x2a, 0xb5, 0x57, 0xf9, 0xf8, 0xc5, 0x28, 0x99, 0x5f, 0x35, 0xd4, 0x28, 0x72, 0xd5, 0xdb, 0xa8,
0x5a, 0xec, 0x99, 0x37, 0xbf, 0xeb, 0x6f, 0x10, 0x4a, 0xb2, 0x20, 0x26, 0xa1, 0x7f, 0x0a, 0x23,
0xd5, 0x8c, 0xbb, 0x96, 0xb4, 0xce, 0x9a, 0x5a, 0x67, 0x29, 0xaf, 0x94, 0x75, 0xd6, 0x61, 0x5e,
0xfd, 0x0c, 0x46, 0xee, 0xe6, 0x64, 0x6c, 0xfc, 0x2f, 0x19, 0x5f, 0x42, 0x98, 0x5e, 0x2d, 0x99,
0x55, 0xe8, 0x5b, 0xa8, 0x26, 0x48, 0x1f, 0xb8, 0xc0, 0xfd, 0x24, 0x97, 0x59, 0xf1, 0x2e, 0x03,
0x8a, 0xef, 0x37, 0x0d, 0xad, 0x3e, 0x06, 0x1c, 0x41, 0x7a, 0x2d, 0xcf, 0x2d, 0x54, 0xe3, 0xa4,
0x4b, 0xb1, 0xc8, 0x52, 0xe9, 0x59, 0xdd, 0xbb, 0x0c, 0xe8, 0x27, 0xa8, 0x41, 0x61, 0xe8, 0x2f,
0x28, 0x59, 0xf9, 0x1b, 0x25, 0xb7, 0x27, 0x63, 0x63, 0x53, 0x2a, 0x29, 0xc2, 0x98, 0x5e, 0x9d,
0xc2, 0x70, 0x5e, 0xa8, 0x28, 0xff, 0x2c, 0xa3, 0xfa, 0x73, 0xc2, 0x03, 0xe8, 0xe1, 0x01, 0x61,
0x59, 0xaa, 0x3b, 0xa8, 0x26, 0xa7, 0xc6, 0x27, 0x51, 0xce, 0xbc, 0xe6, 0x36, 0x27, 0x63, 0x63,
0x43, 0xcd, 0xc7, 0x2c, 0x65, 0x7a, 0x55, 0x79, 0x7e, 0x12, 0x15, 0xb4, 0x96, 0x97, 0xb4, 0x26,
0xe8, 0xbf, 0xb9, 0x34, 0x9f, 0x51, 0x50, 0x62, 0x9c, 0x1b, 0x67, 0xf4, 0x68, 0xf6, 0xd7, 0x3e,
0x8d, 0x1e, 0x61, 0x81, 0xdd, 0xd6, 0x64, 0x6c, 0x34, 0x25, 0x8b, 0x02, 0xa2, 0xe9, 0xd5, 0xe7,
0xf7, 0x17, 0x74, 0xe9, 0x45, 0x31, 0x64, 0xad, 0xca, 0x3f, 0x7d, 0x51, 0x0c, 0xd9, 0xe2, 0x8b,
0xc7, 0x43, 0xb6, 0x57, 0x9d, 0x76, 0xf2, 0xf3, 0xb4, 0x9b, 0x4f, 0xd1, 0xc6, 0x32, 0x4a, 0xd1,
0x6d, 0x6d, 0xd9, 0x6d, 0x1d, 0x55, 0x22, 0x2c, 0xb0, 0x1a, 0x83, 0xfc, 0xac, 0x9c, 0x79, 0x85,
0x9a, 0xc7, 0xb3, 0xf9, 0x82, 0x68, 0x0e, 0x7b, 0x03, 0x5e, 0x61, 0x4c, 0xcb, 0x57, 0x8e, 0xa9,
0xfb, 0xf6, 0xc7, 0x79, 0x47, 0x3b, 0x3b, 0xef, 0x68, 0xbf, 0xcf, 0x3b, 0xda, 0xa7, 0x8b, 0x4e,
0xe9, 0xec, 0xa2, 0x53, 0xfa, 0x75, 0xd1, 0x29, 0xbd, 0x76, 0xbb, 0x44, 0xf4, 0xb2, 0xc0, 0x0a,
0x59, 0xdf, 0x56, 0x2b, 0x4f, 0x7e, 0x76, 0x79, 0x74, 0x6a, 0xbf, 0xb7, 0xe7, 0xab, 0x75, 0xf7,
0xaa, 0xdd, 0x2a, 0x46, 0x09, 0xf0, 0x60, 0x35, 0xdf, 0x79, 0x0f, 0xff, 0x04, 0x00, 0x00, 0xff,
0xff, 0x86, 0xeb, 0x8b, 0x5f, 0x88, 0x05, 0x00, 0x00,
}
func (m *ClientState) Marshal() (dAtA []byte, err error) {
@ -344,6 +350,16 @@ func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if m.AllowUpdateAfterProposal {
i--
if m.AllowUpdateAfterProposal {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x18
}
if m.ConsensusState != nil {
{
size, err := m.ConsensusState.MarshalToSizedBuffer(dAtA[:i])
@ -611,6 +627,9 @@ func (m *ClientState) Size() (n int) {
l = m.ConsensusState.Size()
n += 1 + l + sovSolomachine(uint64(l))
}
if m.AllowUpdateAfterProposal {
n += 2
}
return n
}
@ -800,6 +819,26 @@ func (m *ClientState) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field AllowUpdateAfterProposal", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSolomachine
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.AllowUpdateAfterProposal = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipSolomachine(dAtA[iNdEx:])

View File

@ -29,7 +29,7 @@ func (suite *SoloMachineTestSuite) TestCheckHeaderAndUpdateState() {
{
"wrong client state type",
func() {
clientState = ibctmtypes.ClientState{}
clientState = &ibctmtypes.ClientState{}
header = suite.solomachine.CreateHeader()
},
false,

View File

@ -144,3 +144,25 @@ in the handshake callbacks.
Implementations which do not feel they would benefit from versioning can do
basic string matching using a single compatible version.
## ClientUpdateProposal
A governance proposal may be passed to update a specified client with a provided
header. This is useful in unfreezing clients or updating expired clients. Each
client is expected to implement this functionality. A client may choose to disallow
an update by a governance proposal by returning an error in the client state function
'CheckProposedHeaderAndUpdateState'.
The localhost client cannot be updated by a governance proposal.
The solo machine client requires the boolean flag 'AllowUpdateAfterProposal' to be set
to true in order to be updated by a proposal. This is set upon client creation and cannot
be updated later.
The tendermint client has two flags update flags, 'AllowUpdateAfterExpiry' and
'AllowUpdateAfterMisbehaviour'. The former flag can only be used to unexpire clients. The
latter flag can be used to unfreeze a client and if necessary it will also unexpire the client.
It is advised to let a client expire if it has become frozen before proposing a new header.
This is to avoid the client from becoming refrozen if the misbehaviour evidence has not
expired. These boolean flags are set upon client creation and cannot be updated later.

View File

@ -47,6 +47,16 @@ callbacks to IBC applications.
| message | sender | {senderAddress} |
| submit_evidence | evidence_hash | {evidenceHash} |
### UpdateClientProposal
| Type | Attribute Key | Attribute Value |
|------------------------|------------------|-------------------|
| update_client_proposal | client_id | {clientId} |
| update_client_proposal | client_type | {clientType} |
| update_client_proposal | consensus_height | {consensusHeight} |
## ICS 03 - Connection
### MsgConnectionOpenInit

View File

@ -61,7 +61,8 @@ denomination trace path in order to support special characters and limit the max
consensus states in order to verify their membership in the counterparty clients.
* [ADR 19 - Protobuf State Encoding](../../../docs/architecture/adr-019-protobuf-state-encoding.md): Migration from Amino to Protobuf for state encoding.
* [ADR 020 - Protocol Buffer Transaction Encoding](./../../docs/architecture/adr-020-protobuf-transaction-encoding.md): Client side migration to Protobuf.
* [ADR 021 - Protocol Buffer Query Encoding](./../../docs/architecture/adr-020-protobuf-query-encoding.md): Queries migration to Protobuf.
* [ADR 021 - Protocol Buffer Query Encoding](../../../docs/architecture/adr-020-protobuf-query-encoding.md): Queries migration to Protobuf.
* [ADR 026 - IBC Client Recovery Mechanisms](../../../docs/architecture/adr-026-ibc-client-recovery-mechanisms.md): Allows IBC Clients to be recovered after freezing or expiry.
### SDK Modules

View File

@ -36,8 +36,8 @@ import (
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
// Default params constants used to create a TM client
const (
// Default params constants used to create a TM client
TrustingPeriod time.Duration = time.Hour * 24 * 7 * 2
UnbondingPeriod time.Duration = time.Hour * 24 * 7 * 3
MaxClockDrift time.Duration = time.Second * 10
@ -50,6 +50,10 @@ const (
TransferPort = ibctransfertypes.ModuleName
MockPort = mock.ModuleName
// used for testing UpdateClientProposal
Title = "title"
Description = "description"
)
// Default params variables used to create a TM client
@ -380,6 +384,7 @@ func (chain *TestChain) ConstructMsgCreateClient(counterparty *TestChain, client
clientState = ibctmtypes.NewClientState(
counterparty.ChainID, DefaultTrustLevel, TrustingPeriod, UnbondingPeriod, MaxClockDrift,
height, commitmenttypes.GetSDKSpecs(),
false, false,
)
consensusState = counterparty.LastHeader.ConsensusState()
case exported.ClientTypeSoloMachine:
@ -406,9 +411,24 @@ func (chain *TestChain) CreateTMClient(counterparty *TestChain, clientID string)
}
// UpdateTMClient will construct and execute a 07-tendermint MsgUpdateClient. The counterparty
// client will be updated on the (target) chain.
// UpdateTMClient mocks the relayer flow necessary for updating a Tendermint client
// client will be updated on the (target) chain. UpdateTMClient mocks the relayer flow
// necessary for updating a Tendermint client.
func (chain *TestChain) UpdateTMClient(counterparty *TestChain, clientID string) error {
header, err := chain.ConstructUpdateTMClientHeader(counterparty, clientID)
require.NoError(chain.t, err)
msg, err := clienttypes.NewMsgUpdateClient(
clientID, header,
chain.SenderAccount.GetAddress(),
)
require.NoError(chain.t, err)
return chain.sendMsgs(msg)
}
// ConstructUpdateTMClientHeader will construct a valid 07-tendermint Header to update the
// light client on the source chain.
func (chain *TestChain) ConstructUpdateTMClientHeader(counterparty *TestChain, clientID string) (*ibctmtypes.Header, error) {
header := counterparty.LastHeader
// Relayer must query for LatestHeight on client to get TrustedHeight
trustedHeight := chain.GetClientState(clientID).GetLatestHeight().(clienttypes.Height)
@ -428,7 +448,7 @@ func (chain *TestChain) UpdateTMClient(counterparty *TestChain, clientID string)
// NextValidatorsHash
tmTrustedVals, ok = counterparty.GetValsAtHeight(int64(trustedHeight.EpochHeight + 1))
if !ok {
return sdkerrors.Wrapf(ibctmtypes.ErrInvalidHeaderHeight, "could not retrieve trusted validators at trustedHeight: %d", trustedHeight)
return nil, sdkerrors.Wrapf(ibctmtypes.ErrInvalidHeaderHeight, "could not retrieve trusted validators at trustedHeight: %d", trustedHeight)
}
}
// inject trusted fields into last header
@ -437,17 +457,18 @@ func (chain *TestChain) UpdateTMClient(counterparty *TestChain, clientID string)
trustedVals, err := tmTrustedVals.ToProto()
if err != nil {
return err
return nil, err
}
header.TrustedValidators = trustedVals
msg, err := clienttypes.NewMsgUpdateClient(
clientID, header,
chain.SenderAccount.GetAddress(),
)
require.NoError(chain.t, err)
return header, nil
return chain.sendMsgs(msg)
}
// ExpireClient fast forwards the chain's block time by the provided amount of time which will
// expire any clients with a trusting period less than or equal to this amount of time.
func (chain *TestChain) ExpireClient(amount time.Duration) {
chain.CurrentHeader.Time = chain.CurrentHeader.Time.Add(amount)
}
// CreateTMClientHeader creates a TM header to update the TM client.

View File

@ -41,8 +41,9 @@ func NewSolomachine(t *testing.T, clientID string) *Solomachine {
}
}
// default usage does not allow update after governance proposal
func (solo *Solomachine) ClientState() *solomachinetypes.ClientState {
return solomachinetypes.NewClientState(solo.ConsensusState())
return solomachinetypes.NewClientState(solo.ConsensusState(), false)
}
func (solo *Solomachine) ConsensusState() *solomachinetypes.ConsensusState {

View File

@ -88,6 +88,7 @@ func local_request_Query_AnnualProvisions_0(ctx context.Context, marshaler runti
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -70,6 +70,7 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -142,6 +142,7 @@ func local_request_Query_SigningInfos_0(ctx context.Context, marshaler runtime.M
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -874,6 +874,7 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_Validators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -106,6 +106,7 @@ func local_request_Query_AppliedPlan_0(ctx context.Context, marshaler runtime.Ma
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_CurrentPlan_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {