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:
parent
bae1399ebc
commit
b52ffa08e1
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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")
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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:])
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"})
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -38,7 +38,7 @@ func (suite *SoloMachineTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
|||
{
|
||||
"wrong client state type",
|
||||
func() {
|
||||
clientState = ibctmtypes.ClientState{}
|
||||
clientState = &ibctmtypes.ClientState{}
|
||||
misbehaviour = suite.solomachine.CreateMisbehaviour()
|
||||
},
|
||||
false,
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
|
@ -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:])
|
||||
|
|
|
@ -29,7 +29,7 @@ func (suite *SoloMachineTestSuite) TestCheckHeaderAndUpdateState() {
|
|||
{
|
||||
"wrong client state type",
|
||||
func() {
|
||||
clientState = ibctmtypes.ClientState{}
|
||||
clientState = &ibctmtypes.ClientState{}
|
||||
header = suite.solomachine.CreateHeader()
|
||||
},
|
||||
false,
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue