From 8969e805058b971cfb25caad7463b35422ecf511 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Sat, 8 Feb 2020 18:19:26 -0800 Subject: [PATCH 01/12] refactor tendermint package to move msgs here --- x/ibc/02-client/alias.go | 8 +- x/ibc/02-client/client/cli/cli.go | 18 -- x/ibc/02-client/client/rest/rest.go | 27 --- x/ibc/02-client/client/rest/swagger.go | 29 +-- x/ibc/02-client/client/utils/utils.go | 26 +-- x/ibc/02-client/exported/exported.go | 19 ++ x/ibc/02-client/handler.go | 58 ++++-- x/ibc/02-client/keeper/client.go | 3 +- x/ibc/02-client/keeper/keeper.go | 6 +- x/ibc/02-client/module.go | 5 - x/ibc/02-client/types/codec.go | 5 +- x/ibc/02-client/types/errors.go | 2 - x/ibc/02-client/types/events.go | 6 +- x/ibc/02-client/types/msgs_test.go | 85 --------- x/ibc/07-tendermint/client/cli/cli.go | 26 +++ .../client/cli/tx.go | 13 +- x/ibc/07-tendermint/client/rest/rest.go | 44 +++++ x/ibc/07-tendermint/client/rest/swagger.go | 31 ++++ .../client/rest/tx.go | 7 +- x/ibc/07-tendermint/misbehaviour.go | 9 +- x/ibc/07-tendermint/misbehaviour_test.go | 83 ++++----- x/ibc/07-tendermint/module.go | 29 +++ x/ibc/07-tendermint/tendermint_test.go | 22 ++- .../07-tendermint/{ => types}/client_state.go | 2 +- .../{ => types}/client_state_test.go | 172 +++++++++--------- x/ibc/07-tendermint/{ => types}/codec.go | 4 +- .../{ => types}/consensus_state.go | 2 +- .../{ => types}/consensus_state_test.go | 27 +-- x/ibc/07-tendermint/types/errors.go | 14 ++ x/ibc/07-tendermint/{ => types}/evidence.go | 2 +- .../{ => types}/evidence_test.go | 68 +++---- x/ibc/07-tendermint/{ => types}/header.go | 2 +- .../07-tendermint/{ => types}/header_test.go | 8 +- .../types/msgs.go | 62 ++++--- x/ibc/07-tendermint/types/msgs_test.go | 77 ++++++++ x/ibc/07-tendermint/types/tendermint_test.go | 48 +++++ x/ibc/07-tendermint/{ => types}/test_utils.go | 2 +- x/ibc/07-tendermint/update.go | 11 +- x/ibc/07-tendermint/update_test.go | 12 +- 39 files changed, 618 insertions(+), 456 deletions(-) delete mode 100644 x/ibc/02-client/types/msgs_test.go create mode 100644 x/ibc/07-tendermint/client/cli/cli.go rename x/ibc/{02-client => 07-tendermint}/client/cli/tx.go (94%) create mode 100644 x/ibc/07-tendermint/client/rest/rest.go create mode 100644 x/ibc/07-tendermint/client/rest/swagger.go rename x/ibc/{02-client => 07-tendermint}/client/rest/tx.go (96%) create mode 100644 x/ibc/07-tendermint/module.go rename x/ibc/07-tendermint/{ => types}/client_state.go (99%) rename x/ibc/07-tendermint/{ => types}/client_state_test.go (70%) rename x/ibc/07-tendermint/{ => types}/codec.go (80%) rename x/ibc/07-tendermint/{ => types}/consensus_state.go (98%) rename x/ibc/07-tendermint/{ => types}/consensus_state_test.go (72%) create mode 100644 x/ibc/07-tendermint/types/errors.go rename x/ibc/07-tendermint/{ => types}/evidence.go (99%) rename x/ibc/07-tendermint/{ => types}/evidence_test.go (73%) rename x/ibc/07-tendermint/{ => types}/header.go (99%) rename x/ibc/07-tendermint/{ => types}/header_test.go (80%) rename x/ibc/{02-client => 07-tendermint}/types/msgs.go (63%) create mode 100644 x/ibc/07-tendermint/types/msgs_test.go create mode 100644 x/ibc/07-tendermint/types/tendermint_test.go rename x/ibc/07-tendermint/{ => types}/test_utils.go (99%) diff --git a/x/ibc/02-client/alias.go b/x/ibc/02-client/alias.go index ac62fc7602c8..762cb695ab26 100644 --- a/x/ibc/02-client/alias.go +++ b/x/ibc/02-client/alias.go @@ -37,8 +37,6 @@ var ( ErrRootNotFound = types.ErrRootNotFound ErrInvalidHeader = types.ErrInvalidHeader ErrInvalidEvidence = types.ErrInvalidEvidence - NewMsgCreateClient = types.NewMsgCreateClient - NewMsgUpdateClient = types.NewMsgUpdateClient // variable aliases SubModuleCdc = types.SubModuleCdc @@ -48,8 +46,6 @@ var ( ) type ( - Keeper = keeper.Keeper - StakingKeeper = types.StakingKeeper - MsgCreateClient = types.MsgCreateClient - MsgUpdateClient = types.MsgUpdateClient + Keeper = keeper.Keeper + StakingKeeper = types.StakingKeeper ) diff --git a/x/ibc/02-client/client/cli/cli.go b/x/ibc/02-client/client/cli/cli.go index 757b8894f719..bd9d8d361be2 100644 --- a/x/ibc/02-client/client/cli/cli.go +++ b/x/ibc/02-client/client/cli/cli.go @@ -26,21 +26,3 @@ func GetQueryCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { )...) return ics02ClientQueryCmd } - -// GetTxCmd returns the transaction commands for IBC clients -func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { - ics02ClientTxCmd := &cobra.Command{ - Use: "client", - Short: "Client transaction subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - } - - ics02ClientTxCmd.AddCommand(flags.PostCommands( - GetCmdCreateClient(cdc), - GetCmdUpdateClient(cdc), - GetCmdSubmitMisbehaviour(cdc), - )...) - - return ics02ClientTxCmd -} diff --git a/x/ibc/02-client/client/rest/rest.go b/x/ibc/02-client/client/rest/rest.go index f562634cd742..a6b8b215b2c3 100644 --- a/x/ibc/02-client/client/rest/rest.go +++ b/x/ibc/02-client/client/rest/rest.go @@ -1,14 +1,9 @@ package rest import ( - "time" - "github.com/gorilla/mux" "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/types/rest" - evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" ) // REST client flags @@ -20,26 +15,4 @@ const ( // RegisterRoutes - Central function to define routes that get registered by the main application func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, queryRoute string) { registerQueryRoutes(cliCtx, r) - registerTxRoutes(cliCtx, r) -} - -// CreateClientReq defines the properties of a create client request's body. -type CreateClientReq struct { - BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` - ClientID string `json:"client_id" yaml:"client_id"` - ConsensusState exported.ConsensusState `json:"consensus_state" yaml:"consensus_state"` - TrustingPeriod time.Duration `json:"trusting_period" yaml:"trusting_period"` - UnbondingPeriod time.Duration `json:"unbonding_period" yaml:"unbonding_period"` -} - -// UpdateClientReq defines the properties of a update client request's body. -type UpdateClientReq struct { - BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` - Header exported.Header `json:"header" yaml:"header"` -} - -// SubmitMisbehaviourReq defines the properties of a submit misbehaviour request's body. -type SubmitMisbehaviourReq struct { - BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` - Evidence evidenceexported.Evidence `json:"evidence" yaml:"evidence"` } diff --git a/x/ibc/02-client/client/rest/swagger.go b/x/ibc/02-client/client/rest/swagger.go index 42809a112192..7c78a9f4808b 100644 --- a/x/ibc/02-client/client/rest/swagger.go +++ b/x/ibc/02-client/client/rest/swagger.go @@ -1,10 +1,8 @@ package rest import ( - auth "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/evidence" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -17,7 +15,7 @@ type ( QueryHeader struct { Height int64 `json:"height"` - Result tendermint.Header `json:"result"` + Result ibctmtypes.Header `json:"result"` } QueryClientState struct { @@ -27,32 +25,11 @@ type ( QueryNodeConsensusState struct { Height int64 `json:"height"` - Result tendermint.ConsensusState `json:"result"` + Result ibctmtypes.ConsensusState `json:"result"` } QueryPath struct { Height int64 `json:"height"` Result commitment.Prefix `json:"result"` } - - PostCreateClient struct { - Msgs []types.MsgCreateClient `json:"msg" yaml:"msg"` - Fee auth.StdFee `json:"fee" yaml:"fee"` - Signatures []auth.StdSignature `json:"signatures" yaml:"signatures"` - Memo string `json:"memo" yaml:"memo"` - } - - PostUpdateClient struct { - Msgs []types.MsgUpdateClient `json:"msg" yaml:"msg"` - Fee auth.StdFee `json:"fee" yaml:"fee"` - Signatures []auth.StdSignature `json:"signatures" yaml:"signatures"` - Memo string `json:"memo" yaml:"memo"` - } - - PostSubmitMisbehaviour struct { - Msgs []evidence.MsgSubmitEvidence `json:"msg" yaml:"msg"` - Fee auth.StdFee `json:"fee" yaml:"fee"` - Signatures []auth.StdSignature `json:"signatures" yaml:"signatures"` - Memo string `json:"memo" yaml:"memo"` - } ) diff --git a/x/ibc/02-client/client/utils/utils.go b/x/ibc/02-client/client/utils/utils.go index 4ae251de99f0..7228b8945242 100644 --- a/x/ibc/02-client/client/utils/utils.go +++ b/x/ibc/02-client/client/utils/utils.go @@ -9,7 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" ) @@ -91,30 +91,30 @@ func QueryConsensusState( // QueryTendermintHeader takes a client context and returns the appropriate // tendermint header -func QueryTendermintHeader(cliCtx context.CLIContext) (tendermint.Header, int64, error) { +func QueryTendermintHeader(cliCtx context.CLIContext) (ibctmtypes.Header, int64, error) { node, err := cliCtx.GetNode() if err != nil { - return tendermint.Header{}, 0, err + return ibctmtypes.Header{}, 0, err } info, err := node.ABCIInfo() if err != nil { - return tendermint.Header{}, 0, err + return ibctmtypes.Header{}, 0, err } height := info.Response.LastBlockHeight commit, err := node.Commit(&height) if err != nil { - return tendermint.Header{}, 0, err + return ibctmtypes.Header{}, 0, err } validators, err := node.Validators(&height, 0, 10000) if err != nil { - return tendermint.Header{}, 0, err + return ibctmtypes.Header{}, 0, err } - header := tendermint.Header{ + header := ibctmtypes.Header{ SignedHeader: commit.SignedHeader, ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), } @@ -124,30 +124,30 @@ func QueryTendermintHeader(cliCtx context.CLIContext) (tendermint.Header, int64, // QueryNodeConsensusState takes a client context and returns the appropriate // tendermint consensus state -func QueryNodeConsensusState(cliCtx context.CLIContext) (tendermint.ConsensusState, int64, error) { +func QueryNodeConsensusState(cliCtx context.CLIContext) (ibctmtypes.ConsensusState, int64, error) { node, err := cliCtx.GetNode() if err != nil { - return tendermint.ConsensusState{}, 0, err + return ibctmtypes.ConsensusState{}, 0, err } info, err := node.ABCIInfo() if err != nil { - return tendermint.ConsensusState{}, 0, err + return ibctmtypes.ConsensusState{}, 0, err } height := info.Response.LastBlockHeight commit, err := node.Commit(&height) if err != nil { - return tendermint.ConsensusState{}, 0, err + return ibctmtypes.ConsensusState{}, 0, err } validators, err := node.Validators(&height, 0, 10000) if err != nil { - return tendermint.ConsensusState{}, 0, err + return ibctmtypes.ConsensusState{}, 0, err } - state := tendermint.ConsensusState{ + state := ibctmtypes.ConsensusState{ Timestamp: commit.Time, Root: commitment.NewRoot(commit.AppHash), ValidatorSet: tmtypes.NewValidatorSet(validators.Validators), diff --git a/x/ibc/02-client/exported/exported.go b/x/ibc/02-client/exported/exported.go index bdaa85583bce..19828ee9955b 100644 --- a/x/ibc/02-client/exported/exported.go +++ b/x/ibc/02-client/exported/exported.go @@ -4,6 +4,8 @@ import ( "encoding/json" "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/codec" evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported" connectionexported "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/exported" @@ -110,6 +112,23 @@ type Header interface { GetHeight() uint64 } +// MsgCreateClient defines the msg interface that the +// CreateClient Handler expects +type MsgCreateClient interface { + sdk.Msg + GetClientID() string + GetClientType() string + GetConsensusState() ConsensusState +} + +// MsgUpdateClient defines the msg interface that the +// UpdateClient Handler expects +type MsgUpdateClient interface { + sdk.Msg + GetClientID() string + GetHeader() Header +} + // ClientType defines the type of the consensus algorithm type ClientType byte diff --git a/x/ibc/02-client/handler.go b/x/ibc/02-client/handler.go index 8a06c3485c9d..92a015cf3231 100644 --- a/x/ibc/02-client/handler.go +++ b/x/ibc/02-client/handler.go @@ -7,32 +7,49 @@ import ( evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" ) // HandleMsgCreateClient defines the sdk.Handler for MsgCreateClient -func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg MsgCreateClient) (*sdk.Result, error) { - clientType := exported.ClientTypeFromString(msg.ClientType) +func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg exported.MsgCreateClient) (*sdk.Result, error) { + clientType := exported.ClientTypeFromString(msg.GetClientType()) if clientType == 0 { - return nil, sdkerrors.Wrap(ErrInvalidClientType, msg.ClientType) + } - _, err := k.CreateClient( - ctx, msg.ClientID, clientType, msg.ConsensusState, msg.TrustingPeriod, msg.UnbondingPeriod, - ) - if err != nil { - return nil, err + switch clientType { + case 0: + return nil, sdkerrors.Wrap(ErrInvalidClientType, msg.GetClientType()) + case 1: + tmMsg, ok := msg.(ibctmtypes.MsgCreateClient) + if !ok { + return nil, sdkerrors.Wrap(ErrInvalidClientType, "Msg is not a Tendermint CreateClient msg") + } + _, err := k.CreateClient( + ctx, msg.GetClientID(), clientType, msg.GetConsensusState(), tmMsg.TrustingPeriod, tmMsg.UnbondingPeriod, + ) + if err != nil { + return nil, err + } + default: + return nil, sdkerrors.Wrap(ErrInvalidClientType, msg.GetClientType()) + } + + attributes := make([]sdk.Attribute, len(msg.GetSigners())+1) + attributes[0] = sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory) + for i, signer := range msg.GetSigners() { + attributes[i+1] = sdk.NewAttribute(sdk.AttributeKeySender, signer.String()) } ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( EventTypeCreateClient, - sdk.NewAttribute(AttributeKeyClientID, msg.ClientID), - sdk.NewAttribute(AttrbuteKeyClientType, msg.ClientType), + sdk.NewAttribute(AttributeKeyClientID, msg.GetClientID()), + sdk.NewAttribute(AttrbuteKeyClientType, msg.GetClientType()), ), sdk.NewEvent( sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory), - sdk.NewAttribute(sdk.AttributeKeySender, msg.Signer.String()), + attributes..., ), }) @@ -42,21 +59,26 @@ func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg MsgCreateClient) (*sdk } // HandleMsgUpdateClient defines the sdk.Handler for MsgUpdateClient -func HandleMsgUpdateClient(ctx sdk.Context, k Keeper, msg MsgUpdateClient) (*sdk.Result, error) { - if err := k.UpdateClient(ctx, msg.ClientID, msg.Header); err != nil { +func HandleMsgUpdateClient(ctx sdk.Context, k Keeper, msg exported.MsgUpdateClient) (*sdk.Result, error) { + if err := k.UpdateClient(ctx, msg.GetClientID(), msg.GetHeader()); err != nil { return nil, err } + attributes := make([]sdk.Attribute, len(msg.GetSigners())+1) + attributes[0] = sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory) + for i, signer := range msg.GetSigners() { + attributes[i+1] = sdk.NewAttribute(sdk.AttributeKeySender, signer.String()) + } + ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( EventTypeUpdateClient, - sdk.NewAttribute(AttributeKeyClientID, msg.ClientID), - sdk.NewAttribute(AttrbuteKeyClientType, msg.Header.ClientType().String()), + sdk.NewAttribute(AttributeKeyClientID, msg.GetClientID()), + sdk.NewAttribute(AttrbuteKeyClientType, msg.GetHeader().ClientType().String()), ), sdk.NewEvent( sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory), - sdk.NewAttribute(sdk.AttributeKeySender, msg.Signer.String()), + attributes..., ), }) diff --git a/x/ibc/02-client/keeper/client.go b/x/ibc/02-client/keeper/client.go index a4bd68077632..9a1232d7b166 100644 --- a/x/ibc/02-client/keeper/client.go +++ b/x/ibc/02-client/keeper/client.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" ) // CreateClient creates a new client state and populates it with a given consensus @@ -124,7 +125,7 @@ func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, misbehaviour ex var err error switch e := misbehaviour.(type) { - case tendermint.Evidence: + case ibctmtypes.Evidence: clientState, err = tendermint.CheckMisbehaviourAndUpdateState( clientState, consensusState, misbehaviour, uint64(misbehaviour.GetHeight()), ctx.BlockTime(), ) diff --git a/x/ibc/02-client/keeper/keeper.go b/x/ibc/02-client/keeper/keeper.go index bae9e50adfce..9a1423f7450a 100644 --- a/x/ibc/02-client/keeper/keeper.go +++ b/x/ibc/02-client/keeper/keeper.go @@ -11,7 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" ) @@ -104,7 +104,7 @@ func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height uint64) (exported. return nil, false } - consensusState := tendermint.ConsensusState{ + consensusState := ibctmtypes.ConsensusState{ Timestamp: ctx.BlockTime(), Root: commitment.NewRoot(histInfo.Header.AppHash), ValidatorSet: tmtypes.NewValidatorSet(histInfo.ValSet.ToTmValidators()), @@ -153,7 +153,7 @@ func (k Keeper) initialize( ) switch clientType { case exported.Tendermint: - clientState, err = tendermint.Initialize( + clientState, err = ibctmtypes.Initialize( clientID, consensusState, trustingPeriod, unbondingPeriod, height, ) default: diff --git a/x/ibc/02-client/module.go b/x/ibc/02-client/module.go index 9e5ddbd7dbd5..fd1fd48c06b2 100644 --- a/x/ibc/02-client/module.go +++ b/x/ibc/02-client/module.go @@ -22,11 +22,6 @@ func RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router, queryRoute stri rest.RegisterRoutes(ctx, rtr, fmt.Sprintf("%s/%s", queryRoute, SubModuleName)) } -// GetTxCmd returns the root tx command for the IBC client -func GetTxCmd(cdc *codec.Codec, storeKey string) *cobra.Command { - return cli.GetTxCmd(fmt.Sprintf("%s/%s", storeKey, SubModuleName), cdc) -} - // GetQueryCmd returns no root query command for the IBC client func GetQueryCmd(cdc *codec.Codec, queryRoute string) *cobra.Command { return cli.GetQueryCmd(fmt.Sprintf("%s/%s", queryRoute, SubModuleName), cdc) diff --git a/x/ibc/02-client/types/codec.go b/x/ibc/02-client/types/codec.go index 3226fc02c2cf..b8c0eed6ee61 100644 --- a/x/ibc/02-client/types/codec.go +++ b/x/ibc/02-client/types/codec.go @@ -11,13 +11,12 @@ var SubModuleCdc *codec.Codec // RegisterCodec registers the IBC client interfaces and types func RegisterCodec(cdc *codec.Codec) { cdc.RegisterInterface((*exported.ClientState)(nil), nil) + cdc.RegisterInterface((*exported.MsgCreateClient)(nil), nil) + cdc.RegisterInterface((*exported.MsgUpdateClient)(nil), nil) cdc.RegisterInterface((*exported.ConsensusState)(nil), nil) cdc.RegisterInterface((*exported.Header)(nil), nil) cdc.RegisterInterface((*exported.Misbehaviour)(nil), nil) - cdc.RegisterConcrete(MsgCreateClient{}, "ibc/client/MsgCreateClient", nil) - cdc.RegisterConcrete(MsgUpdateClient{}, "ibc/client/MsgUpdateClient", nil) - SetSubModuleCodec(cdc) } diff --git a/x/ibc/02-client/types/errors.go b/x/ibc/02-client/types/errors.go index 03e0224349d7..ceba41f85988 100644 --- a/x/ibc/02-client/types/errors.go +++ b/x/ibc/02-client/types/errors.go @@ -23,6 +23,4 @@ var ( ErrFailedPacketAckVerification = sdkerrors.Register(SubModuleName, 17, "packet acknowledgement verification failed") ErrFailedPacketAckAbsenceVerification = sdkerrors.Register(SubModuleName, 18, "packet acknowledgement absence verification failed") ErrFailedNextSeqRecvVerification = sdkerrors.Register(SubModuleName, 19, "next sequence receive verification failed") - ErrInvalidTrustingPeriod = sdkerrors.Register(SubModuleName, 20, "invalid trusting period") - ErrInvalidUnbondingPeriod = sdkerrors.Register(SubModuleName, 21, "invalid unbonding period") ) diff --git a/x/ibc/02-client/types/events.go b/x/ibc/02-client/types/events.go index ea0dcc7d6606..9692cd389232 100644 --- a/x/ibc/02-client/types/events.go +++ b/x/ibc/02-client/types/events.go @@ -14,9 +14,9 @@ const ( // IBC client events vars var ( - EventTypeCreateClient = TypeMsgCreateClient - EventTypeUpdateClient = TypeMsgUpdateClient - EventTypeSubmitMisbehaviour = TypeClientMisbehaviour + EventTypeCreateClient = "create_client" + EventTypeUpdateClient = "update_client" + EventTypeSubmitMisbehaviour = "client_misbehaviour" AttributeValueCategory = fmt.Sprintf("%s_%s", ibctypes.ModuleName, SubModuleName) ) diff --git a/x/ibc/02-client/types/msgs_test.go b/x/ibc/02-client/types/msgs_test.go deleted file mode 100644 index b529836b51b6..000000000000 --- a/x/ibc/02-client/types/msgs_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package types_test - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/tendermint/tendermint/crypto/secp256k1" - tmtypes "github.com/tendermint/tendermint/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" - commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" -) - -const ( - trustingPeriod time.Duration = time.Hour * 24 * 7 * 2 - ubdPeriod time.Duration = time.Hour * 24 * 7 * 3 -) - -func TestMsgCreateClientValidateBasic(t *testing.T) { - validator := tmtypes.NewValidator(tmtypes.NewMockPV().GetPubKey(), 1) - valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) - - now := time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) - cs := tendermint.ConsensusState{ - Timestamp: now, - Root: commitment.NewRoot([]byte("root")), - ValidatorSet: valSet, - } - privKey := secp256k1.GenPrivKey() - signer := sdk.AccAddress(privKey.PubKey().Address()) - - cases := []struct { - msg types.MsgCreateClient - expPass bool - errMsg string - }{ - {types.NewMsgCreateClient(exported.ClientTypeTendermint, exported.ClientTypeTendermint, cs, trustingPeriod, ubdPeriod, signer), true, "success msg should pass"}, - {types.NewMsgCreateClient("BADCHAIN", exported.ClientTypeTendermint, cs, trustingPeriod, ubdPeriod, signer), false, "invalid client id passed"}, - {types.NewMsgCreateClient("goodchain", "invalid_client_type", cs, trustingPeriod, ubdPeriod, signer), false, "unregistered client type passed"}, - {types.NewMsgCreateClient("goodchain", exported.ClientTypeTendermint, nil, trustingPeriod, ubdPeriod, signer), false, "nil Consensus State in msg passed"}, - {types.NewMsgCreateClient("goodchain", exported.ClientTypeTendermint, tendermint.ConsensusState{}, trustingPeriod, ubdPeriod, signer), false, "invalid Consensus State in msg passed"}, - {types.NewMsgCreateClient("goodchain", exported.ClientTypeTendermint, cs, 0, ubdPeriod, signer), false, "zero trusting period passed"}, - {types.NewMsgCreateClient("goodchain", exported.ClientTypeTendermint, cs, trustingPeriod, 0, signer), false, "zero unbonding period passed"}, - {types.NewMsgCreateClient("goodchain", exported.ClientTypeTendermint, cs, trustingPeriod, ubdPeriod, nil), false, "Empty address passed"}, - } - - for i, tc := range cases { - err := tc.msg.ValidateBasic() - if tc.expPass { - require.NoError(t, err, "Msg %d failed: %v", i, err) - } else { - require.Error(t, err, "Invalid Msg %d passed: %s", i, tc.errMsg) - } - } -} - -func TestMsgUpdateClient(t *testing.T) { - privKey := secp256k1.GenPrivKey() - signer := sdk.AccAddress(privKey.PubKey().Address()) - - cases := []struct { - msg types.MsgUpdateClient - expPass bool - errMsg string - }{ - {types.NewMsgUpdateClient(exported.ClientTypeTendermint, tendermint.Header{}, signer), true, "success msg should pass"}, - {types.NewMsgUpdateClient("badClient", tendermint.Header{}, signer), false, "invalid client id passed"}, - {types.NewMsgUpdateClient(exported.ClientTypeTendermint, nil, signer), false, "Nil Header passed"}, - {types.NewMsgUpdateClient(exported.ClientTypeTendermint, tendermint.Header{}, nil), false, "Empty address passed"}, - } - - for i, tc := range cases { - err := tc.msg.ValidateBasic() - if tc.expPass { - require.NoError(t, err, "Msg %d failed: %v", i, err) - } else { - require.Error(t, err, "Invalid Msg %d passed: %s", i, tc.errMsg) - } - } -} diff --git a/x/ibc/07-tendermint/client/cli/cli.go b/x/ibc/07-tendermint/client/cli/cli.go new file mode 100644 index 000000000000..0d525777850c --- /dev/null +++ b/x/ibc/07-tendermint/client/cli/cli.go @@ -0,0 +1,26 @@ +package cli + +import ( + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/codec" +) + +// GetTxCmd returns the transaction commands for IBC clients +func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { + ics07TendermintTxCmd := &cobra.Command{ + Use: "tendermint", + Short: "Tendermint transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + } + + ics07TendermintTxCmd.AddCommand(flags.PostCommands( + GetCmdCreateClient(cdc), + GetCmdUpdateClient(cdc), + GetCmdSubmitMisbehaviour(cdc), + )...) + + return ics07TendermintTxCmd +} diff --git a/x/ibc/02-client/client/cli/tx.go b/x/ibc/07-tendermint/client/cli/tx.go similarity index 94% rename from x/ibc/02-client/client/cli/tx.go rename to x/ibc/07-tendermint/client/cli/tx.go index 78d3973c53b7..2b6636df0f3c 100644 --- a/x/ibc/02-client/client/cli/tx.go +++ b/x/ibc/07-tendermint/client/cli/tx.go @@ -20,8 +20,7 @@ import ( authclient "github.com/cosmos/cosmos-sdk/x/auth/client" "github.com/cosmos/cosmos-sdk/x/evidence" evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" ) // GetCmdCreateClient defines the command to create a new IBC Client as defined @@ -44,7 +43,7 @@ $ %s tx ibc client create [client-id] [path/to/consensus_state.json] [trusting_p clientID := args[0] - var state exported.ConsensusState + var state ibctmtypes.ConsensusState if err := cdc.UnmarshalJSON([]byte(args[1]), &state); err != nil { // check for file path if JSON input is not provided contents, err := ioutil.ReadFile(args[1]) @@ -66,8 +65,8 @@ $ %s tx ibc client create [client-id] [path/to/consensus_state.json] [trusting_p return err } - msg := types.NewMsgCreateClient( - clientID, state.ClientType().String(), state, + msg := ibctmtypes.NewMsgCreateClient( + clientID, state, trustingPeriod, ubdPeriod, cliCtx.GetFromAddress(), ) @@ -101,7 +100,7 @@ $ %s tx ibc client update [client-id] [path/to/header.json] --from node0 --home clientID := args[0] - var header exported.Header + var header ibctmtypes.Header if err := cdc.UnmarshalJSON([]byte(args[1]), &header); err != nil { // check for file path if JSON input is not provided contents, err := ioutil.ReadFile(args[1]) @@ -113,7 +112,7 @@ $ %s tx ibc client update [client-id] [path/to/header.json] --from node0 --home } } - msg := types.NewMsgUpdateClient(clientID, header, cliCtx.GetFromAddress()) + msg := ibctmtypes.NewMsgUpdateClient(clientID, header, cliCtx.GetFromAddress()) if err := msg.ValidateBasic(); err != nil { return err } diff --git a/x/ibc/07-tendermint/client/rest/rest.go b/x/ibc/07-tendermint/client/rest/rest.go new file mode 100644 index 000000000000..af6d5021ada3 --- /dev/null +++ b/x/ibc/07-tendermint/client/rest/rest.go @@ -0,0 +1,44 @@ +package rest + +import ( + "time" + + "github.com/gorilla/mux" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/types/rest" + evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" +) + +// REST client flags +const ( + RestClientID = "client-id" + RestRootHeight = "height" +) + +// RegisterRoutes - Central function to define routes that get registered by the main application +func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, queryRoute string) { + registerTxRoutes(cliCtx, r) +} + +// CreateClientReq defines the properties of a create client request's body. +type CreateClientReq struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + ClientID string `json:"client_id" yaml:"client_id"` + ConsensusState ibctmtypes.ConsensusState `json:"consensus_state" yaml:"consensus_state"` + TrustingPeriod time.Duration `json:"trusting_period" yaml:"trusting_period"` + UnbondingPeriod time.Duration `json:"unbonding_period" yaml:"unbonding_period"` +} + +// UpdateClientReq defines the properties of a update client request's body. +type UpdateClientReq struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + Header ibctmtypes.Header `json:"header" yaml:"header"` +} + +// SubmitMisbehaviourReq defines the properties of a submit misbehaviour request's body. +type SubmitMisbehaviourReq struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + Evidence evidenceexported.Evidence `json:"evidence" yaml:"evidence"` +} diff --git a/x/ibc/07-tendermint/client/rest/swagger.go b/x/ibc/07-tendermint/client/rest/swagger.go new file mode 100644 index 000000000000..34d5f30af8c7 --- /dev/null +++ b/x/ibc/07-tendermint/client/rest/swagger.go @@ -0,0 +1,31 @@ +package rest + +import ( + auth "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/evidence" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" +) + +// nolint +type ( + PostCreateClient struct { + Msgs []ibctmtypes.MsgCreateClient `json:"msg" yaml:"msg"` + Fee auth.StdFee `json:"fee" yaml:"fee"` + Signatures []auth.StdSignature `json:"signatures" yaml:"signatures"` + Memo string `json:"memo" yaml:"memo"` + } + + PostUpdateClient struct { + Msgs []ibctmtypes.MsgUpdateClient `json:"msg" yaml:"msg"` + Fee auth.StdFee `json:"fee" yaml:"fee"` + Signatures []auth.StdSignature `json:"signatures" yaml:"signatures"` + Memo string `json:"memo" yaml:"memo"` + } + + PostSubmitMisbehaviour struct { + Msgs []evidence.MsgSubmitEvidence `json:"msg" yaml:"msg"` + Fee auth.StdFee `json:"fee" yaml:"fee"` + Signatures []auth.StdSignature `json:"signatures" yaml:"signatures"` + Memo string `json:"memo" yaml:"memo"` + } +) diff --git a/x/ibc/02-client/client/rest/tx.go b/x/ibc/07-tendermint/client/rest/tx.go similarity index 96% rename from x/ibc/02-client/client/rest/tx.go rename to x/ibc/07-tendermint/client/rest/tx.go index f1cf87dd4d48..964ce27588d2 100644 --- a/x/ibc/02-client/client/rest/tx.go +++ b/x/ibc/07-tendermint/client/rest/tx.go @@ -11,7 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/rest" authclient "github.com/cosmos/cosmos-sdk/x/auth/client" "github.com/cosmos/cosmos-sdk/x/evidence" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" ) // RegisterRoutes - Central function to define routes that get registered by the main application @@ -50,9 +50,8 @@ func createClientHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { } // create the message - msg := types.NewMsgCreateClient( + msg := ibctmtypes.NewMsgCreateClient( req.ClientID, - req.ConsensusState.ClientType().String(), req.ConsensusState, req.TrustingPeriod, req.UnbondingPeriod, fromAddr, @@ -101,7 +100,7 @@ func updateClientHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { } // create the message - msg := types.NewMsgUpdateClient( + msg := ibctmtypes.NewMsgUpdateClient( clientID, req.Header, fromAddr, diff --git a/x/ibc/07-tendermint/misbehaviour.go b/x/ibc/07-tendermint/misbehaviour.go index 557d8f855e05..9f53342b43cb 100644 --- a/x/ibc/07-tendermint/misbehaviour.go +++ b/x/ibc/07-tendermint/misbehaviour.go @@ -9,6 +9,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" + "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" ) @@ -26,17 +27,17 @@ func CheckMisbehaviourAndUpdateState( ) (clientexported.ClientState, error) { // cast the interface to specific types before checking for misbehaviour - tmClientState, ok := clientState.(ClientState) + tmClientState, ok := clientState.(types.ClientState) if !ok { return nil, sdkerrors.Wrap(clienttypes.ErrInvalidClientType, "client state type is not Tendermint") } - tmConsensusState, ok := consensusState.(ConsensusState) + tmConsensusState, ok := consensusState.(types.ConsensusState) if !ok { return nil, sdkerrors.Wrap(clienttypes.ErrInvalidClientType, "consensus state is not Tendermint") } - tmEvidence, ok := misbehaviour.(Evidence) + tmEvidence, ok := misbehaviour.(types.Evidence) if !ok { return nil, sdkerrors.Wrap(clienttypes.ErrInvalidClientType, "evidence type is not Tendermint") } @@ -62,7 +63,7 @@ func CheckMisbehaviourAndUpdateState( // checkMisbehaviour checks if the evidence provided is a valid light client misbehaviour func checkMisbehaviour( - clientState ClientState, consensusState ConsensusState, evidence Evidence, + clientState types.ClientState, consensusState types.ConsensusState, evidence types.Evidence, height uint64, currentTimestamp time.Time, ) error { // check if provided height matches the headers' height diff --git a/x/ibc/07-tendermint/misbehaviour_test.go b/x/ibc/07-tendermint/misbehaviour_test.go index 789795c97d94..d6dab36888fa 100644 --- a/x/ibc/07-tendermint/misbehaviour_test.go +++ b/x/ibc/07-tendermint/misbehaviour_test.go @@ -7,6 +7,7 @@ import ( tmtypes "github.com/tendermint/tendermint/types" tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -31,19 +32,19 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { testCases := []struct { name string - clientState tendermint.ClientState - consensusState tendermint.ConsensusState - evidence tendermint.Evidence + clientState ibctmtypes.ClientState + consensusState ibctmtypes.ConsensusState + evidence ibctmtypes.Evidence height uint64 expPass bool }{ { "valid misbehavior evidence", - tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: 0}, - tendermint.ConsensusState{Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, - tendermint.Evidence{ - Header1: tendermint.CreateTestHeader(chainID, height, suite.now, bothValset, suite.valSet, bothSigners), - Header2: tendermint.CreateTestHeader(chainID, height, suite.now, bothValset, bothValSet, bothSigners), + ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, suite.valSet, bothSigners), + Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), ChainID: chainID, ClientID: chainID, }, @@ -52,37 +53,37 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { }, { "height doesn't match provided evidence", - tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: 0}, - tendermint.ConsensusState{Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, - tendermint.Evidence{ - Header1: tendermint.CreateTestHeader(chainID, height, suite.now, bothValset, suite.valSet, bothSigners), - Header2: tendermint.CreateTestHeader(chainID, height, suite.now, bothValset, bothValSet, bothSigners), + ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, suite.valSet, bothSigners), + Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), ChainID: chainID, ClientID: chainID, }, 0, false, }, - { - "consensus state's valset hash different from evidence", - tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: 0}, - tendermint.ConsensusState{Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: suite.valSet}, - tendermint.Evidence{ - Header1: tendermint.CreateTestHeader(chainID, height, suite.now, bothValset, suite.valSet, bothSigners), - Header2: tendermint.CreateTestHeader(chainID, height, suite.now, bothValset, bothValSet, bothSigners), - ChainID: chainID, - ClientID: chainID, - }, - height, - false, - }, + // { + // "consensus state's valset hash different from evidence", + // ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + // ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: suite.valSet}, + // ibctmtypes.Evidence{ + // Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, suite.valSet, bothSigners), + // Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), + // ChainID: chainID, + // ClientID: chainID, + // }, + // height, + // false, + // }, { "first valset has too much change", - tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: 0}, - tendermint.ConsensusState{Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, - tendermint.Evidence{ - Header1: tendermint.CreateTestHeader(chainID, height, suite.now, altValSet, bothValSet, altSigners), - Header2: tendermint.CreateTestHeader(chainID, height, suite.now, bothValset, bothValSet, bothSigners), + ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, bothValSet, altSigners), + Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), ChainID: chainID, ClientID: chainID, }, @@ -91,11 +92,11 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { }, { "second valset has too much change", - tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: 0}, - tendermint.ConsensusState{Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, - tendermint.Evidence{ - Header1: tendermint.CreateTestHeader(chainID, height, suite.now, bothValset, bothValSet, bothSigners), - Header2: tendermint.CreateTestHeader(chainID, height, suite.now, altValSet, bothValSet, altSigners), + ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), + Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, bothValSet, altSigners), ChainID: chainID, ClientID: chainID, }, @@ -104,11 +105,11 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { }, { "both valsets have too much change", - tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: 0}, - tendermint.ConsensusState{Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, - tendermint.Evidence{ - Header1: tendermint.CreateTestHeader(chainID, height, suite.now, altValSet, altValSet, altSigners), - Header2: tendermint.CreateTestHeader(chainID, height, suite.now, altValSet, bothValSet, altSigners), + ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, altValSet, altSigners), + Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, bothValSet, altSigners), ChainID: chainID, ClientID: chainID, }, diff --git a/x/ibc/07-tendermint/module.go b/x/ibc/07-tendermint/module.go new file mode 100644 index 000000000000..f85765752a51 --- /dev/null +++ b/x/ibc/07-tendermint/module.go @@ -0,0 +1,29 @@ +package tendermint + +import ( + "fmt" + + "github.com/gorilla/mux" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/client/cli" + "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/client/rest" + "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" +) + +// Name returns the IBC client name +func Name() string { + return types.SubModuleName +} + +// RegisterRESTRoutes registers the REST routes for the IBC client +func RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router, queryRoute string) { + rest.RegisterRoutes(ctx, rtr, fmt.Sprintf("%s/%s", queryRoute, types.SubModuleName)) +} + +// GetTxCmd returns the root tx command for the IBC client +func GetTxCmd(cdc *codec.Codec, storeKey string) *cobra.Command { + return cli.GetTxCmd(fmt.Sprintf("%s/%s", storeKey, types.SubModuleName), cdc) +} diff --git a/x/ibc/07-tendermint/tendermint_test.go b/x/ibc/07-tendermint/tendermint_test.go index 02090e6acd5e..9c846c50fb3a 100644 --- a/x/ibc/07-tendermint/tendermint_test.go +++ b/x/ibc/07-tendermint/tendermint_test.go @@ -9,7 +9,7 @@ import ( tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/codec" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -23,24 +23,28 @@ const ( type TendermintTestSuite struct { suite.Suite - cdc *codec.Codec - privVal tmtypes.PrivValidator - valSet *tmtypes.ValidatorSet - header tendermint.Header - now time.Time + cdc *codec.Codec + privVal tmtypes.PrivValidator + valSet *tmtypes.ValidatorSet + header ibctmtypes.Header + now time.Time + clientTime time.Time + headerTime time.Time } func (suite *TendermintTestSuite) SetupTest() { suite.cdc = codec.New() codec.RegisterCrypto(suite.cdc) - tendermint.RegisterCodec(suite.cdc) + ibctmtypes.RegisterCodec(suite.cdc) commitment.RegisterCodec(suite.cdc) - suite.now = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) + suite.now = time.Date(2020, 1, 3, 0, 0, 0, 0, time.UTC) + suite.clientTime = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) + suite.headerTime = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) suite.privVal = tmtypes.NewMockPV() val := tmtypes.NewValidator(suite.privVal.GetPubKey(), 10) suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{val}) - suite.header = tendermint.CreateTestHeader(chainID, height, suite.now, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) + suite.header = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) } func TestTendermintTestSuite(t *testing.T) { diff --git a/x/ibc/07-tendermint/client_state.go b/x/ibc/07-tendermint/types/client_state.go similarity index 99% rename from x/ibc/07-tendermint/client_state.go rename to x/ibc/07-tendermint/types/client_state.go index bb5c36b5d7fa..0b6f4490e830 100644 --- a/x/ibc/07-tendermint/client_state.go +++ b/x/ibc/07-tendermint/types/client_state.go @@ -1,4 +1,4 @@ -package tendermint +package types import ( "errors" diff --git a/x/ibc/07-tendermint/client_state_test.go b/x/ibc/07-tendermint/types/client_state_test.go similarity index 70% rename from x/ibc/07-tendermint/client_state_test.go rename to x/ibc/07-tendermint/types/client_state_test.go index cd283a5ef381..208db3480313 100644 --- a/x/ibc/07-tendermint/client_state_test.go +++ b/x/ibc/07-tendermint/types/client_state_test.go @@ -1,11 +1,11 @@ -package tendermint_test +package types_test import ( connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" connectionexported "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/exported" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -19,16 +19,16 @@ const ( func (suite *TendermintTestSuite) TestVerifyClientConsensusState() { testCases := []struct { name string - clientState tendermint.ClientState - consensusState tendermint.ConsensusState + clientState ibctmtypes.ClientState + consensusState ibctmtypes.ConsensusState prefix commitment.Prefix proof commitment.Proof expPass bool }{ // { // name: "successful verification", - // clientState: tendermint.NewClientState(chainID, height), - // consensusState: tendermint.ConsensusState{ + // clientState: ibctmtypes.NewClientState(chainID, height), + // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), // }, // prefix: commitment.NewPrefix([]byte("ibc")), @@ -36,8 +36,8 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() { // }, { name: "ApplyPrefix failed", - clientState: tendermint.NewClientState(chainID, height), - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.Prefix{}, @@ -45,8 +45,8 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() { }, { name: "latest client height < height", - clientState: tendermint.NewClientState(chainID, height-1), - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -54,8 +54,8 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() { }, { name: "client is frozen", - clientState: tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -63,8 +63,8 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() { }, { name: "proof verification failed", - clientState: tendermint.NewClientState(chainID, height), - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, }, @@ -95,18 +95,18 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() { testCases := []struct { name string - clientState tendermint.ClientState + clientState ibctmtypes.ClientState connection connection.ConnectionEnd - consensusState tendermint.ConsensusState + consensusState ibctmtypes.ConsensusState prefix commitment.Prefix proof commitment.Proof expPass bool }{ // { // name: "successful verification", - // clientState: tendermint.NewClientState(chainID, height), + // clientState: ibctmtypes.NewClientState(chainID, height), // connection: conn, - // consensusState: tendermint.ConsensusState{ + // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), // }, // prefix: commitment.NewPrefix([]byte("ibc")), @@ -114,9 +114,9 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() { // }, { name: "ApplyPrefix failed", - clientState: tendermint.NewClientState(chainID, height), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), connection: conn, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.Prefix{}, @@ -124,9 +124,9 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() { }, { name: "latest client height < height", - clientState: tendermint.NewClientState(chainID, height-1), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), connection: conn, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -134,9 +134,9 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() { }, { name: "client is frozen", - clientState: tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, + clientState: ibctmtypes.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, connection: conn, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -144,9 +144,9 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() { }, { name: "proof verification failed", - clientState: tendermint.NewClientState(chainID, height), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), connection: conn, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, }, @@ -177,18 +177,18 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() { testCases := []struct { name string - clientState tendermint.ClientState + clientState ibctmtypes.ClientState channel channel.Channel - consensusState tendermint.ConsensusState + consensusState ibctmtypes.ConsensusState prefix commitment.Prefix proof commitment.Proof expPass bool }{ // { // name: "successful verification", - // clientState: tendermint.NewClientState(chainID, height), + // clientState: ibctmtypes.NewClientState(chainID, height), // connection: conn, - // consensusState: tendermint.ConsensusState{ + // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), // }, // prefix: commitment.NewPrefix([]byte("ibc")), @@ -196,9 +196,9 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() { // }, { name: "ApplyPrefix failed", - clientState: tendermint.NewClientState(chainID, height), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), channel: ch, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.Prefix{}, @@ -206,9 +206,9 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() { }, { name: "latest client height < height", - clientState: tendermint.NewClientState(chainID, height-1), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), channel: ch, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -216,9 +216,9 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() { }, { name: "client is frozen", - clientState: tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, + clientState: ibctmtypes.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, channel: ch, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -226,9 +226,9 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() { }, { name: "proof verification failed", - clientState: tendermint.NewClientState(chainID, height), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), channel: ch, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, }, @@ -256,18 +256,18 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() { func (suite *TendermintTestSuite) TestVerifyPacketCommitment() { testCases := []struct { name string - clientState tendermint.ClientState + clientState ibctmtypes.ClientState commitment []byte - consensusState tendermint.ConsensusState + consensusState ibctmtypes.ConsensusState prefix commitment.Prefix proof commitment.Proof expPass bool }{ // { // name: "successful verification", - // clientState: tendermint.NewClientState(chainID, height), + // clientState: ibctmtypes.NewClientState(chainID, height), // connection: conn, - // consensusState: tendermint.ConsensusState{ + // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), // }, // prefix: commitment.NewPrefix([]byte("ibc")), @@ -275,9 +275,9 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() { // }, { name: "ApplyPrefix failed", - clientState: tendermint.NewClientState(chainID, height), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), commitment: []byte{}, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.Prefix{}, @@ -285,9 +285,9 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() { }, { name: "latest client height < height", - clientState: tendermint.NewClientState(chainID, height-1), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), commitment: []byte{}, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -295,9 +295,9 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() { }, { name: "client is frozen", - clientState: tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, + clientState: ibctmtypes.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, commitment: []byte{}, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -305,9 +305,9 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() { }, { name: "proof verification failed", - clientState: tendermint.NewClientState(chainID, height), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), commitment: []byte{}, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, }, @@ -335,18 +335,18 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() { func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() { testCases := []struct { name string - clientState tendermint.ClientState + clientState ibctmtypes.ClientState ack []byte - consensusState tendermint.ConsensusState + consensusState ibctmtypes.ConsensusState prefix commitment.Prefix proof commitment.Proof expPass bool }{ // { // name: "successful verification", - // clientState: tendermint.NewClientState(chainID, height), + // clientState: ibctmtypes.NewClientState(chainID, height), // connection: conn, - // consensusState: tendermint.ConsensusState{ + // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), // }, // prefix: commitment.NewPrefix([]byte("ibc")), @@ -354,9 +354,9 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() { // }, { name: "ApplyPrefix failed", - clientState: tendermint.NewClientState(chainID, height), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), ack: []byte{}, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.Prefix{}, @@ -364,9 +364,9 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() { }, { name: "latest client height < height", - clientState: tendermint.NewClientState(chainID, height-1), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), ack: []byte{}, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -374,9 +374,9 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() { }, { name: "client is frozen", - clientState: tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, + clientState: ibctmtypes.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, ack: []byte{}, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -384,9 +384,9 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() { }, { name: "proof verification failed", - clientState: tendermint.NewClientState(chainID, height), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), ack: []byte{}, - consensusState: tendermint.ConsensusState{ + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, }, @@ -414,17 +414,17 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() { func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() { testCases := []struct { name string - clientState tendermint.ClientState - consensusState tendermint.ConsensusState + clientState ibctmtypes.ClientState + consensusState ibctmtypes.ConsensusState prefix commitment.Prefix proof commitment.Proof expPass bool }{ // { // name: "successful verification", - // clientState: tendermint.NewClientState(chainID, height), + // clientState: ibctmtypes.NewClientState(chainID, height), // connection: conn, - // consensusState: tendermint.ConsensusState{ + // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), // }, // prefix: commitment.NewPrefix([]byte("ibc")), @@ -432,8 +432,8 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() { // }, { name: "ApplyPrefix failed", - clientState: tendermint.NewClientState(chainID, height), - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.Prefix{}, @@ -441,8 +441,8 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() { }, { name: "latest client height < height", - clientState: tendermint.NewClientState(chainID, height-1), - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -450,8 +450,8 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() { }, { name: "client is frozen", - clientState: tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -459,8 +459,8 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() { }, { name: "proof verification failed", - clientState: tendermint.NewClientState(chainID, height), - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, }, @@ -488,17 +488,17 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() { func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() { testCases := []struct { name string - clientState tendermint.ClientState - consensusState tendermint.ConsensusState + clientState ibctmtypes.ClientState + consensusState ibctmtypes.ConsensusState prefix commitment.Prefix proof commitment.Proof expPass bool }{ // { // name: "successful verification", - // clientState: tendermint.NewClientState(chainID, height), + // clientState: ibctmtypes.NewClientState(chainID, height), // connection: conn, - // consensusState: tendermint.ConsensusState{ + // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), // }, // prefix: commitment.NewPrefix([]byte("ibc")), @@ -506,8 +506,8 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() { // }, { name: "ApplyPrefix failed", - clientState: tendermint.NewClientState(chainID, height), - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.Prefix{}, @@ -515,8 +515,8 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() { }, { name: "latest client height < height", - clientState: tendermint.NewClientState(chainID, height-1), - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -524,8 +524,8 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() { }, { name: "client is frozen", - clientState: tendermint.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.ClientState{ID: chainID, LatestHeight: height, FrozenHeight: height - 1}, + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, prefix: commitment.NewPrefix([]byte("ibc")), @@ -533,8 +533,8 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() { }, { name: "proof verification failed", - clientState: tendermint.NewClientState(chainID, height), - consensusState: tendermint.ConsensusState{ + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, }, diff --git a/x/ibc/07-tendermint/codec.go b/x/ibc/07-tendermint/types/codec.go similarity index 80% rename from x/ibc/07-tendermint/codec.go rename to x/ibc/07-tendermint/types/codec.go index 22c6d508ed6a..61e63c31f603 100644 --- a/x/ibc/07-tendermint/codec.go +++ b/x/ibc/07-tendermint/types/codec.go @@ -1,4 +1,4 @@ -package tendermint +package types import ( "github.com/cosmos/cosmos-sdk/codec" @@ -13,6 +13,8 @@ func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(ConsensusState{}, "ibc/client/tendermint/ConsensusState", nil) cdc.RegisterConcrete(Header{}, "ibc/client/tendermint/Header", nil) cdc.RegisterConcrete(Evidence{}, "ibc/client/tendermint/Evidence", nil) + cdc.RegisterConcrete(MsgCreateClient{}, "ibc/client/MsgCreateClient", nil) + cdc.RegisterConcrete(MsgUpdateClient{}, "ibc/client/MsgUpdateClient", nil) SetSubModuleCodec(cdc) } diff --git a/x/ibc/07-tendermint/consensus_state.go b/x/ibc/07-tendermint/types/consensus_state.go similarity index 98% rename from x/ibc/07-tendermint/consensus_state.go rename to x/ibc/07-tendermint/types/consensus_state.go index 01633b118104..de890243bb84 100644 --- a/x/ibc/07-tendermint/consensus_state.go +++ b/x/ibc/07-tendermint/types/consensus_state.go @@ -1,4 +1,4 @@ -package tendermint +package types import ( "time" diff --git a/x/ibc/07-tendermint/consensus_state_test.go b/x/ibc/07-tendermint/types/consensus_state_test.go similarity index 72% rename from x/ibc/07-tendermint/consensus_state_test.go rename to x/ibc/07-tendermint/types/consensus_state_test.go index 9d7d92936eef..90499ddb483c 100644 --- a/x/ibc/07-tendermint/consensus_state_test.go +++ b/x/ibc/07-tendermint/types/consensus_state_test.go @@ -1,57 +1,50 @@ -package tendermint_test +package types_test import ( "time" clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) func (suite *TendermintTestSuite) TestConsensusStateValidateBasic() { testCases := []struct { msg string - consensusState tendermint.ConsensusState + consensusState ibctmtypes.ConsensusState expectPass bool }{ {"success", - tendermint.ConsensusState{ + ibctmtypes.ConsensusState{ Timestamp: suite.now, Root: commitment.NewRoot([]byte("app_hash")), ValidatorSet: suite.valSet, }, true}, {"root is nil", - tendermint.ConsensusState{ + ibctmtypes.ConsensusState{ Timestamp: suite.now, Root: nil, ValidatorSet: suite.valSet, }, false}, {"root is empty", - tendermint.ConsensusState{ + ibctmtypes.ConsensusState{ Timestamp: suite.now, Root: commitment.Root{}, ValidatorSet: suite.valSet, }, false}, - {"invalid client type", - tendermint.ConsensusState{ - Timestamp: suite.now, - Root: commitment.NewRoot([]byte("app_hash")), - ValidatorSet: suite.valSet, - }, - false}, {"valset is nil", - tendermint.ConsensusState{ + ibctmtypes.ConsensusState{ Timestamp: suite.now, Root: commitment.NewRoot([]byte("app_hash")), ValidatorSet: nil, }, false}, - {"valset is nil", - tendermint.ConsensusState{ - Timestamp: time.Unix(0, 0), + {"timestamp is zero", + ibctmtypes.ConsensusState{ + Timestamp: time.Time{}, Root: commitment.NewRoot([]byte("app_hash")), ValidatorSet: suite.valSet, }, diff --git a/x/ibc/07-tendermint/types/errors.go b/x/ibc/07-tendermint/types/errors.go new file mode 100644 index 000000000000..1348d340fabb --- /dev/null +++ b/x/ibc/07-tendermint/types/errors.go @@ -0,0 +1,14 @@ +package types + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const ( + SubModuleName = "tendermint" +) + +var ( + ErrInvalidTrustingPeriod = sdkerrors.Register(SubModuleName, 1, "invalid trusting period") + ErrInvalidUnbondingPeriod = sdkerrors.Register(SubModuleName, 2, "invalid unbonding period") +) diff --git a/x/ibc/07-tendermint/evidence.go b/x/ibc/07-tendermint/types/evidence.go similarity index 99% rename from x/ibc/07-tendermint/evidence.go rename to x/ibc/07-tendermint/types/evidence.go index 49d8d3629a5a..d161c10ed5dc 100644 --- a/x/ibc/07-tendermint/evidence.go +++ b/x/ibc/07-tendermint/types/evidence.go @@ -1,4 +1,4 @@ -package tendermint +package types import ( "math" diff --git a/x/ibc/07-tendermint/evidence_test.go b/x/ibc/07-tendermint/types/evidence_test.go similarity index 73% rename from x/ibc/07-tendermint/evidence_test.go rename to x/ibc/07-tendermint/types/evidence_test.go index 4e6eb21f4828..2a7384224896 100644 --- a/x/ibc/07-tendermint/evidence_test.go +++ b/x/ibc/07-tendermint/types/evidence_test.go @@ -1,4 +1,4 @@ -package tendermint_test +package types_test import ( "bytes" @@ -8,15 +8,15 @@ import ( tmtypes "github.com/tendermint/tendermint/types" clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" ) func (suite *TendermintTestSuite) TestEvidence() { signers := []tmtypes.PrivValidator{suite.privVal} - ev := tendermint.Evidence{ + ev := ibctmtypes.Evidence{ Header1: suite.header, - Header2: tendermint.CreateTestHeader(chainID, height, suite.now, suite.valSet, suite.valSet, signers), + Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, suite.valSet, suite.valSet, signers), ChainID: chainID, ClientID: "gaiamainnet", } @@ -25,7 +25,7 @@ func (suite *TendermintTestSuite) TestEvidence() { suite.Require().Equal(ev.GetClientID(), "gaiamainnet") suite.Require().Equal(ev.Route(), "client") suite.Require().Equal(ev.Type(), "client_misbehaviour") - suite.Require().Equal(ev.Hash(), tmbytes.HexBytes(tmhash.Sum(tendermint.SubModuleCdc.MustMarshalBinaryBare(ev)))) + suite.Require().Equal(ev.Hash(), tmbytes.HexBytes(tmhash.Sum(ibctmtypes.SubModuleCdc.MustMarshalBinaryBare(ev)))) suite.Require().Equal(ev.GetHeight(), int64(height)) } @@ -51,85 +51,85 @@ func (suite *TendermintTestSuite) TestEvidenceValidateBasic() { testCases := []struct { name string - evidence tendermint.Evidence - malleateEvidence func(ev *tendermint.Evidence) error + evidence ibctmtypes.Evidence + malleateEvidence func(ev *ibctmtypes.Evidence) error expPass bool }{ { "valid evidence", - tendermint.Evidence{ + ibctmtypes.Evidence{ Header1: suite.header, - Header2: tendermint.CreateTestHeader(chainID, height, suite.now, suite.valSet, bothValSet, signers), + Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, suite.valSet, bothValSet, signers), ChainID: chainID, ClientID: "gaiamainnet", }, - func(ev *tendermint.Evidence) error { return nil }, + func(ev *ibctmtypes.Evidence) error { return nil }, true, }, { "invalid client ID ", - tendermint.Evidence{ + ibctmtypes.Evidence{ Header1: suite.header, - Header2: tendermint.CreateTestHeader(chainID, height, suite.now, suite.valSet, bothValSet, signers), + Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, suite.valSet, bothValSet, signers), ChainID: chainID, ClientID: "GAIA", }, - func(ev *tendermint.Evidence) error { return nil }, + func(ev *ibctmtypes.Evidence) error { return nil }, false, }, { "wrong chainID on header1", - tendermint.Evidence{ + ibctmtypes.Evidence{ Header1: suite.header, - Header2: tendermint.CreateTestHeader("ethermint", height, suite.now, suite.valSet, bothValSet, signers), + Header2: ibctmtypes.CreateTestHeader("ethermint", height, suite.now, suite.valSet, bothValSet, signers), ChainID: "ethermint", ClientID: "gaiamainnet", }, - func(ev *tendermint.Evidence) error { return nil }, + func(ev *ibctmtypes.Evidence) error { return nil }, false, }, { "wrong chainID on header2", - tendermint.Evidence{ + ibctmtypes.Evidence{ Header1: suite.header, - Header2: tendermint.CreateTestHeader("ethermint", height, suite.now, suite.valSet, bothValSet, signers), + Header2: ibctmtypes.CreateTestHeader("ethermint", height, suite.now, suite.valSet, bothValSet, signers), ChainID: chainID, ClientID: "gaiamainnet", }, - func(ev *tendermint.Evidence) error { return nil }, + func(ev *ibctmtypes.Evidence) error { return nil }, false, }, { "mismatched heights", - tendermint.Evidence{ + ibctmtypes.Evidence{ Header1: suite.header, - Header2: tendermint.CreateTestHeader(chainID, 6, suite.now, suite.valSet, bothValSet, signers), + Header2: ibctmtypes.CreateTestHeader(chainID, 6, suite.now, suite.valSet, bothValSet, signers), ChainID: chainID, ClientID: "gaiamainnet", }, - func(ev *tendermint.Evidence) error { return nil }, + func(ev *ibctmtypes.Evidence) error { return nil }, false, }, { "same block id", - tendermint.Evidence{ + ibctmtypes.Evidence{ Header1: suite.header, Header2: suite.header, ChainID: chainID, ClientID: "gaiamainnet", }, - func(ev *tendermint.Evidence) error { return nil }, + func(ev *ibctmtypes.Evidence) error { return nil }, false, }, { "header 1 doesn't have 2/3 majority", - tendermint.Evidence{ - Header1: tendermint.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), Header2: suite.header, ChainID: chainID, ClientID: "gaiamainnet", }, - func(ev *tendermint.Evidence) error { + func(ev *ibctmtypes.Evidence) error { // voteSet contains only altVal which is less than 2/3 of total power (height/1height) wrongVoteSet := tmtypes.NewVoteSet(chainID, ev.Header1.Height, 1, tmtypes.PrecommitType, altValSet) var err error @@ -140,13 +140,13 @@ func (suite *TendermintTestSuite) TestEvidenceValidateBasic() { }, { "header 2 doesn't have 2/3 majority", - tendermint.Evidence{ + ibctmtypes.Evidence{ Header1: suite.header, - Header2: tendermint.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), + Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), ChainID: chainID, ClientID: "gaiamainnet", }, - func(ev *tendermint.Evidence) error { + func(ev *ibctmtypes.Evidence) error { // voteSet contains only altVal which is less than 2/3 of total power (height/1height) wrongVoteSet := tmtypes.NewVoteSet(chainID, ev.Header2.Height, 1, tmtypes.PrecommitType, altValSet) var err error @@ -157,14 +157,14 @@ func (suite *TendermintTestSuite) TestEvidenceValidateBasic() { }, { "validators sign off on wrong commit", - tendermint.Evidence{ + ibctmtypes.Evidence{ Header1: suite.header, - Header2: tendermint.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), + Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), ChainID: chainID, ClientID: "gaiamainnet", }, - func(ev *tendermint.Evidence) error { - ev.Header2.Commit.BlockID = tendermint.MakeBlockID(tmhash.Sum([]byte("other_hash")), 3, tmhash.Sum([]byte("other_partset"))) + func(ev *ibctmtypes.Evidence) error { + ev.Header2.Commit.BlockID = ibctmtypes.MakeBlockID(tmhash.Sum([]byte("other_hash")), 3, tmhash.Sum([]byte("other_partset"))) return nil }, false, diff --git a/x/ibc/07-tendermint/header.go b/x/ibc/07-tendermint/types/header.go similarity index 99% rename from x/ibc/07-tendermint/header.go rename to x/ibc/07-tendermint/types/header.go index fb53e36641b8..ed35e905c4e1 100644 --- a/x/ibc/07-tendermint/header.go +++ b/x/ibc/07-tendermint/types/header.go @@ -1,4 +1,4 @@ -package tendermint +package types import ( abci "github.com/tendermint/tendermint/abci/types" diff --git a/x/ibc/07-tendermint/header_test.go b/x/ibc/07-tendermint/types/header_test.go similarity index 80% rename from x/ibc/07-tendermint/header_test.go rename to x/ibc/07-tendermint/types/header_test.go index e88362d230d3..c5c004028a7f 100644 --- a/x/ibc/07-tendermint/header_test.go +++ b/x/ibc/07-tendermint/types/header_test.go @@ -1,20 +1,20 @@ -package tendermint_test +package types_test import ( clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" ) func (suite *TendermintTestSuite) TestHeaderValidateBasic() { testCases := []struct { name string - header tendermint.Header + header ibctmtypes.Header chainID string expPass bool }{ {"valid header", suite.header, chainID, true}, {"signed header basic validation failed", suite.header, "chainID", false}, - {"validator set nil", tendermint.Header{suite.header.SignedHeader, nil}, chainID, false}, + {"validator set nil", ibctmtypes.Header{suite.header.SignedHeader, nil}, chainID, false}, } suite.Require().Equal(clientexported.Tendermint, suite.header.ClientType()) diff --git a/x/ibc/02-client/types/msgs.go b/x/ibc/07-tendermint/types/msgs.go similarity index 63% rename from x/ibc/02-client/types/msgs.go rename to x/ibc/07-tendermint/types/msgs.go index ba9fe9169ec5..6382f916d0b0 100644 --- a/x/ibc/02-client/types/msgs.go +++ b/x/ibc/07-tendermint/types/msgs.go @@ -5,7 +5,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" + + clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" host "github.com/cosmos/cosmos-sdk/x/ibc/24-host" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" ) @@ -17,26 +18,25 @@ const ( TypeClientMisbehaviour string = "client_misbehaviour" ) -var _ sdk.Msg = MsgCreateClient{} +var _ clientexported.MsgCreateClient = MsgCreateClient{} +var _ clientexported.MsgUpdateClient = MsgUpdateClient{} // MsgCreateClient defines a message to create an IBC client type MsgCreateClient struct { - ClientID string `json:"client_id" yaml:"client_id"` - ClientType string `json:"client_type" yaml:"client_type"` - ConsensusState exported.ConsensusState `json:"consensus_state" yaml:"consensus_address"` - TrustingPeriod time.Duration `json:"trusting_period" yaml:"trusting_period"` - UnbondingPeriod time.Duration `json:"unbonding_period" yaml:"unbonding_period"` - Signer sdk.AccAddress `json:"address" yaml:"address"` + ClientID string `json:"client_id" yaml:"client_id"` + ConsensusState ConsensusState `json:"consensus_state" yaml:"consensus_state"` + TrustingPeriod time.Duration `json:"trusting_period" yaml:"trusting_period"` + UnbondingPeriod time.Duration `json:"unbonding_period" yaml:"unbonding_period"` + Signer sdk.AccAddress `json:"address" yaml:"address"` } // NewMsgCreateClient creates a new MsgCreateClient instance func NewMsgCreateClient( - id, clientType string, consensusState exported.ConsensusState, + id string, consensusState ConsensusState, trustingPeriod, unbondingPeriod time.Duration, signer sdk.AccAddress, ) MsgCreateClient { return MsgCreateClient{ ClientID: id, - ClientType: clientType, ConsensusState: consensusState, TrustingPeriod: trustingPeriod, UnbondingPeriod: unbondingPeriod, @@ -56,12 +56,6 @@ func (msg MsgCreateClient) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgCreateClient) ValidateBasic() error { - if clientType := exported.ClientTypeFromString(msg.ClientType); clientType == 0 { - return sdkerrors.Wrap(ErrInvalidClientType, msg.ClientType) - } - if msg.ConsensusState == nil { - return ErrInvalidConsensus - } if err := msg.ConsensusState.ValidateBasic(); err != nil { return err } @@ -87,17 +81,30 @@ func (msg MsgCreateClient) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{msg.Signer} } -var _ sdk.Msg = MsgUpdateClient{} +// GetClientID implements clientexported.MsgCreateClient +func (msg MsgCreateClient) GetClientID() string { + return msg.ClientID +} + +// GetClientType implements clientexported.MsgCreateClient +func (msg MsgCreateClient) GetClientType() string { + return clientexported.ClientTypeTendermint +} + +// GetConsensusState implements clientexported.MsgCreateClient +func (msg MsgCreateClient) GetConsensusState() clientexported.ConsensusState { + return msg.ConsensusState +} // MsgUpdateClient defines a message to update an IBC client type MsgUpdateClient struct { - ClientID string `json:"client_id" yaml:"client_id"` - Header exported.Header `json:"header" yaml:"header"` - Signer sdk.AccAddress `json:"address" yaml:"address"` + ClientID string `json:"client_id" yaml:"client_id"` + Header Header `json:"header" yaml:"header"` + Signer sdk.AccAddress `json:"address" yaml:"address"` } // NewMsgUpdateClient creates a new MsgUpdateClient instance -func NewMsgUpdateClient(id string, header exported.Header, signer sdk.AccAddress) MsgUpdateClient { +func NewMsgUpdateClient(id string, header Header, signer sdk.AccAddress) MsgUpdateClient { return MsgUpdateClient{ ClientID: id, Header: header, @@ -117,9 +124,6 @@ func (msg MsgUpdateClient) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgUpdateClient) ValidateBasic() error { - if msg.Header == nil { - return ErrInvalidHeader - } if msg.Signer.Empty() { return sdkerrors.ErrInvalidAddress } @@ -135,3 +139,13 @@ func (msg MsgUpdateClient) GetSignBytes() []byte { func (msg MsgUpdateClient) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{msg.Signer} } + +// GetClientID implements clientexported.MsgUpdateClient +func (msg MsgUpdateClient) GetClientID() string { + return msg.ClientID +} + +// GetHeader implements clientexported.MsgUpdateClient +func (msg MsgUpdateClient) GetHeader() clientexported.Header { + return msg.Header +} diff --git a/x/ibc/07-tendermint/types/msgs_test.go b/x/ibc/07-tendermint/types/msgs_test.go new file mode 100644 index 000000000000..78bbf34d3460 --- /dev/null +++ b/x/ibc/07-tendermint/types/msgs_test.go @@ -0,0 +1,77 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto/secp256k1" + tmtypes "github.com/tendermint/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +func TestMsgCreateClientValidateBasic(t *testing.T) { + validator := tmtypes.NewValidator(tmtypes.NewMockPV().GetPubKey(), 1) + valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) + + now := time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) + cs := ibctmtypes.ConsensusState{ + Timestamp: now, + Root: commitment.NewRoot([]byte("root")), + ValidatorSet: valSet, + } + privKey := secp256k1.GenPrivKey() + signer := sdk.AccAddress(privKey.PubKey().Address()) + + cases := []struct { + msg ibctmtypes.MsgCreateClient + expPass bool + errMsg string + }{ + {ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, cs, trustingPeriod, ubdPeriod, signer), true, "success msg should pass"}, + {ibctmtypes.NewMsgCreateClient("BADCHAIN", cs, trustingPeriod, ubdPeriod, signer), false, "invalid client id passed"}, + {ibctmtypes.NewMsgCreateClient("goodchain", cs, trustingPeriod, ubdPeriod, signer), false, "unregistered client type passed"}, + {ibctmtypes.NewMsgCreateClient("goodchain", ibctmtypes.ConsensusState{}, trustingPeriod, ubdPeriod, signer), false, "invalid Consensus State in msg passed"}, + {ibctmtypes.NewMsgCreateClient("goodchain", cs, 0, ubdPeriod, signer), false, "zero trusting period passed"}, + {ibctmtypes.NewMsgCreateClient("goodchain", cs, trustingPeriod, 0, signer), false, "zero unbonding period passed"}, + {ibctmtypes.NewMsgCreateClient("goodchain", cs, trustingPeriod, ubdPeriod, nil), false, "Empty address passed"}, + } + + for i, tc := range cases { + err := tc.msg.ValidateBasic() + if tc.expPass { + require.NoError(t, err, "Msg %d failed: %v", i, err) + } else { + require.Error(t, err, "Invalid Msg %d passed: %s", i, tc.errMsg) + } + } +} + +func TestMsgUpdateClient(t *testing.T) { + privKey := secp256k1.GenPrivKey() + signer := sdk.AccAddress(privKey.PubKey().Address()) + + cases := []struct { + msg ibctmtypes.MsgUpdateClient + expPass bool + errMsg string + }{ + {ibctmtypes.NewMsgUpdateClient(exported.ClientTypeTendermint, ibctmtypes.Header{}, signer), true, "success msg should pass"}, + {ibctmtypes.NewMsgUpdateClient("badClient", ibctmtypes.Header{}, signer), false, "invalid client id passed"}, + {ibctmtypes.NewMsgUpdateClient(exported.ClientTypeTendermint, ibctmtypes.Header{}, nil), false, "Empty address passed"}, + } + + for i, tc := range cases { + err := tc.msg.ValidateBasic() + if tc.expPass { + require.NoError(t, err, "Msg %d failed: %v", i, err) + } else { + require.Error(t, err, "Invalid Msg %d passed: %s", i, tc.errMsg) + } + } +} diff --git a/x/ibc/07-tendermint/types/tendermint_test.go b/x/ibc/07-tendermint/types/tendermint_test.go new file mode 100644 index 000000000000..d4d71cc91ce2 --- /dev/null +++ b/x/ibc/07-tendermint/types/tendermint_test.go @@ -0,0 +1,48 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" +) + +const ( + chainID = "gaia" + height = 4 + trustingPeriod time.Duration = time.Hour * 24 * 7 * 2 + ubdPeriod time.Duration = time.Hour * 24 * 7 * 3 +) + +type TendermintTestSuite struct { + suite.Suite + + cdc *codec.Codec + privVal tmtypes.PrivValidator + valSet *tmtypes.ValidatorSet + header ibctmtypes.Header + now time.Time +} + +func (suite *TendermintTestSuite) SetupTest() { + suite.cdc = codec.New() + codec.RegisterCrypto(suite.cdc) + ibctmtypes.RegisterCodec(suite.cdc) + commitment.RegisterCodec(suite.cdc) + + suite.now = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) + suite.privVal = tmtypes.NewMockPV() + val := tmtypes.NewValidator(suite.privVal.GetPubKey(), 10) + suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{val}) + suite.header = ibctmtypes.CreateTestHeader(chainID, height, suite.now, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) +} + +func TestTendermintTestSuite(t *testing.T) { + suite.Run(t, new(TendermintTestSuite)) +} diff --git a/x/ibc/07-tendermint/test_utils.go b/x/ibc/07-tendermint/types/test_utils.go similarity index 99% rename from x/ibc/07-tendermint/test_utils.go rename to x/ibc/07-tendermint/types/test_utils.go index 9ae1d86069bb..bd538bc4871b 100644 --- a/x/ibc/07-tendermint/test_utils.go +++ b/x/ibc/07-tendermint/types/test_utils.go @@ -1,4 +1,4 @@ -package tendermint +package types import ( "math" diff --git a/x/ibc/07-tendermint/update.go b/x/ibc/07-tendermint/update.go index c3530d461e02..c1a86d8393b6 100644 --- a/x/ibc/07-tendermint/update.go +++ b/x/ibc/07-tendermint/update.go @@ -7,6 +7,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types" + "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -23,14 +24,14 @@ func CheckValidityAndUpdateState( clientState clientexported.ClientState, header clientexported.Header, chainID string, currentTimestamp time.Time, ) (clientexported.ClientState, clientexported.ConsensusState, error) { - tmClientState, ok := clientState.(ClientState) + tmClientState, ok := clientState.(types.ClientState) if !ok { return nil, nil, sdkerrors.Wrap( clienttypes.ErrInvalidClientType, "light client is not from Tendermint", ) } - tmHeader, ok := header.(Header) + tmHeader, ok := header.(types.Header) if !ok { return nil, nil, sdkerrors.Wrap( clienttypes.ErrInvalidHeader, "header is not from Tendermint", @@ -49,7 +50,7 @@ func CheckValidityAndUpdateState( // // CONTRACT: assumes header.Height > consensusState.Height func checkValidity( - clientState ClientState, header Header, chainID string, currentTimestamp time.Time, + clientState types.ClientState, header types.Header, chainID string, currentTimestamp time.Time, ) error { // assert trusting period has not yet passed if currentTimestamp.Sub(clientState.LatestTimestamp) >= clientState.TrustingPeriod { @@ -90,9 +91,9 @@ func checkValidity( } // update the consensus state from a new header -func update(clientState ClientState, header Header) (ClientState, ConsensusState) { +func update(clientState types.ClientState, header types.Header) (types.ClientState, types.ConsensusState) { clientState.LatestHeight = header.GetHeight() - consensusState := ConsensusState{ + consensusState := types.ConsensusState{ Timestamp: header.Time, Root: commitment.NewRoot(header.AppHash), ValidatorSet: header.ValidatorSet, diff --git a/x/ibc/07-tendermint/update_test.go b/x/ibc/07-tendermint/update_test.go index 7b9bb3a74a16..33f693cae85f 100644 --- a/x/ibc/07-tendermint/update_test.go +++ b/x/ibc/07-tendermint/update_test.go @@ -2,31 +2,32 @@ package tendermint_test import ( tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) func (suite *TendermintTestSuite) TestCheckValidity() { testCases := []struct { name string - clientState tendermint.ClientState + clientState ibctmtypes.ClientState chainID string expPass bool }{ { name: "successful update", - clientState: tendermint.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.clientTime), chainID: chainID, expPass: true, }, { name: "header basic validation failed", - clientState: tendermint.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.clientTime), chainID: "cosmoshub", expPass: false, }, { name: "header height < latest client height", - clientState: tendermint.NewClientState(chainID, height+1), + clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height+1, suite.clientTime), chainID: chainID, expPass: false, }, @@ -35,7 +36,8 @@ func (suite *TendermintTestSuite) TestCheckValidity() { for i, tc := range testCases { tc := tc - expectedConsensus := tendermint.ConsensusState{ + expectedConsensus := ibctmtypes.ConsensusState{ + Timestamp: suite.headerTime, Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.header.ValidatorSet, } From 80b14326bb89e4def1578bdf577586aa7d1250d7 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Mon, 10 Feb 2020 12:15:00 -0800 Subject: [PATCH 02/12] fix rest of package to accomadate 07 refactor --- x/ibc/02-client/keeper/client_test.go | 47 +++++++++++++---------- x/ibc/02-client/keeper/keeper_test.go | 22 ++++++----- x/ibc/03-connection/keeper/keeper_test.go | 14 +++---- x/ibc/04-channel/keeper/keeper_test.go | 9 +++-- x/ibc/07-tendermint/client/cli/cli.go | 2 +- x/ibc/07-tendermint/module.go | 2 +- x/ibc/20-transfer/handler_test.go | 6 +-- x/ibc/20-transfer/keeper/relay_test.go | 6 +-- x/ibc/ante/ante.go | 5 ++- x/ibc/ante/ante_test.go | 9 +++-- x/ibc/client/cli/cli.go | 3 +- x/ibc/handler.go | 7 ++-- x/ibc/module.go | 4 +- 13 files changed, 74 insertions(+), 62 deletions(-) diff --git a/x/ibc/02-client/keeper/client_test.go b/x/ibc/02-client/keeper/client_test.go index a3f29aa19979..3837368f9c66 100644 --- a/x/ibc/02-client/keeper/client_test.go +++ b/x/ibc/02-client/keeper/client_test.go @@ -7,7 +7,8 @@ import ( tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ) @@ -78,7 +79,7 @@ func (suite *KeeperTestSuite) TestUpdateClient() { return nil }, false}, {"frozen client", func() error { - clientState := tendermint.ClientState{FrozenHeight: 1, ID: testClientID, LatestHeight: 10} + clientState := ibctmtypes.ClientState{FrozenHeight: 1, ID: testClientID, LatestHeight: 10} suite.keeper.SetClientState(suite.ctx, clientState) suite.keeper.SetClientType(suite.ctx, testClientID, exported.Tendermint) return nil @@ -104,7 +105,7 @@ func (suite *KeeperTestSuite) TestUpdateClient() { err = suite.keeper.UpdateClient(suite.ctx, testClientID, suite.header) if tc.expPass { - expConsensusState := tendermint.ConsensusState{ + expConsensusState := ibctmtypes.ConsensusState{ Timestamp: suite.header.Time, Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.header.ValidatorSet, @@ -115,10 +116,14 @@ func (suite *KeeperTestSuite) TestUpdateClient() { consensusState, found := suite.keeper.GetClientConsensusState(suite.ctx, testClientID, uint64(suite.header.GetHeight())) suite.Require().True(found, "valid test case %d failed: %s", i, tc.name) + tmConsState, ok := consensusState.(ibctmtypes.ConsensusState) + suite.Require().True(ok, "consensus state is not a tendermint consensus state") + // recalculate cached totalVotingPower field for equality check + tmConsState.ValidatorSet.TotalVotingPower() suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - suite.Require().Equal(suite.header.GetHeight(), clientState.GetLatestHeight(), "client state height not updated correctly") - suite.Require().Equal(expConsensusState, consensusState, "consensus state should have been updated") + suite.Require().Equal(suite.header.GetHeight(), clientState.GetLatestHeight(), "client state height not updated correctly on case %d: %s", i, tc.name) + suite.Require().Equal(expConsensusState, consensusState, "consensus state should have been updated on case %d: %s", i, tc.name) } else { suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) } @@ -147,15 +152,15 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { testCases := []struct { name string - evidence tendermint.Evidence + evidence ibctmtypes.Evidence malleate func() error expPass bool }{ { "trusting period misbehavior should pass", - tendermint.Evidence{ - Header1: tendermint.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, suite.valSet, bothSigners), - Header2: tendermint.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, suite.valSet, bothSigners), + Header2: ibctmtypes.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), ChainID: testClientID, ClientID: testClientID, }, @@ -168,20 +173,20 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { }, { "client state not found", - tendermint.Evidence{}, + ibctmtypes.Evidence{}, func() error { return nil }, false, }, { "consensus state not found", - tendermint.Evidence{ - Header1: tendermint.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, suite.valSet, bothSigners), - Header2: tendermint.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, suite.valSet, bothSigners), + Header2: ibctmtypes.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), ChainID: testClientID, ClientID: testClientID, }, func() error { - clientState := tendermint.ClientState{FrozenHeight: 1, ID: testClientID, LatestHeight: 10} + clientState := ibctmtypes.ClientState{FrozenHeight: 1, ID: testClientID, LatestHeight: 10} suite.keeper.SetClientState(suite.ctx, clientState) return nil }, @@ -189,14 +194,14 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { }, { "consensus state not found", - tendermint.Evidence{ - Header1: tendermint.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, suite.valSet, bothSigners), - Header2: tendermint.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, suite.valSet, bothSigners), + Header2: ibctmtypes.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), ChainID: testClientID, ClientID: testClientID, }, func() error { - clientState := tendermint.ClientState{FrozenHeight: 1, ID: testClientID, LatestHeight: 10} + clientState := ibctmtypes.ClientState{FrozenHeight: 1, ID: testClientID, LatestHeight: 10} suite.keeper.SetClientState(suite.ctx, clientState) return nil }, @@ -204,9 +209,9 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { }, { "misbehaviour check failed", - tendermint.Evidence{ - Header1: tendermint.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), - Header2: tendermint.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), altValSet, bothValSet, altSigners), + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), + Header2: ibctmtypes.CreateTestHeader(testClientID, testClientHeight, suite.ctx.BlockTime(), altValSet, bothValSet, altSigners), ChainID: testClientID, ClientID: testClientID, }, diff --git a/x/ibc/02-client/keeper/keeper_test.go b/x/ibc/02-client/keeper/keeper_test.go index 5c7c54c4e71b..d067f6d873bb 100644 --- a/x/ibc/02-client/keeper/keeper_test.go +++ b/x/ibc/02-client/keeper/keeper_test.go @@ -15,7 +15,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" "github.com/cosmos/cosmos-sdk/x/ibc/02-client/keeper" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/staking" ) @@ -37,8 +37,8 @@ type KeeperTestSuite struct { cdc *codec.Codec ctx sdk.Context keeper *keeper.Keeper - consensusState tendermint.ConsensusState - header tendermint.Header + consensusState ibctmtypes.ConsensusState + header ibctmtypes.Header valSet *tmtypes.ValidatorSet privVal tmtypes.PrivValidator now time.Time @@ -56,8 +56,8 @@ func (suite *KeeperTestSuite) SetupTest() { suite.privVal = tmtypes.NewMockPV() validator := tmtypes.NewValidator(suite.privVal.GetPubKey(), 1) suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) - suite.header = tendermint.CreateTestHeader(testClientID, testClientHeight+2, now2, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) - suite.consensusState = tendermint.ConsensusState{ + suite.header = ibctmtypes.CreateTestHeader(testClientID, testClientHeight+2, now2, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) + suite.consensusState = ibctmtypes.ConsensusState{ Timestamp: suite.now, Root: commitment.NewRoot([]byte("hash")), ValidatorSet: suite.valSet, @@ -81,7 +81,7 @@ func TestKeeperTestSuite(t *testing.T) { } func (suite *KeeperTestSuite) TestSetClientState() { - clientState := tendermint.NewClientState(testClientID, trustingPeriod, ubdPeriod, testClientHeight, suite.now) + clientState := ibctmtypes.NewClientState(testClientID, trustingPeriod, ubdPeriod, testClientHeight, suite.now) suite.keeper.SetClientState(suite.ctx, clientState) retrievedState, found := suite.keeper.GetClientState(suite.ctx, testClientID) @@ -103,16 +103,18 @@ func (suite *KeeperTestSuite) TestSetClientConsensusState() { retrievedConsState, found := suite.keeper.GetClientConsensusState(suite.ctx, testClientID, testClientHeight) suite.Require().True(found, "GetConsensusState failed") - tmConsState, ok := retrievedConsState.(tendermint.ConsensusState) + tmConsState, ok := retrievedConsState.(ibctmtypes.ConsensusState) + // recalculate cached totalVotingPower field for equality check + tmConsState.ValidatorSet.TotalVotingPower() suite.Require().True(ok) suite.Require().Equal(suite.consensusState, tmConsState, "ConsensusState not stored correctly") } func (suite KeeperTestSuite) TestGetAllClients() { expClients := []exported.ClientState{ - tendermint.NewClientState(testClientID2, trustingPeriod, ubdPeriod, testClientHeight, suite.now), - tendermint.NewClientState(testClientID3, trustingPeriod, ubdPeriod, testClientHeight, suite.now), - tendermint.NewClientState(testClientID, trustingPeriod, ubdPeriod, testClientHeight, suite.now), + ibctmtypes.NewClientState(testClientID2, trustingPeriod, ubdPeriod, testClientHeight, suite.now), + ibctmtypes.NewClientState(testClientID3, trustingPeriod, ubdPeriod, testClientHeight, suite.now), + ibctmtypes.NewClientState(testClientID, trustingPeriod, ubdPeriod, testClientHeight, suite.now), } for i := range expClients { diff --git a/x/ibc/03-connection/keeper/keeper_test.go b/x/ibc/03-connection/keeper/keeper_test.go index 3163496c4af7..c40235eb1caf 100644 --- a/x/ibc/03-connection/keeper/keeper_test.go +++ b/x/ibc/03-connection/keeper/keeper_test.go @@ -20,7 +20,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types" channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" "github.com/cosmos/cosmos-sdk/x/staking" @@ -53,7 +53,7 @@ type KeeperTestSuite struct { app *simapp.SimApp valSet *tmtypes.ValidatorSet consensusState clientexported.ConsensusState - header tendermint.Header + header ibctmtypes.Header now time.Time } @@ -69,8 +69,8 @@ func (suite *KeeperTestSuite) SetupTest() { privVal := tmtypes.NewMockPV() validator := tmtypes.NewValidator(privVal.GetPubKey(), 1) suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) - suite.header = tendermint.CreateTestHeader(chainID, testHeight, now2, suite.valSet, suite.valSet, []tmtypes.PrivValidator{privVal}) - suite.consensusState = tendermint.ConsensusState{ + suite.header = ibctmtypes.CreateTestHeader(chainID, testHeight, now2, suite.valSet, suite.valSet, []tmtypes.PrivValidator{privVal}) + suite.consensusState = ibctmtypes.ConsensusState{ Timestamp: suite.now, Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, @@ -113,7 +113,7 @@ func (suite *KeeperTestSuite) createClient(clientID string) { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: suite.app.LastBlockHeight() + 1, Time: suite.now}}) suite.ctx = suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 1) - consensusState := tendermint.ConsensusState{ + consensusState := ibctmtypes.ConsensusState{ Timestamp: suite.now, Root: commitment.NewRoot(commitID.Hash), ValidatorSet: suite.valSet, @@ -143,7 +143,7 @@ func (suite *KeeperTestSuite) updateClient(clientID string) { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: suite.app.LastBlockHeight() + 1, Time: suite.now}}) suite.ctx = suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 1) - consensusState := tendermint.ConsensusState{ + consensusState := ibctmtypes.ConsensusState{ Timestamp: suite.now, Root: commitment.NewRoot(commitID.Hash), ValidatorSet: suite.valSet, @@ -153,7 +153,7 @@ func (suite *KeeperTestSuite) updateClient(clientID string) { suite.ctx, clientID, uint64(suite.app.LastBlockHeight()), consensusState, ) suite.app.IBCKeeper.ClientKeeper.SetClientState( - suite.ctx, tendermint.NewClientState(clientID, trustingPeriod, ubdPeriod, uint64(suite.app.LastBlockHeight()), suite.now), + suite.ctx, ibctmtypes.NewClientState(clientID, trustingPeriod, ubdPeriod, uint64(suite.app.LastBlockHeight()), suite.now), ) // _, _, err := simapp.SignCheckDeliver( diff --git a/x/ibc/04-channel/keeper/keeper_test.go b/x/ibc/04-channel/keeper/keeper_test.go index f618f6fc27e0..b0f466bb9989 100644 --- a/x/ibc/04-channel/keeper/keeper_test.go +++ b/x/ibc/04-channel/keeper/keeper_test.go @@ -18,7 +18,8 @@ import ( connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" ) @@ -203,7 +204,7 @@ func (suite *KeeperTestSuite) createClient(clientID string) { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: suite.app.LastBlockHeight() + 1}}) suite.ctx = suite.app.BaseApp.NewContext(false, abci.Header{Height: suite.app.LastBlockHeight()}) - consensusState := tendermint.ConsensusState{ + consensusState := ibctmtypes.ConsensusState{ Root: commitment.NewRoot(commitID.Hash), ValidatorSet: suite.valSet, } @@ -222,13 +223,13 @@ func (suite *KeeperTestSuite) updateClient() { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: height}}) suite.ctx = suite.app.BaseApp.NewContext(false, abci.Header{Height: suite.app.LastBlockHeight()}) - state := tendermint.ConsensusState{ + state := ibctmtypes.ConsensusState{ Root: commitment.NewRoot(commitID.Hash), } suite.app.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.ctx, testClientID1, uint64(height-1), state) csi, _ := suite.app.IBCKeeper.ClientKeeper.GetClientState(suite.ctx, testClientID1) - cs, _ := csi.(tendermint.ClientState) + cs, _ := csi.(ibctmtypes.ClientState) cs.LatestHeight = uint64(height - 1) suite.app.IBCKeeper.ClientKeeper.SetClientState(suite.ctx, cs) } diff --git a/x/ibc/07-tendermint/client/cli/cli.go b/x/ibc/07-tendermint/client/cli/cli.go index 0d525777850c..e25dd98536ed 100644 --- a/x/ibc/07-tendermint/client/cli/cli.go +++ b/x/ibc/07-tendermint/client/cli/cli.go @@ -8,7 +8,7 @@ import ( ) // GetTxCmd returns the transaction commands for IBC clients -func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { +func GetTxCmd(cdc *codec.Codec, storeKey string) *cobra.Command { ics07TendermintTxCmd := &cobra.Command{ Use: "tendermint", Short: "Tendermint transaction subcommands", diff --git a/x/ibc/07-tendermint/module.go b/x/ibc/07-tendermint/module.go index f85765752a51..4f5b32cea681 100644 --- a/x/ibc/07-tendermint/module.go +++ b/x/ibc/07-tendermint/module.go @@ -25,5 +25,5 @@ func RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router, queryRoute stri // GetTxCmd returns the root tx command for the IBC client func GetTxCmd(cdc *codec.Codec, storeKey string) *cobra.Command { - return cli.GetTxCmd(fmt.Sprintf("%s/%s", storeKey, types.SubModuleName), cdc) + return cli.GetTxCmd(cdc, fmt.Sprintf("%s/%s", storeKey, types.SubModuleName)) } diff --git a/x/ibc/20-transfer/handler_test.go b/x/ibc/20-transfer/handler_test.go index bfb8af5442f0..58e6a982f974 100644 --- a/x/ibc/20-transfer/handler_test.go +++ b/x/ibc/20-transfer/handler_test.go @@ -17,7 +17,7 @@ import ( connectionexported "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/exported" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" transfer "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer" "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" @@ -87,7 +87,7 @@ func (suite *HandlerTestSuite) createClient() { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: suite.app.LastBlockHeight() + 1}}) suite.ctx = suite.app.BaseApp.NewContext(false, abci.Header{}) - consensusState := tendermint.ConsensusState{ + consensusState := ibctmtypes.ConsensusState{ Root: commitment.NewRoot(commitID.Hash), ValidatorSet: suite.valSet, } @@ -104,7 +104,7 @@ func (suite *HandlerTestSuite) updateClient() { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: suite.app.LastBlockHeight() + 1}}) suite.ctx = suite.app.BaseApp.NewContext(false, abci.Header{}) - state := tendermint.ConsensusState{ + state := ibctmtypes.ConsensusState{ Root: commitment.NewRoot(commitID.Hash), } diff --git a/x/ibc/20-transfer/keeper/relay_test.go b/x/ibc/20-transfer/keeper/relay_test.go index d404f35324bc..87450fddb5aa 100644 --- a/x/ibc/20-transfer/keeper/relay_test.go +++ b/x/ibc/20-transfer/keeper/relay_test.go @@ -10,7 +10,7 @@ import ( connectionexported "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/exported" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" "github.com/cosmos/cosmos-sdk/x/ibc/20-transfer/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" @@ -24,7 +24,7 @@ func (suite *KeeperTestSuite) createClient() { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: suite.app.LastBlockHeight() + 1}}) suite.ctx = suite.app.BaseApp.NewContext(false, abci.Header{}) - consensusState := tendermint.ConsensusState{ + consensusState := ibctmtypes.ConsensusState{ Root: commitment.NewRoot(commitID.Hash), ValidatorSet: suite.valSet, } @@ -41,7 +41,7 @@ func (suite *KeeperTestSuite) updateClient() { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: suite.app.LastBlockHeight() + 1}}) suite.ctx = suite.app.BaseApp.NewContext(false, abci.Header{}) - state := tendermint.ConsensusState{ + state := ibctmtypes.ConsensusState{ Root: commitment.NewRoot(commitID.Hash), } diff --git a/x/ibc/ante/ante.go b/x/ibc/ante/ante.go index 1873c2edf612..4301e95c5a10 100644 --- a/x/ibc/ante/ante.go +++ b/x/ibc/ante/ante.go @@ -3,6 +3,7 @@ package ante import ( sdk "github.com/cosmos/cosmos-sdk/types" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" ) @@ -28,8 +29,8 @@ func (pvr ProofVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim for _, msg := range tx.GetMsgs() { var err error switch msg := msg.(type) { - case client.MsgUpdateClient: - err = pvr.clientKeeper.UpdateClient(ctx, msg.ClientID, msg.Header) + case clientexported.MsgUpdateClient: + err = pvr.clientKeeper.UpdateClient(ctx, msg.GetClientID(), msg.GetHeader()) case channel.MsgPacket: _, err = pvr.channelKeeper.RecvPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight) case channel.MsgAcknowledgement: diff --git a/x/ibc/ante/ante_test.go b/x/ibc/ante/ante_test.go index f65a50e00523..0bbd095d2db7 100644 --- a/x/ibc/ante/ante_test.go +++ b/x/ibc/ante/ante_test.go @@ -19,7 +19,8 @@ import ( channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" channelexported "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported" channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" + commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/ante" ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types" @@ -76,7 +77,7 @@ func (suite *HandlerTestSuite) createClient() { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: suite.app.LastBlockHeight() + 1, Time: now2}}) suite.ctx = suite.app.BaseApp.NewContext(false, abci.Header{}) - consensusState := tendermint.ConsensusState{ + consensusState := ibctmtypes.ConsensusState{ Timestamp: suite.now, Root: commitment.NewRoot(commitID.Hash), ValidatorSet: suite.valSet, @@ -98,13 +99,13 @@ func (suite *HandlerTestSuite) updateClient() { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: height, Time: suite.now}}) suite.ctx = suite.app.BaseApp.NewContext(false, abci.Header{}) - state := tendermint.ConsensusState{ + state := ibctmtypes.ConsensusState{ Root: commitment.NewRoot(commitID.Hash), } suite.app.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.ctx, testClient, uint64(height-1), state) csi, _ := suite.app.IBCKeeper.ClientKeeper.GetClientState(suite.ctx, testClient) - cs, _ := csi.(tendermint.ClientState) + cs, _ := csi.(ibctmtypes.ClientState) cs.LatestHeight = uint64(height - 1) suite.app.IBCKeeper.ClientKeeper.SetClientState(suite.ctx, cs) } diff --git a/x/ibc/client/cli/cli.go b/x/ibc/client/cli/cli.go index 6a98669c858e..c42fbc8aa98e 100644 --- a/x/ibc/client/cli/cli.go +++ b/x/ibc/client/cli/cli.go @@ -9,6 +9,7 @@ import ( ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/02-client" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" + tmclient "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/client/cli" "github.com/cosmos/cosmos-sdk/x/ibc/types" ) @@ -23,7 +24,7 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { } ibcTxCmd.AddCommand(flags.PostCommands( - ibcclient.GetTxCmd(cdc, storeKey), + tmclient.GetTxCmd(cdc, storeKey), connection.GetTxCmd(cdc, storeKey), channel.GetTxCmd(cdc, storeKey), )...) diff --git a/x/ibc/handler.go b/x/ibc/handler.go index eb6705888f81..1a3f5843f01f 100644 --- a/x/ibc/handler.go +++ b/x/ibc/handler.go @@ -4,6 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" + clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" ) @@ -14,11 +15,11 @@ func NewHandler(k Keeper) sdk.Handler { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { - // IBC client msgs - case client.MsgCreateClient: + // IBC client msg interface types + case clientexported.MsgCreateClient: return client.HandleMsgCreateClient(ctx, k.ClientKeeper, msg) - case client.MsgUpdateClient: + case clientexported.MsgUpdateClient: return &sdk.Result{}, nil // IBC connection msgs diff --git a/x/ibc/module.go b/x/ibc/module.go index 65f03954cd1d..17a58c8d9c9d 100644 --- a/x/ibc/module.go +++ b/x/ibc/module.go @@ -15,7 +15,7 @@ import ( client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment" "github.com/cosmos/cosmos-sdk/x/ibc/client/cli" "github.com/cosmos/cosmos-sdk/x/ibc/client/rest" @@ -43,7 +43,7 @@ func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { client.RegisterCodec(cdc) connection.RegisterCodec(cdc) channel.RegisterCodec(cdc) - tendermint.RegisterCodec(cdc) + ibctmtypes.RegisterCodec(cdc) commitment.RegisterCodec(cdc) } From 16ff5fc74e51d682459f8179a6aa53471e60efbd Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Wed, 12 Feb 2020 15:45:21 -0800 Subject: [PATCH 03/12] added GetHeight to ConsensusState and moved clientstate struct creation to 07-tendermint --- x/ibc/02-client/exported/exported.go | 3 ++ x/ibc/02-client/handler.go | 12 ++--- x/ibc/02-client/keeper/client.go | 16 +++--- x/ibc/02-client/keeper/client_test.go | 50 ++++++++++++++----- x/ibc/02-client/keeper/keeper.go | 31 +----------- x/ibc/02-client/keeper/keeper_test.go | 1 + x/ibc/03-connection/keeper/keeper_test.go | 15 ++++-- x/ibc/04-channel/keeper/handshake_test.go | 16 +++--- x/ibc/04-channel/keeper/keeper_test.go | 6 ++- x/ibc/07-tendermint/types/client_state.go | 9 +++- x/ibc/07-tendermint/types/consensus_state.go | 9 ++++ .../types/consensus_state_test.go | 13 +++++ x/ibc/07-tendermint/types/msgs_test.go | 1 + x/ibc/20-transfer/handler_test.go | 4 +- x/ibc/20-transfer/keeper/relay_test.go | 4 +- x/ibc/ante/ante_test.go | 5 +- 16 files changed, 119 insertions(+), 76 deletions(-) diff --git a/x/ibc/02-client/exported/exported.go b/x/ibc/02-client/exported/exported.go index 19828ee9955b..e5623ed8ddca 100644 --- a/x/ibc/02-client/exported/exported.go +++ b/x/ibc/02-client/exported/exported.go @@ -92,6 +92,9 @@ type ClientState interface { type ConsensusState interface { ClientType() ClientType // Consensus kind + // GetHeight returns the height of the consensus state + GetHeight() uint64 + // GetRoot returns the commitment root of the consensus state, // which is used for key-value pair verification. GetRoot() commitment.RootI diff --git a/x/ibc/02-client/handler.go b/x/ibc/02-client/handler.go index 92a015cf3231..d057c3c61566 100644 --- a/x/ibc/02-client/handler.go +++ b/x/ibc/02-client/handler.go @@ -13,10 +13,6 @@ import ( // HandleMsgCreateClient defines the sdk.Handler for MsgCreateClient func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg exported.MsgCreateClient) (*sdk.Result, error) { clientType := exported.ClientTypeFromString(msg.GetClientType()) - if clientType == 0 { - - } - switch clientType { case 0: return nil, sdkerrors.Wrap(ErrInvalidClientType, msg.GetClientType()) @@ -25,8 +21,12 @@ func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg exported.MsgCreateClie if !ok { return nil, sdkerrors.Wrap(ErrInvalidClientType, "Msg is not a Tendermint CreateClient msg") } - _, err := k.CreateClient( - ctx, msg.GetClientID(), clientType, msg.GetConsensusState(), tmMsg.TrustingPeriod, tmMsg.UnbondingPeriod, + clientState, err := ibctmtypes.InitializeFromMsg(tmMsg) + if err != nil { + return nil, err + } + _, err = k.CreateClient( + ctx, clientState, msg.GetConsensusState(), ) if err != nil { return nil, err diff --git a/x/ibc/02-client/keeper/client.go b/x/ibc/02-client/keeper/client.go index 9a1232d7b166..7758ea8d6cc5 100644 --- a/x/ibc/02-client/keeper/client.go +++ b/x/ibc/02-client/keeper/client.go @@ -2,7 +2,6 @@ package keeper import ( "fmt" - "time" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -12,13 +11,12 @@ import ( ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" ) -// CreateClient creates a new client state and populates it with a given consensus +// CreateTMClient creates a new tendermint client state and populates it with a given consensus // state as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create func (k Keeper) CreateClient( - ctx sdk.Context, clientID string, - clientType exported.ClientType, consensusState exported.ConsensusState, - trustingPeriod, unbondingPeriod time.Duration, + ctx sdk.Context, clientState exported.ClientState, consensusState exported.ConsensusState, ) (exported.ClientState, error) { + clientID := clientState.GetID() _, found := k.GetClientState(ctx, clientID) if found { return nil, sdkerrors.Wrapf(types.ErrClientExists, "cannot create client with ID %s", clientID) @@ -29,13 +27,11 @@ func (k Keeper) CreateClient( panic(fmt.Sprintf("client type is already defined for client %s", clientID)) } - clientState, err := k.initialize(ctx, clientID, clientType, consensusState, trustingPeriod, unbondingPeriod) - if err != nil { - return nil, sdkerrors.Wrapf(err, "cannot create client with ID %s", clientID) - } + height := consensusState.GetHeight() + k.SetClientConsensusState(ctx, clientID, height, consensusState) k.SetClientState(ctx, clientState) - k.SetClientType(ctx, clientID, clientType) + k.SetClientType(ctx, clientID, clientState.ClientType()) k.Logger(ctx).Info(fmt.Sprintf("client %s created at height %d", clientID, clientState.GetLatestHeight())) ctx.EventManager().EmitEvents(sdk.Events{ diff --git a/x/ibc/02-client/keeper/client_test.go b/x/ibc/02-client/keeper/client_test.go index 3837368f9c66..aaa66beeb61a 100644 --- a/x/ibc/02-client/keeper/client_test.go +++ b/x/ibc/02-client/keeper/client_test.go @@ -26,14 +26,13 @@ func (suite *KeeperTestSuite) TestCreateClient() { cases := []struct { msg string - params params + clientID string expPass bool expPanic bool }{ - {"success", params{testClientID, exported.Tendermint}, true, false}, - {"client ID exists", params{testClientID, exported.Tendermint}, false, false}, - {"client type exists", params{testClientID2, exported.Tendermint}, false, true}, - {"invalid client type", params{testClientID3, invalidClientType}, false, false}, + {"success", testClientID, true, false}, + {"client ID exists", testClientID, false, false}, + {"client type exists", testClientID2, false, true}, } for i, tc := range cases { @@ -41,17 +40,24 @@ func (suite *KeeperTestSuite) TestCreateClient() { if tc.expPanic { suite.Require().Panics(func() { - suite.keeper.CreateClient(suite.ctx, tc.params.clientID, tc.params.clientType, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(tc.clientID, suite.consensusState, trustingPeriod, ubdPeriod) + suite.Require().NoError(err, "err on client state initialization") + suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) }, "Msg %d didn't panic: %s", i, tc.msg) } else { - clientState, err := suite.keeper.CreateClient(suite.ctx, tc.params.clientID, tc.params.clientType, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(tc.clientID, suite.consensusState, trustingPeriod, ubdPeriod) + if tc.expPass { + suite.Require().NoError(err, "errored on initialization") + suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.msg) + } + if err == nil { + _, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) + } if tc.expPass { suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg) - suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.msg) } else { suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg) - suite.Require().Nil(clientState, "invalid test case %d passed: %s", i, tc.msg) } } } @@ -64,7 +70,11 @@ func (suite *KeeperTestSuite) TestUpdateClient() { expPass bool }{ {"valid update", func() error { - _, err := suite.keeper.CreateClient(suite.ctx, testClientID, exported.Tendermint, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + if err != nil { + return err + } + _, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) return err }, true}, {"client type not found", func() error { @@ -85,7 +95,11 @@ func (suite *KeeperTestSuite) TestUpdateClient() { return nil }, false}, {"invalid header", func() error { - _, err := suite.keeper.CreateClient(suite.ctx, testClientID, exported.Tendermint, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + if err != nil { + return err + } + _, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) if err != nil { return err } @@ -166,7 +180,12 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { }, func() error { suite.consensusState.ValidatorSet = bothValSet - _, err := suite.keeper.CreateClient(suite.ctx, testClientID, exported.Tendermint, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + if err != nil { + return err + } + _, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) + return err }, true, @@ -216,7 +235,12 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { ClientID: testClientID, }, func() error { - _, err := suite.keeper.CreateClient(suite.ctx, testClientID, exported.Tendermint, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + if err != nil { + return err + } + _, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) + return err }, false, diff --git a/x/ibc/02-client/keeper/keeper.go b/x/ibc/02-client/keeper/keeper.go index 9a1423f7450a..a3eee851a408 100644 --- a/x/ibc/02-client/keeper/keeper.go +++ b/x/ibc/02-client/keeper/keeper.go @@ -2,7 +2,6 @@ package keeper import ( "fmt" - "time" "github.com/tendermint/tendermint/libs/log" tmtypes "github.com/tendermint/tendermint/types" @@ -105,6 +104,7 @@ func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height uint64) (exported. } consensusState := ibctmtypes.ConsensusState{ + Height: height, Timestamp: ctx.BlockTime(), Root: commitment.NewRoot(histInfo.Header.AppHash), ValidatorSet: tmtypes.NewValidatorSet(histInfo.ValSet.ToTmValidators()), @@ -138,32 +138,3 @@ func (k Keeper) GetAllClients(ctx sdk.Context) (states []exported.ClientState) { }) return states } - -// State returns a new client state with a given id as defined in -// https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#example-implementation -func (k Keeper) initialize( - ctx sdk.Context, clientID string, clientType exported.ClientType, - consensusState exported.ConsensusState, trustingPeriod, unbondingPeriod time.Duration, -) (exported.ClientState, error) { - height := uint64(ctx.BlockHeight()) - - var ( - clientState exported.ClientState - err error - ) - switch clientType { - case exported.Tendermint: - clientState, err = ibctmtypes.Initialize( - clientID, consensusState, trustingPeriod, unbondingPeriod, height, - ) - default: - err = types.ErrInvalidClientType - } - - if err != nil { - return nil, err - } - - k.SetClientConsensusState(ctx, clientID, height, consensusState) - return clientState, nil -} diff --git a/x/ibc/02-client/keeper/keeper_test.go b/x/ibc/02-client/keeper/keeper_test.go index d067f6d873bb..5dda2c1b9732 100644 --- a/x/ibc/02-client/keeper/keeper_test.go +++ b/x/ibc/02-client/keeper/keeper_test.go @@ -58,6 +58,7 @@ func (suite *KeeperTestSuite) SetupTest() { suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) suite.header = ibctmtypes.CreateTestHeader(testClientID, testClientHeight+2, now2, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) suite.consensusState = ibctmtypes.ConsensusState{ + Height: testClientHeight, Timestamp: suite.now, Root: commitment.NewRoot([]byte("hash")), ValidatorSet: suite.valSet, diff --git a/x/ibc/03-connection/keeper/keeper_test.go b/x/ibc/03-connection/keeper/keeper_test.go index c40235eb1caf..2dd92e8c5f2f 100644 --- a/x/ibc/03-connection/keeper/keeper_test.go +++ b/x/ibc/03-connection/keeper/keeper_test.go @@ -30,7 +30,6 @@ const ( clientType = clientexported.Tendermint storeKey = ibctypes.StoreKey chainID = "gaia" - testHeight = 10 testClientID1 = "testclientidone" testConnectionID1 = "connectionidone" @@ -45,6 +44,8 @@ const ( ubdPeriod time.Duration = time.Hour * 24 * 7 * 3 ) +var testHeight uint64 + type KeeperTestSuite struct { suite.Suite @@ -58,6 +59,7 @@ type KeeperTestSuite struct { } func (suite *KeeperTestSuite) SetupTest() { + testHeight = 1 isCheckTx := false app := simapp.Setup(isCheckTx) suite.now = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) @@ -69,8 +71,9 @@ func (suite *KeeperTestSuite) SetupTest() { privVal := tmtypes.NewMockPV() validator := tmtypes.NewValidator(privVal.GetPubKey(), 1) suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) - suite.header = ibctmtypes.CreateTestHeader(chainID, testHeight, now2, suite.valSet, suite.valSet, []tmtypes.PrivValidator{privVal}) + suite.header = ibctmtypes.CreateTestHeader(chainID, int64(testHeight), now2, suite.valSet, suite.valSet, []tmtypes.PrivValidator{privVal}) suite.consensusState = ibctmtypes.ConsensusState{ + Height: testHeight, Timestamp: suite.now, Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, @@ -112,14 +115,18 @@ func (suite *KeeperTestSuite) createClient(clientID string) { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: suite.app.LastBlockHeight() + 1, Time: suite.now}}) suite.ctx = suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 1) + testHeight += 1 consensusState := ibctmtypes.ConsensusState{ + Height: testHeight, Timestamp: suite.now, Root: commitment.NewRoot(commitID.Hash), ValidatorSet: suite.valSet, } - _, err := suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientID, clientType, consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(clientID, consensusState, trustingPeriod, ubdPeriod) + suite.Require().NoError(err) + _, err = suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientState, consensusState) suite.Require().NoError(err) // _, _, err := simapp.SignCheckDeliver( @@ -142,8 +149,10 @@ func (suite *KeeperTestSuite) updateClient(clientID string) { suite.app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: suite.app.LastBlockHeight() + 1, Time: suite.now}}) suite.ctx = suite.ctx.WithBlockHeight(suite.ctx.BlockHeight() + 1) + testHeight += 1 consensusState := ibctmtypes.ConsensusState{ + Height: testHeight, Timestamp: suite.now, Root: commitment.NewRoot(commitID.Hash), ValidatorSet: suite.valSet, diff --git a/x/ibc/04-channel/keeper/handshake_test.go b/x/ibc/04-channel/keeper/handshake_test.go index aee68d6cd00c..59c42ca40d9f 100644 --- a/x/ibc/04-channel/keeper/handshake_test.go +++ b/x/ibc/04-channel/keeper/handshake_test.go @@ -101,14 +101,14 @@ func (suite *KeeperTestSuite) TestChanOpenTry() { err := suite.app.IBCKeeper.ChannelKeeper.ChanOpenTry( suite.ctx, exported.ORDERED, []string{testConnectionID2}, testPort2, testChannel2, counterparty, testChannelVersion, testChannelVersion, - validProof{}, uint64(suite.ctx.BlockHeight()), + validProof{}, uint64(testHeight), ) suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg) } else { err := suite.app.IBCKeeper.ChannelKeeper.ChanOpenTry( suite.ctx, exported.ORDERED, []string{testConnectionID2}, testPort2, testChannel2, counterparty, testChannelVersion, testChannelVersion, - invalidProof{}, uint64(suite.ctx.BlockHeight()), + invalidProof{}, uint64(testHeight), ) suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg) } @@ -184,13 +184,13 @@ func (suite *KeeperTestSuite) TestChanOpenAck() { if tc.expPass { err := suite.app.IBCKeeper.ChannelKeeper.ChanOpenAck( suite.ctx, testPort1, testChannel1, testChannelVersion, - validProof{}, uint64(suite.ctx.BlockHeight()), + validProof{}, uint64(testHeight), ) suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg) } else { err := suite.app.IBCKeeper.ChannelKeeper.ChanOpenAck( suite.ctx, testPort1, testChannel1, testChannelVersion, - invalidProof{}, uint64(suite.ctx.BlockHeight()), + invalidProof{}, uint64(testHeight), ) suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg) } @@ -266,13 +266,13 @@ func (suite *KeeperTestSuite) TestChanOpenConfirm() { if tc.expPass { err := suite.app.IBCKeeper.ChannelKeeper.ChanOpenConfirm( suite.ctx, testPort2, testChannel2, - validProof{}, uint64(suite.ctx.BlockHeight()), + validProof{}, uint64(testHeight), ) suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg) } else { err := suite.app.IBCKeeper.ChannelKeeper.ChanOpenConfirm( suite.ctx, testPort2, testChannel2, - invalidProof{}, uint64(suite.ctx.BlockHeight()), + invalidProof{}, uint64(testHeight), ) suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg) } @@ -404,13 +404,13 @@ func (suite *KeeperTestSuite) TestChanCloseConfirm() { if tc.expPass { err := suite.app.IBCKeeper.ChannelKeeper.ChanCloseConfirm( suite.ctx, testPort2, testChannel2, - validProof{}, uint64(suite.ctx.BlockHeight()), + validProof{}, uint64(testHeight), ) suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg) } else { err := suite.app.IBCKeeper.ChannelKeeper.ChanCloseConfirm( suite.ctx, testPort2, testChannel2, - invalidProof{}, uint64(suite.ctx.BlockHeight()), + invalidProof{}, uint64(testHeight), ) suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg) } diff --git a/x/ibc/04-channel/keeper/keeper_test.go b/x/ibc/04-channel/keeper/keeper_test.go index b0f466bb9989..09b5c2834b61 100644 --- a/x/ibc/04-channel/keeper/keeper_test.go +++ b/x/ibc/04-channel/keeper/keeper_test.go @@ -45,6 +45,8 @@ const ( testChannelOrder = exported.ORDERED testChannelVersion = "1.0" + testHeight = 10 + trustingPeriod time.Duration = time.Hour * 24 * 7 * 2 ubdPeriod time.Duration = time.Hour * 24 * 7 * 3 ) @@ -205,11 +207,13 @@ func (suite *KeeperTestSuite) createClient(clientID string) { suite.ctx = suite.app.BaseApp.NewContext(false, abci.Header{Height: suite.app.LastBlockHeight()}) consensusState := ibctmtypes.ConsensusState{ + Height: testHeight, Root: commitment.NewRoot(commitID.Hash), ValidatorSet: suite.valSet, } - _, err := suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientID, testClientType, consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(clientID, consensusState, trustingPeriod, ubdPeriod) + _, err = suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientState, consensusState) suite.Require().NoError(err) } diff --git a/x/ibc/07-tendermint/types/client_state.go b/x/ibc/07-tendermint/types/client_state.go index 0b6f4490e830..4fc3fd756576 100644 --- a/x/ibc/07-tendermint/types/client_state.go +++ b/x/ibc/07-tendermint/types/client_state.go @@ -36,16 +36,23 @@ type ClientState struct { FrozenHeight uint64 `json:"frozen_height" yaml:"frozen_height"` } +// InitializeFromMsg creates a tendermint client state from a CreateClientMsg +func InitializeFromMsg( + msg MsgCreateClient, +) (ClientState, error) { + return Initialize(msg.GetClientID(), msg.GetConsensusState(), msg.TrustingPeriod, msg.UnbondingPeriod) +} + // Initialize creates a client state and validates its contents, checking that // the provided consensus state is from the same client type. func Initialize( id string, consensusState clientexported.ConsensusState, trustingPeriod, ubdPeriod time.Duration, - latestHeight uint64, ) (ClientState, error) { tmConsState, ok := consensusState.(ConsensusState) if !ok { return ClientState{}, errors.New("consensus state is not from Tendermint") } + latestHeight := tmConsState.GetHeight() if trustingPeriod >= ubdPeriod { return ClientState{}, errors.New("trusting period should be < unbonding period") diff --git a/x/ibc/07-tendermint/types/consensus_state.go b/x/ibc/07-tendermint/types/consensus_state.go index de890243bb84..cba067f9a918 100644 --- a/x/ibc/07-tendermint/types/consensus_state.go +++ b/x/ibc/07-tendermint/types/consensus_state.go @@ -14,6 +14,7 @@ import ( type ConsensusState struct { Timestamp time.Time `json:"timestamp" yaml:"timestamp"` Root commitment.RootI `json:"root" yaml:"root"` + Height uint64 `json:"height" yaml:"height"` ValidatorSet *tmtypes.ValidatorSet `json:"validator_set" yaml:"validator_set"` } @@ -27,6 +28,11 @@ func (cs ConsensusState) GetRoot() commitment.RootI { return cs.Root } +// GetHeight returns the height for the specific consensus state +func (cs ConsensusState) GetHeight() uint64 { + return cs.Height +} + // GetTimestamp returns block time at which the consensus state was stored func (cs ConsensusState) GetTimestamp() time.Time { return cs.Timestamp @@ -40,6 +46,9 @@ func (cs ConsensusState) ValidateBasic() error { if cs.ValidatorSet == nil { return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "validator set cannot be nil") } + if cs.Height == 0 { + return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "height cannot be 0") + } if cs.Timestamp.IsZero() { return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "timestamp cannot be zero Unix time") } diff --git a/x/ibc/07-tendermint/types/consensus_state_test.go b/x/ibc/07-tendermint/types/consensus_state_test.go index 90499ddb483c..c50be3483e5f 100644 --- a/x/ibc/07-tendermint/types/consensus_state_test.go +++ b/x/ibc/07-tendermint/types/consensus_state_test.go @@ -17,6 +17,7 @@ func (suite *TendermintTestSuite) TestConsensusStateValidateBasic() { {"success", ibctmtypes.ConsensusState{ Timestamp: suite.now, + Height: height, Root: commitment.NewRoot([]byte("app_hash")), ValidatorSet: suite.valSet, }, @@ -24,6 +25,7 @@ func (suite *TendermintTestSuite) TestConsensusStateValidateBasic() { {"root is nil", ibctmtypes.ConsensusState{ Timestamp: suite.now, + Height: height, Root: nil, ValidatorSet: suite.valSet, }, @@ -31,6 +33,7 @@ func (suite *TendermintTestSuite) TestConsensusStateValidateBasic() { {"root is empty", ibctmtypes.ConsensusState{ Timestamp: suite.now, + Height: height, Root: commitment.Root{}, ValidatorSet: suite.valSet, }, @@ -38,13 +41,23 @@ func (suite *TendermintTestSuite) TestConsensusStateValidateBasic() { {"valset is nil", ibctmtypes.ConsensusState{ Timestamp: suite.now, + Height: height, Root: commitment.NewRoot([]byte("app_hash")), ValidatorSet: nil, }, false}, + {"height is 0", + ibctmtypes.ConsensusState{ + Timestamp: suite.now, + Height: 0, + Root: commitment.NewRoot([]byte("app_hash")), + ValidatorSet: suite.valSet, + }, + false}, {"timestamp is zero", ibctmtypes.ConsensusState{ Timestamp: time.Time{}, + Height: height, Root: commitment.NewRoot([]byte("app_hash")), ValidatorSet: suite.valSet, }, diff --git a/x/ibc/07-tendermint/types/msgs_test.go b/x/ibc/07-tendermint/types/msgs_test.go index 78bbf34d3460..f4e0bbaecdad 100644 --- a/x/ibc/07-tendermint/types/msgs_test.go +++ b/x/ibc/07-tendermint/types/msgs_test.go @@ -21,6 +21,7 @@ func TestMsgCreateClientValidateBasic(t *testing.T) { now := time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) cs := ibctmtypes.ConsensusState{ + Height: height, Timestamp: now, Root: commitment.NewRoot([]byte("root")), ValidatorSet: valSet, diff --git a/x/ibc/20-transfer/handler_test.go b/x/ibc/20-transfer/handler_test.go index 58e6a982f974..ca8deb292181 100644 --- a/x/ibc/20-transfer/handler_test.go +++ b/x/ibc/20-transfer/handler_test.go @@ -92,7 +92,9 @@ func (suite *HandlerTestSuite) createClient() { ValidatorSet: suite.valSet, } - _, err := suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, testClient, testClientType, consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClient, consensusState, trustingPeriod, ubdPeriod) + suite.NoError(err) + _, err = suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientState, consensusState) suite.NoError(err) } diff --git a/x/ibc/20-transfer/keeper/relay_test.go b/x/ibc/20-transfer/keeper/relay_test.go index 87450fddb5aa..5e22240842a8 100644 --- a/x/ibc/20-transfer/keeper/relay_test.go +++ b/x/ibc/20-transfer/keeper/relay_test.go @@ -29,7 +29,9 @@ func (suite *KeeperTestSuite) createClient() { ValidatorSet: suite.valSet, } - _, err := suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, testClient, testClientType, consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClient, consensusState, trustingPeriod, ubdPeriod) + suite.NoError(err) + _, err = suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientState, consensusState) suite.NoError(err) } diff --git a/x/ibc/ante/ante_test.go b/x/ibc/ante/ante_test.go index 0bbd095d2db7..ef96ecc02625 100644 --- a/x/ibc/ante/ante_test.go +++ b/x/ibc/ante/ante_test.go @@ -83,8 +83,9 @@ func (suite *HandlerTestSuite) createClient() { ValidatorSet: suite.valSet, } - _, err := suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, testClient, testClientType, consensusState, trustingPeriod, ubdPeriod) - suite.app.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.ctx, testClient, uint64(suite.app.LastBlockHeight()), consensusState) + clientState, err := ibctmtypes.Initialize(testClient, consensusState, trustingPeriod, ubdPeriod) + suite.NoError(err) + _, err = suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientState, consensusState) suite.NoError(err) } From 56398af19be42839c37af92dca960bd1d239c223 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Wed, 12 Feb 2020 18:10:04 -0800 Subject: [PATCH 04/12] start work on making misbehavior retrieve consensusState LTE misbehavior --- x/ibc/02-client/keeper/client.go | 6 +++-- x/ibc/02-client/keeper/keeper.go | 21 ++++++++++++++++++ x/ibc/02-client/keeper/keeper_test.go | 32 +++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/x/ibc/02-client/keeper/client.go b/x/ibc/02-client/keeper/client.go index 7758ea8d6cc5..4ebfe54c6f97 100644 --- a/x/ibc/02-client/keeper/client.go +++ b/x/ibc/02-client/keeper/client.go @@ -13,6 +13,8 @@ import ( // CreateTMClient creates a new tendermint client state and populates it with a given consensus // state as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create +// +// CONTRACT: ClientState was constructed correctly from given initial consensusState func (k Keeper) CreateClient( ctx sdk.Context, clientState exported.ClientState, consensusState exported.ConsensusState, ) (exported.ClientState, error) { @@ -114,7 +116,7 @@ func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, misbehaviour ex return sdkerrors.Wrap(types.ErrClientNotFound, misbehaviour.GetClientID()) } - consensusState, found := k.GetClientConsensusState(ctx, misbehaviour.GetClientID(), uint64(misbehaviour.GetHeight())) + consensusState, found := k.GetClientConsensusStateLTE(ctx, misbehaviour.GetClientID(), uint64(misbehaviour.GetHeight())) if !found { return sdkerrors.Wrap(types.ErrConsensusStateNotFound, misbehaviour.GetClientID()) } @@ -123,7 +125,7 @@ func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, misbehaviour ex switch e := misbehaviour.(type) { case ibctmtypes.Evidence: clientState, err = tendermint.CheckMisbehaviourAndUpdateState( - clientState, consensusState, misbehaviour, uint64(misbehaviour.GetHeight()), ctx.BlockTime(), + clientState, consensusState, misbehaviour, consensusState.GetHeight(), ctx.BlockTime(), ) default: diff --git a/x/ibc/02-client/keeper/keeper.go b/x/ibc/02-client/keeper/keeper.go index a3eee851a408..0b5a59a03be0 100644 --- a/x/ibc/02-client/keeper/keeper.go +++ b/x/ibc/02-client/keeper/keeper.go @@ -95,6 +95,27 @@ func (k Keeper) SetClientConsensusState(ctx sdk.Context, clientID string, height store.Set(ibctypes.KeyConsensusState(clientID, height), bz) } +// GetLatestClientConsensusState gets the latest ConsensusState stored for a given client +func (k Keeper) GetLatestClientConsensusState(ctx sdk.Context, clientID string) (exported.ConsensusState, bool) { + clientState, ok := k.GetClientState(ctx, clientID) + if !ok { + return nil, false + } + return k.GetClientConsensusState(ctx, clientID, clientState.GetLatestHeight()) +} + +// GetClientConsensusStatelTE will get the latest ConsensusState of a particular client at the latest height +// less than or equal to the given height +func (k Keeper) GetClientConsensusStateLTE(ctx sdk.Context, clientID string, maxHeight uint64) (exported.ConsensusState, bool) { + for i := maxHeight; i > 0; i-- { + consState, ok := k.GetClientConsensusState(ctx, clientID, i) + if ok { + return consState, ok + } + } + return nil, false +} + // GetSelfConsensusState introspects the (self) past historical info at a given height // and returns the expected consensus state at that height. func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height uint64) (exported.ConsensusState, bool) { diff --git a/x/ibc/02-client/keeper/keeper_test.go b/x/ibc/02-client/keeper/keeper_test.go index 5dda2c1b9732..da5f3efeada6 100644 --- a/x/ibc/02-client/keeper/keeper_test.go +++ b/x/ibc/02-client/keeper/keeper_test.go @@ -152,3 +152,35 @@ func (suite KeeperTestSuite) TestGetConsensusState() { } } } + +func (suite KeeperTestSuite) TestConsensusStateHelpers() { + // initial setup + clientState, _ := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + suite.keeper.SetClientState(suite.ctx, clientState) + suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, suite.consensusState) + + nextState := ibctmtypes.ConsensusState{ + Height: testClientHeight + 5, + Timestamp: suite.now, + Root: commitment.NewRoot([]byte("next")), + ValidatorSet: suite.valSet, + } + + // mock update functionality + suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight+5, nextState) + clientState.LatestHeight += 5 + suite.keeper.SetClientState(suite.ctx, clientState) + + latest, ok := suite.keeper.GetLatestClientConsensusState(suite.ctx, testClientID) + // recalculate cached totalVotingPower for equality check + latest.(ibctmtypes.ConsensusState).ValidatorSet.TotalVotingPower() + suite.Require().True(ok) + suite.Require().Equal(nextState, latest, "Latest client not returned correctly") + + // Should return existing consensusState at latestClientHeight + lte, ok := suite.keeper.GetClientConsensusStateLTE(suite.ctx, testClientID, testClientHeight+3) + // recalculate cached totalVotingPower for equality check + lte.(ibctmtypes.ConsensusState).ValidatorSet.TotalVotingPower() + suite.Require().True(ok) + suite.Require().Equal(suite.consensusState, lte, "LTE helper function did not return latest client state below height: %d", testClientHeight+3) +} From 87da72a1c536c7616e717f292ba4e46474cac9f7 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Thu, 13 Feb 2020 10:13:56 -0800 Subject: [PATCH 05/12] allow misbehavior submission at height not equal to persisted consensusState --- x/ibc/02-client/keeper/client_test.go | 20 ++++++++++++++++++++ x/ibc/07-tendermint/misbehaviour.go | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/x/ibc/02-client/keeper/client_test.go b/x/ibc/02-client/keeper/client_test.go index aaa66beeb61a..2daf5074bef5 100644 --- a/x/ibc/02-client/keeper/client_test.go +++ b/x/ibc/02-client/keeper/client_test.go @@ -190,6 +190,26 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { }, true, }, + { + "misbehavior at later height should pass", + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(testClientID, testClientHeight+5, suite.ctx.BlockTime(), bothValSet, suite.valSet, bothSigners), + Header2: ibctmtypes.CreateTestHeader(testClientID, testClientHeight+5, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), + ChainID: testClientID, + ClientID: testClientID, + }, + func() error { + suite.consensusState.ValidatorSet = bothValSet + clientState, err := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + if err != nil { + return err + } + _, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) + + return err + }, + true, + }, { "client state not found", ibctmtypes.Evidence{}, diff --git a/x/ibc/07-tendermint/misbehaviour.go b/x/ibc/07-tendermint/misbehaviour.go index 9f53342b43cb..7d626fc27aa5 100644 --- a/x/ibc/07-tendermint/misbehaviour.go +++ b/x/ibc/07-tendermint/misbehaviour.go @@ -67,10 +67,10 @@ func checkMisbehaviour( height uint64, currentTimestamp time.Time, ) error { // check if provided height matches the headers' height - if height != uint64(evidence.GetHeight()) { + if height > uint64(evidence.GetHeight()) { return sdkerrors.Wrapf( ibctypes.ErrInvalidHeight, - "height ≠ evidence header height (%d ≠ %d)", height, evidence.GetHeight(), + "height > evidence header height (%d ≠ %d)", height, evidence.GetHeight(), ) } From a67eabf7b929295cf9b4d44c58913d91edfbd205 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Thu, 13 Feb 2020 10:37:15 -0800 Subject: [PATCH 06/12] optimize submitMisbehavior by erroring earlier --- x/ibc/07-tendermint/misbehaviour.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/x/ibc/07-tendermint/misbehaviour.go b/x/ibc/07-tendermint/misbehaviour.go index 7d626fc27aa5..3097e9162533 100644 --- a/x/ibc/07-tendermint/misbehaviour.go +++ b/x/ibc/07-tendermint/misbehaviour.go @@ -32,6 +32,12 @@ func CheckMisbehaviourAndUpdateState( return nil, sdkerrors.Wrap(clienttypes.ErrInvalidClientType, "client state type is not Tendermint") } + // If client is already frozen at earlier height than evidence, return with error + if tmClientState.IsFrozen() && tmClientState.FrozenHeight <= uint64(misbehaviour.GetHeight()) { + return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidEvidence, + "client is already frozen at earlier height %d than misbehaviour height %d", tmClientState.FrozenHeight, misbehaviour.GetHeight()) + } + tmConsensusState, ok := consensusState.(types.ConsensusState) if !ok { return nil, sdkerrors.Wrap(clienttypes.ErrInvalidClientType, "consensus state is not Tendermint") From bbaa538ab3e5e80f6036ce049d8fbc5521e1a379 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Mon, 17 Feb 2020 00:45:25 -0800 Subject: [PATCH 07/12] cleanup misbehavior and propose lazy fix --- x/ibc/02-client/keeper/client.go | 4 +++- x/ibc/07-tendermint/misbehaviour.go | 12 +----------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/x/ibc/02-client/keeper/client.go b/x/ibc/02-client/keeper/client.go index 4ebfe54c6f97..8242a8430f2d 100644 --- a/x/ibc/02-client/keeper/client.go +++ b/x/ibc/02-client/keeper/client.go @@ -30,7 +30,9 @@ func (k Keeper) CreateClient( } height := consensusState.GetHeight() - k.SetClientConsensusState(ctx, clientID, height, consensusState) + if consensusState == nil { + k.SetClientConsensusState(ctx, clientID, height, consensusState) + } k.SetClientState(ctx, clientState) k.SetClientType(ctx, clientID, clientState.ClientType()) diff --git a/x/ibc/07-tendermint/misbehaviour.go b/x/ibc/07-tendermint/misbehaviour.go index 3097e9162533..8e30821fcc15 100644 --- a/x/ibc/07-tendermint/misbehaviour.go +++ b/x/ibc/07-tendermint/misbehaviour.go @@ -3,7 +3,6 @@ package tendermint import ( "errors" "fmt" - "math" "time" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -54,16 +53,7 @@ func CheckMisbehaviourAndUpdateState( return nil, sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, err.Error()) } - var newFrozenHeight uint64 - if tmClientState.IsFrozen() { - // freeze at an earlier height if another misbehaviour is discovered - newFrozenHeight = uint64(math.Min(float64(tmClientState.FrozenHeight), float64(tmEvidence.GetHeight()))) - } else { - newFrozenHeight = uint64(tmEvidence.GetHeight()) - } - - tmClientState.FrozenHeight = newFrozenHeight - + tmClientState.FrozenHeight = uint64(tmEvidence.GetHeight()) return tmClientState, nil } From d3ac2b8d757a663cb864180abee9b3625585004d Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Mon, 17 Feb 2020 01:03:50 -0800 Subject: [PATCH 08/12] fix bug --- x/ibc/02-client/keeper/client.go | 2 +- x/ibc/07-tendermint/misbehaviour_test.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x/ibc/02-client/keeper/client.go b/x/ibc/02-client/keeper/client.go index 8242a8430f2d..5a442373c137 100644 --- a/x/ibc/02-client/keeper/client.go +++ b/x/ibc/02-client/keeper/client.go @@ -30,7 +30,7 @@ func (k Keeper) CreateClient( } height := consensusState.GetHeight() - if consensusState == nil { + if consensusState != nil { k.SetClientConsensusState(ctx, clientID, height, consensusState) } diff --git a/x/ibc/07-tendermint/misbehaviour_test.go b/x/ibc/07-tendermint/misbehaviour_test.go index d6dab36888fa..f3acefea7b4c 100644 --- a/x/ibc/07-tendermint/misbehaviour_test.go +++ b/x/ibc/07-tendermint/misbehaviour_test.go @@ -52,17 +52,17 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { true, }, { - "height doesn't match provided evidence", - ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), - ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, + "valid misbehavior at height greater than last consensusState", + ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + ibctmtypes.ConsensusState{Timestamp: suite.now, Height: height - 1, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, ibctmtypes.Evidence{ Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, suite.valSet, bothSigners), Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), ChainID: chainID, ClientID: chainID, }, - 0, - false, + height - 1, + true, }, // { // "consensus state's valset hash different from evidence", From f9fbfebe311a5c7e9e1174fc7a3f3d156e3eecc3 Mon Sep 17 00:00:00 2001 From: Aditya Date: Mon, 17 Feb 2020 15:35:37 +0100 Subject: [PATCH 09/12] Update x/ibc/02-client/keeper/client.go Co-Authored-By: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- x/ibc/02-client/keeper/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/02-client/keeper/client.go b/x/ibc/02-client/keeper/client.go index 5a442373c137..4e82366582ba 100644 --- a/x/ibc/02-client/keeper/client.go +++ b/x/ibc/02-client/keeper/client.go @@ -11,7 +11,7 @@ import ( ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types" ) -// CreateTMClient creates a new tendermint client state and populates it with a given consensus +// CreateClient creates a new client state and populates it with a given consensus // state as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create // // CONTRACT: ClientState was constructed correctly from given initial consensusState From ab0bb5aff70aaf089b0bbfc56b5b8c420e911981 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Mon, 17 Feb 2020 08:31:19 -0800 Subject: [PATCH 10/12] address fede review --- x/ibc/02-client/handler.go | 2 +- x/ibc/02-client/keeper/client_test.go | 1 + x/ibc/02-client/keeper/keeper.go | 13 +++++++++--- x/ibc/04-channel/keeper/keeper_test.go | 1 + x/ibc/07-tendermint/misbehaviour.go | 2 +- x/ibc/07-tendermint/misbehaviour_test.go | 26 ++++++++++++------------ 6 files changed, 27 insertions(+), 18 deletions(-) diff --git a/x/ibc/02-client/handler.go b/x/ibc/02-client/handler.go index d057c3c61566..1f7993366a2f 100644 --- a/x/ibc/02-client/handler.go +++ b/x/ibc/02-client/handler.go @@ -16,7 +16,7 @@ func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg exported.MsgCreateClie switch clientType { case 0: return nil, sdkerrors.Wrap(ErrInvalidClientType, msg.GetClientType()) - case 1: + case exported.Tendermint: tmMsg, ok := msg.(ibctmtypes.MsgCreateClient) if !ok { return nil, sdkerrors.Wrap(ErrInvalidClientType, "Msg is not a Tendermint CreateClient msg") diff --git a/x/ibc/02-client/keeper/client_test.go b/x/ibc/02-client/keeper/client_test.go index 2daf5074bef5..08e0a85b79c4 100644 --- a/x/ibc/02-client/keeper/client_test.go +++ b/x/ibc/02-client/keeper/client_test.go @@ -50,6 +50,7 @@ func (suite *KeeperTestSuite) TestCreateClient() { suite.Require().NoError(err, "errored on initialization") suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.msg) } + // If we were able to initialize clientstate successfully, try persisting it to state if err == nil { _, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) } diff --git a/x/ibc/02-client/keeper/keeper.go b/x/ibc/02-client/keeper/keeper.go index 0b5a59a03be0..0d97f0c79880 100644 --- a/x/ibc/02-client/keeper/keeper.go +++ b/x/ibc/02-client/keeper/keeper.go @@ -95,6 +95,13 @@ func (k Keeper) SetClientConsensusState(ctx sdk.Context, clientID string, height store.Set(ibctypes.KeyConsensusState(clientID, height), bz) } +// HasClientConsensusState returns if keeper has a ConsensusState for a particular +// client at the given height +func (k Keeper) HasClientConsensusState(ctx sdk.Context, clientID string, height uint64) bool { + store := ctx.KVStore(k.storeKey) + return store.Has(ibctypes.KeyConsensusState(clientID, height)) +} + // GetLatestClientConsensusState gets the latest ConsensusState stored for a given client func (k Keeper) GetLatestClientConsensusState(ctx sdk.Context, clientID string) (exported.ConsensusState, bool) { clientState, ok := k.GetClientState(ctx, clientID) @@ -108,9 +115,9 @@ func (k Keeper) GetLatestClientConsensusState(ctx sdk.Context, clientID string) // less than or equal to the given height func (k Keeper) GetClientConsensusStateLTE(ctx sdk.Context, clientID string, maxHeight uint64) (exported.ConsensusState, bool) { for i := maxHeight; i > 0; i-- { - consState, ok := k.GetClientConsensusState(ctx, clientID, i) - if ok { - return consState, ok + found := k.HasClientConsensusState(ctx, clientID, i) + if found { + return k.GetClientConsensusState(ctx, clientID, i) } } return nil, false diff --git a/x/ibc/04-channel/keeper/keeper_test.go b/x/ibc/04-channel/keeper/keeper_test.go index 09b5c2834b61..59b8d5732dec 100644 --- a/x/ibc/04-channel/keeper/keeper_test.go +++ b/x/ibc/04-channel/keeper/keeper_test.go @@ -213,6 +213,7 @@ func (suite *KeeperTestSuite) createClient(clientID string) { } clientState, err := ibctmtypes.Initialize(clientID, consensusState, trustingPeriod, ubdPeriod) + suite.Require().NoError(err) _, err = suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientState, consensusState) suite.Require().NoError(err) } diff --git a/x/ibc/07-tendermint/misbehaviour.go b/x/ibc/07-tendermint/misbehaviour.go index 8e30821fcc15..990412f78c9d 100644 --- a/x/ibc/07-tendermint/misbehaviour.go +++ b/x/ibc/07-tendermint/misbehaviour.go @@ -66,7 +66,7 @@ func checkMisbehaviour( if height > uint64(evidence.GetHeight()) { return sdkerrors.Wrapf( ibctypes.ErrInvalidHeight, - "height > evidence header height (%d ≠ %d)", height, evidence.GetHeight(), + "height > evidence header height (%d > %d)", height, evidence.GetHeight(), ) } diff --git a/x/ibc/07-tendermint/misbehaviour_test.go b/x/ibc/07-tendermint/misbehaviour_test.go index f3acefea7b4c..4ba1634f805f 100644 --- a/x/ibc/07-tendermint/misbehaviour_test.go +++ b/x/ibc/07-tendermint/misbehaviour_test.go @@ -64,19 +64,19 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { height - 1, true, }, - // { - // "consensus state's valset hash different from evidence", - // ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), - // ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: suite.valSet}, - // ibctmtypes.Evidence{ - // Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, suite.valSet, bothSigners), - // Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), - // ChainID: chainID, - // ClientID: chainID, - // }, - // height, - // false, - // }, + { + "consensus state's valset hash different from evidence should still pass", + ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + ibctmtypes.ConsensusState{Timestamp: suite.now, Height: height - 1, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: suite.valSet}, + ibctmtypes.Evidence{ + Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, suite.valSet, bothSigners), + Header2: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), + ChainID: chainID, + ClientID: chainID, + }, + height - 1, + true, + }, { "first valset has too much change", ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), From b23bc14a9a72e64fe82c6e65bd0eba36290c6723 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Tue, 18 Feb 2020 03:13:03 -0800 Subject: [PATCH 11/12] add chain-id into clientstate --- x/ibc/02-client/keeper/client.go | 2 +- x/ibc/02-client/keeper/client_test.go | 14 ++--- x/ibc/02-client/keeper/keeper_test.go | 10 ++-- x/ibc/03-connection/keeper/keeper_test.go | 4 +- x/ibc/04-channel/keeper/keeper_test.go | 2 +- x/ibc/07-tendermint/client/cli/tx.go | 13 ++--- x/ibc/07-tendermint/client/rest/rest.go | 1 + x/ibc/07-tendermint/client/rest/tx.go | 1 + x/ibc/07-tendermint/misbehaviour_test.go | 12 ++--- x/ibc/07-tendermint/types/client_state.go | 14 +++-- .../07-tendermint/types/client_state_test.go | 52 +++++++++---------- x/ibc/07-tendermint/types/errors.go | 1 + x/ibc/07-tendermint/types/msgs.go | 7 ++- x/ibc/07-tendermint/types/msgs_test.go | 16 +++--- x/ibc/07-tendermint/update.go | 8 +-- x/ibc/07-tendermint/update_test.go | 12 ++--- x/ibc/20-transfer/handler_test.go | 2 +- x/ibc/20-transfer/keeper/relay_test.go | 2 +- x/ibc/ante/ante_test.go | 2 +- 19 files changed, 94 insertions(+), 81 deletions(-) diff --git a/x/ibc/02-client/keeper/client.go b/x/ibc/02-client/keeper/client.go index 4e82366582ba..98f2220727ef 100644 --- a/x/ibc/02-client/keeper/client.go +++ b/x/ibc/02-client/keeper/client.go @@ -82,7 +82,7 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H switch clientType { case exported.Tendermint: clientState, consensusState, err = tendermint.CheckValidityAndUpdateState( - clientState, header, ctx.ChainID(), ctx.BlockTime(), + clientState, header, ctx.BlockTime(), ) default: err = types.ErrInvalidClientType diff --git a/x/ibc/02-client/keeper/client_test.go b/x/ibc/02-client/keeper/client_test.go index 71ced441d935..dcd7ef911474 100644 --- a/x/ibc/02-client/keeper/client_test.go +++ b/x/ibc/02-client/keeper/client_test.go @@ -40,12 +40,12 @@ func (suite *KeeperTestSuite) TestCreateClient() { if tc.expPanic { suite.Require().Panics(func() { - clientState, err := ibctmtypes.Initialize(tc.clientID, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(tc.clientID, tc.clientID, suite.consensusState, trustingPeriod, ubdPeriod) suite.Require().NoError(err, "err on client state initialization") suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) }, "Msg %d didn't panic: %s", i, tc.msg) } else { - clientState, err := ibctmtypes.Initialize(tc.clientID, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(tc.clientID, tc.clientID, suite.consensusState, trustingPeriod, ubdPeriod) if tc.expPass { suite.Require().NoError(err, "errored on initialization") suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.msg) @@ -71,7 +71,7 @@ func (suite *KeeperTestSuite) TestUpdateClient() { expPass bool }{ {"valid update", func() error { - clientState, err := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClientID, testClientID, suite.consensusState, trustingPeriod, ubdPeriod) if err != nil { return err } @@ -96,7 +96,7 @@ func (suite *KeeperTestSuite) TestUpdateClient() { return nil }, false}, {"invalid header", func() error { - clientState, err := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClientID, testClientID, suite.consensusState, trustingPeriod, ubdPeriod) if err != nil { return err } @@ -181,7 +181,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { }, func() error { suite.consensusState.ValidatorSet = bothValSet - clientState, err := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClientID, testClientID, suite.consensusState, trustingPeriod, ubdPeriod) if err != nil { return err } @@ -201,7 +201,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { }, func() error { suite.consensusState.ValidatorSet = bothValSet - clientState, err := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClientID, testClientID, suite.consensusState, trustingPeriod, ubdPeriod) if err != nil { return err } @@ -256,7 +256,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { ClientID: testClientID, }, func() error { - clientState, err := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClientID, testClientID, suite.consensusState, trustingPeriod, ubdPeriod) if err != nil { return err } diff --git a/x/ibc/02-client/keeper/keeper_test.go b/x/ibc/02-client/keeper/keeper_test.go index da5f3efeada6..1cdf296ed6b1 100644 --- a/x/ibc/02-client/keeper/keeper_test.go +++ b/x/ibc/02-client/keeper/keeper_test.go @@ -82,7 +82,7 @@ func TestKeeperTestSuite(t *testing.T) { } func (suite *KeeperTestSuite) TestSetClientState() { - clientState := ibctmtypes.NewClientState(testClientID, trustingPeriod, ubdPeriod, testClientHeight, suite.now) + clientState := ibctmtypes.NewClientState(testClientID, testClientID, trustingPeriod, ubdPeriod, testClientHeight, suite.now) suite.keeper.SetClientState(suite.ctx, clientState) retrievedState, found := suite.keeper.GetClientState(suite.ctx, testClientID) @@ -113,9 +113,9 @@ func (suite *KeeperTestSuite) TestSetClientConsensusState() { func (suite KeeperTestSuite) TestGetAllClients() { expClients := []exported.ClientState{ - ibctmtypes.NewClientState(testClientID2, trustingPeriod, ubdPeriod, testClientHeight, suite.now), - ibctmtypes.NewClientState(testClientID3, trustingPeriod, ubdPeriod, testClientHeight, suite.now), - ibctmtypes.NewClientState(testClientID, trustingPeriod, ubdPeriod, testClientHeight, suite.now), + ibctmtypes.NewClientState(testClientID2, testClientID, trustingPeriod, ubdPeriod, testClientHeight, suite.now), + ibctmtypes.NewClientState(testClientID3, testClientID, trustingPeriod, ubdPeriod, testClientHeight, suite.now), + ibctmtypes.NewClientState(testClientID, testClientID, trustingPeriod, ubdPeriod, testClientHeight, suite.now), } for i := range expClients { @@ -155,7 +155,7 @@ func (suite KeeperTestSuite) TestGetConsensusState() { func (suite KeeperTestSuite) TestConsensusStateHelpers() { // initial setup - clientState, _ := ibctmtypes.Initialize(testClientID, suite.consensusState, trustingPeriod, ubdPeriod) + clientState, _ := ibctmtypes.Initialize(testClientID, testClientID, suite.consensusState, trustingPeriod, ubdPeriod) suite.keeper.SetClientState(suite.ctx, clientState) suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, suite.consensusState) diff --git a/x/ibc/03-connection/keeper/keeper_test.go b/x/ibc/03-connection/keeper/keeper_test.go index c47e6a22d5b9..3ddfaf5a52ff 100644 --- a/x/ibc/03-connection/keeper/keeper_test.go +++ b/x/ibc/03-connection/keeper/keeper_test.go @@ -124,7 +124,7 @@ func (suite *KeeperTestSuite) createClient(clientID string) { ValidatorSet: suite.valSet, } - clientState, err := ibctmtypes.Initialize(clientID, consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(clientID, clientID, consensusState, trustingPeriod, ubdPeriod) suite.Require().NoError(err) _, err = suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientState, consensusState) suite.Require().NoError(err) @@ -162,7 +162,7 @@ func (suite *KeeperTestSuite) updateClient(clientID string) { suite.ctx, clientID, uint64(suite.app.LastBlockHeight()), consensusState, ) suite.app.IBCKeeper.ClientKeeper.SetClientState( - suite.ctx, ibctmtypes.NewClientState(clientID, trustingPeriod, ubdPeriod, uint64(suite.app.LastBlockHeight()), suite.now), + suite.ctx, ibctmtypes.NewClientState(clientID, clientID, trustingPeriod, ubdPeriod, uint64(suite.app.LastBlockHeight()), suite.now), ) // _, _, err := simapp.SignCheckDeliver( diff --git a/x/ibc/04-channel/keeper/keeper_test.go b/x/ibc/04-channel/keeper/keeper_test.go index 59b8d5732dec..58bc96c5f05c 100644 --- a/x/ibc/04-channel/keeper/keeper_test.go +++ b/x/ibc/04-channel/keeper/keeper_test.go @@ -212,7 +212,7 @@ func (suite *KeeperTestSuite) createClient(clientID string) { ValidatorSet: suite.valSet, } - clientState, err := ibctmtypes.Initialize(clientID, consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(clientID, clientID, consensusState, trustingPeriod, ubdPeriod) suite.Require().NoError(err) _, err = suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientState, consensusState) suite.Require().NoError(err) diff --git a/x/ibc/07-tendermint/client/cli/tx.go b/x/ibc/07-tendermint/client/cli/tx.go index 2b6636df0f3c..58931f5bf97f 100644 --- a/x/ibc/07-tendermint/client/cli/tx.go +++ b/x/ibc/07-tendermint/client/cli/tx.go @@ -27,7 +27,7 @@ import ( // in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create func GetCmdCreateClient(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "create [client-id] [path/to/consensus_state.json] [trusting_period] [unbonding_period]", + Use: "create [client-id] [chain-id] [path/to/consensus_state.json] [trusting_period] [unbonding_period]", Short: "create new client with a consensus state", Long: strings.TrimSpace(fmt.Sprintf(`create new client with a specified identifier and consensus state: @@ -42,11 +42,12 @@ $ %s tx ibc client create [client-id] [path/to/consensus_state.json] [trusting_p cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc).WithBroadcastMode(flags.BroadcastBlock) clientID := args[0] + chainID := args[1] var state ibctmtypes.ConsensusState - if err := cdc.UnmarshalJSON([]byte(args[1]), &state); err != nil { + if err := cdc.UnmarshalJSON([]byte(args[2]), &state); err != nil { // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[1]) + contents, err := ioutil.ReadFile(args[2]) if err != nil { return errors.New("neither JSON input nor path to .json file were provided") } @@ -55,18 +56,18 @@ $ %s tx ibc client create [client-id] [path/to/consensus_state.json] [trusting_p } } - trustingPeriod, err := time.ParseDuration(args[2]) + trustingPeriod, err := time.ParseDuration(args[3]) if err != nil { return err } - ubdPeriod, err := time.ParseDuration(args[3]) + ubdPeriod, err := time.ParseDuration(args[4]) if err != nil { return err } msg := ibctmtypes.NewMsgCreateClient( - clientID, state, + clientID, chainID, state, trustingPeriod, ubdPeriod, cliCtx.GetFromAddress(), ) diff --git a/x/ibc/07-tendermint/client/rest/rest.go b/x/ibc/07-tendermint/client/rest/rest.go index af6d5021ada3..c483329e14b2 100644 --- a/x/ibc/07-tendermint/client/rest/rest.go +++ b/x/ibc/07-tendermint/client/rest/rest.go @@ -26,6 +26,7 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, queryRoute string) type CreateClientReq struct { BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` ClientID string `json:"client_id" yaml:"client_id"` + ChainID string `json:"chain_id" yaml:"chain_id"` ConsensusState ibctmtypes.ConsensusState `json:"consensus_state" yaml:"consensus_state"` TrustingPeriod time.Duration `json:"trusting_period" yaml:"trusting_period"` UnbondingPeriod time.Duration `json:"unbonding_period" yaml:"unbonding_period"` diff --git a/x/ibc/07-tendermint/client/rest/tx.go b/x/ibc/07-tendermint/client/rest/tx.go index 964ce27588d2..378bedcf9636 100644 --- a/x/ibc/07-tendermint/client/rest/tx.go +++ b/x/ibc/07-tendermint/client/rest/tx.go @@ -52,6 +52,7 @@ func createClientHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { // create the message msg := ibctmtypes.NewMsgCreateClient( req.ClientID, + req.ChainID, req.ConsensusState, req.TrustingPeriod, req.UnbondingPeriod, fromAddr, diff --git a/x/ibc/07-tendermint/misbehaviour_test.go b/x/ibc/07-tendermint/misbehaviour_test.go index 4ba1634f805f..ca72b5cc78d1 100644 --- a/x/ibc/07-tendermint/misbehaviour_test.go +++ b/x/ibc/07-tendermint/misbehaviour_test.go @@ -40,7 +40,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { }{ { "valid misbehavior evidence", - ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, ibctmtypes.Evidence{ Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, suite.valSet, bothSigners), @@ -53,7 +53,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { }, { "valid misbehavior at height greater than last consensusState", - ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height-1, suite.now), ibctmtypes.ConsensusState{Timestamp: suite.now, Height: height - 1, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, ibctmtypes.Evidence{ Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, suite.valSet, bothSigners), @@ -66,7 +66,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { }, { "consensus state's valset hash different from evidence should still pass", - ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), ibctmtypes.ConsensusState{Timestamp: suite.now, Height: height - 1, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: suite.valSet}, ibctmtypes.Evidence{ Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, suite.valSet, bothSigners), @@ -79,7 +79,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { }, { "first valset has too much change", - ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, ibctmtypes.Evidence{ Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, bothValSet, altSigners), @@ -92,7 +92,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { }, { "second valset has too much change", - ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, ibctmtypes.Evidence{ Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothValSet, bothSigners), @@ -105,7 +105,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() { }, { "both valsets have too much change", - ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitment.NewRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet}, ibctmtypes.Evidence{ Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, altValSet, altSigners), diff --git a/x/ibc/07-tendermint/types/client_state.go b/x/ibc/07-tendermint/types/client_state.go index 4fc3fd756576..d0ea9c87c3a6 100644 --- a/x/ibc/07-tendermint/types/client_state.go +++ b/x/ibc/07-tendermint/types/client_state.go @@ -23,6 +23,8 @@ var _ clientexported.ClientState = ClientState{} type ClientState struct { // Client ID ID string `json:"id" yaml:"id"` + // Chain ID for Tendermint chain, not guaranteed to be unique + ChainID string `json:"chain_id" yaml:"chain_id"` // Duration of the period since the LastestTimestamp during which the // submitted headers are valid for upgrade TrustingPeriod time.Duration `json:"trusting_period" yaml:"trusting_period"` @@ -40,13 +42,13 @@ type ClientState struct { func InitializeFromMsg( msg MsgCreateClient, ) (ClientState, error) { - return Initialize(msg.GetClientID(), msg.GetConsensusState(), msg.TrustingPeriod, msg.UnbondingPeriod) + return Initialize(msg.GetClientID(), msg.ChainID, msg.GetConsensusState(), msg.TrustingPeriod, msg.UnbondingPeriod) } // Initialize creates a client state and validates its contents, checking that // the provided consensus state is from the same client type. func Initialize( - id string, consensusState clientexported.ConsensusState, trustingPeriod, ubdPeriod time.Duration, + id string, chainID string, consensusState clientexported.ConsensusState, trustingPeriod, ubdPeriod time.Duration, ) (ClientState, error) { tmConsState, ok := consensusState.(ConsensusState) if !ok { @@ -57,20 +59,24 @@ func Initialize( if trustingPeriod >= ubdPeriod { return ClientState{}, errors.New("trusting period should be < unbonding period") } + if chainID == "" { + return ClientState{}, errors.New("client state cannot have empty chain id") + } clientState := NewClientState( - id, trustingPeriod, ubdPeriod, latestHeight, tmConsState.Timestamp, + id, chainID, trustingPeriod, ubdPeriod, latestHeight, tmConsState.Timestamp, ) return clientState, nil } // NewClientState creates a new ClientState instance func NewClientState( - id string, trustingPeriod, ubdPeriod time.Duration, + id string, chainID string, trustingPeriod, ubdPeriod time.Duration, latestHeight uint64, latestTimestamp time.Time, ) ClientState { return ClientState{ ID: id, + ChainID: chainID, TrustingPeriod: trustingPeriod, UnbondingPeriod: ubdPeriod, LatestHeight: latestHeight, diff --git a/x/ibc/07-tendermint/types/client_state_test.go b/x/ibc/07-tendermint/types/client_state_test.go index 208db3480313..cbb4c9c9e301 100644 --- a/x/ibc/07-tendermint/types/client_state_test.go +++ b/x/ibc/07-tendermint/types/client_state_test.go @@ -27,7 +27,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() { }{ // { // name: "successful verification", - // clientState: ibctmtypes.NewClientState(chainID, height), + // clientState: ibctmtypes.NewClientState(chainID, chainID, height), // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), // }, @@ -36,7 +36,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() { // }, { name: "ApplyPrefix failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, @@ -45,7 +45,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() { }, { name: "latest client height < height", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height-1, suite.now), consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, @@ -63,7 +63,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() { }, { name: "proof verification failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, @@ -104,7 +104,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() { }{ // { // name: "successful verification", - // clientState: ibctmtypes.NewClientState(chainID, height), + // clientState: ibctmtypes.NewClientState(chainID, chainID, height), // connection: conn, // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), @@ -114,7 +114,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() { // }, { name: "ApplyPrefix failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), connection: conn, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -124,7 +124,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() { }, { name: "latest client height < height", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height-1, suite.now), connection: conn, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -144,7 +144,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() { }, { name: "proof verification failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), connection: conn, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -196,7 +196,7 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() { // }, { name: "ApplyPrefix failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), channel: ch, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -206,7 +206,7 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() { }, { name: "latest client height < height", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height-1, suite.now), channel: ch, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -226,7 +226,7 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() { }, { name: "proof verification failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), channel: ch, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -275,7 +275,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() { // }, { name: "ApplyPrefix failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), commitment: []byte{}, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -285,7 +285,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() { }, { name: "latest client height < height", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height-1, suite.now), commitment: []byte{}, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -305,7 +305,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() { }, { name: "proof verification failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), commitment: []byte{}, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -344,7 +344,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() { }{ // { // name: "successful verification", - // clientState: ibctmtypes.NewClientState(chainID, height), + // clientState: ibctmtypes.NewClientState(chainID, chainID, height), // connection: conn, // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), @@ -354,7 +354,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() { // }, { name: "ApplyPrefix failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), ack: []byte{}, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -364,7 +364,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() { }, { name: "latest client height < height", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height-1, suite.now), ack: []byte{}, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -384,7 +384,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() { }, { name: "proof verification failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), ack: []byte{}, consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), @@ -422,7 +422,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() { }{ // { // name: "successful verification", - // clientState: ibctmtypes.NewClientState(chainID, height), + // clientState: ibctmtypes.NewClientState(chainID, chainID, height), // connection: conn, // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), @@ -432,7 +432,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() { // }, { name: "ApplyPrefix failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, @@ -441,7 +441,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() { }, { name: "latest client height < height", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height-1, suite.now), consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, @@ -459,7 +459,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() { }, { name: "proof verification failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, @@ -496,7 +496,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() { }{ // { // name: "successful verification", - // clientState: ibctmtypes.NewClientState(chainID, height), + // clientState: ibctmtypes.NewClientState(chainID, chainID, height), // connection: conn, // consensusState: ibctmtypes.ConsensusState{ // Root: commitment.NewRoot(suite.header.AppHash), @@ -506,7 +506,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() { // }, { name: "ApplyPrefix failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, @@ -515,7 +515,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() { }, { name: "latest client height < height", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height-1, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height-1, suite.now), consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), }, @@ -533,7 +533,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() { }, { name: "proof verification failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.now), + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.now), consensusState: ibctmtypes.ConsensusState{ Root: commitment.NewRoot(suite.header.AppHash), ValidatorSet: suite.valSet, diff --git a/x/ibc/07-tendermint/types/errors.go b/x/ibc/07-tendermint/types/errors.go index 1348d340fabb..1f2bcd48174b 100644 --- a/x/ibc/07-tendermint/types/errors.go +++ b/x/ibc/07-tendermint/types/errors.go @@ -11,4 +11,5 @@ const ( var ( ErrInvalidTrustingPeriod = sdkerrors.Register(SubModuleName, 1, "invalid trusting period") ErrInvalidUnbondingPeriod = sdkerrors.Register(SubModuleName, 2, "invalid unbonding period") + ErrInvalidChainID = sdkerrors.Register(SubModuleName, 3, "invalid chain ID") ) diff --git a/x/ibc/07-tendermint/types/msgs.go b/x/ibc/07-tendermint/types/msgs.go index 6382f916d0b0..99d2ca209213 100644 --- a/x/ibc/07-tendermint/types/msgs.go +++ b/x/ibc/07-tendermint/types/msgs.go @@ -24,6 +24,7 @@ var _ clientexported.MsgUpdateClient = MsgUpdateClient{} // MsgCreateClient defines a message to create an IBC client type MsgCreateClient struct { ClientID string `json:"client_id" yaml:"client_id"` + ChainID string `json:"chain_id" yaml:"chain_id"` ConsensusState ConsensusState `json:"consensus_state" yaml:"consensus_state"` TrustingPeriod time.Duration `json:"trusting_period" yaml:"trusting_period"` UnbondingPeriod time.Duration `json:"unbonding_period" yaml:"unbonding_period"` @@ -32,11 +33,12 @@ type MsgCreateClient struct { // NewMsgCreateClient creates a new MsgCreateClient instance func NewMsgCreateClient( - id string, consensusState ConsensusState, + id string, chainID string, consensusState ConsensusState, trustingPeriod, unbondingPeriod time.Duration, signer sdk.AccAddress, ) MsgCreateClient { return MsgCreateClient{ ClientID: id, + ChainID: chainID, ConsensusState: consensusState, TrustingPeriod: trustingPeriod, UnbondingPeriod: unbondingPeriod, @@ -56,6 +58,9 @@ func (msg MsgCreateClient) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgCreateClient) ValidateBasic() error { + if msg.ChainID == "" { + return sdkerrors.Wrap(ErrInvalidChainID, "cannot have empty chain-id") + } if err := msg.ConsensusState.ValidateBasic(); err != nil { return err } diff --git a/x/ibc/07-tendermint/types/msgs_test.go b/x/ibc/07-tendermint/types/msgs_test.go index f4e0bbaecdad..6ea7eac33828 100644 --- a/x/ibc/07-tendermint/types/msgs_test.go +++ b/x/ibc/07-tendermint/types/msgs_test.go @@ -28,19 +28,21 @@ func TestMsgCreateClientValidateBasic(t *testing.T) { } privKey := secp256k1.GenPrivKey() signer := sdk.AccAddress(privKey.PubKey().Address()) + chainID := "gaia" cases := []struct { msg ibctmtypes.MsgCreateClient expPass bool errMsg string }{ - {ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, cs, trustingPeriod, ubdPeriod, signer), true, "success msg should pass"}, - {ibctmtypes.NewMsgCreateClient("BADCHAIN", cs, trustingPeriod, ubdPeriod, signer), false, "invalid client id passed"}, - {ibctmtypes.NewMsgCreateClient("goodchain", cs, trustingPeriod, ubdPeriod, signer), false, "unregistered client type passed"}, - {ibctmtypes.NewMsgCreateClient("goodchain", ibctmtypes.ConsensusState{}, trustingPeriod, ubdPeriod, signer), false, "invalid Consensus State in msg passed"}, - {ibctmtypes.NewMsgCreateClient("goodchain", cs, 0, ubdPeriod, signer), false, "zero trusting period passed"}, - {ibctmtypes.NewMsgCreateClient("goodchain", cs, trustingPeriod, 0, signer), false, "zero unbonding period passed"}, - {ibctmtypes.NewMsgCreateClient("goodchain", cs, trustingPeriod, ubdPeriod, nil), false, "Empty address passed"}, + {ibctmtypes.NewMsgCreateClient(exported.ClientTypeTendermint, chainID, cs, trustingPeriod, ubdPeriod, signer), true, "success msg should pass"}, + {ibctmtypes.NewMsgCreateClient("BADCHAIN", chainID, cs, trustingPeriod, ubdPeriod, signer), false, "invalid client id passed"}, + {ibctmtypes.NewMsgCreateClient("goodchain", chainID, cs, trustingPeriod, ubdPeriod, signer), false, "unregistered client type passed"}, + {ibctmtypes.NewMsgCreateClient("goodchain", chainID, ibctmtypes.ConsensusState{}, trustingPeriod, ubdPeriod, signer), false, "invalid Consensus State in msg passed"}, + {ibctmtypes.NewMsgCreateClient("goodchain", chainID, cs, 0, ubdPeriod, signer), false, "zero trusting period passed"}, + {ibctmtypes.NewMsgCreateClient("goodchain", chainID, cs, trustingPeriod, 0, signer), false, "zero unbonding period passed"}, + {ibctmtypes.NewMsgCreateClient("goodchain", chainID, cs, trustingPeriod, ubdPeriod, nil), false, "Empty address passed"}, + {ibctmtypes.NewMsgCreateClient("goodchain", "", cs, trustingPeriod, ubdPeriod, nil), false, "Empty chain ID"}, } for i, tc := range cases { diff --git a/x/ibc/07-tendermint/update.go b/x/ibc/07-tendermint/update.go index c1a86d8393b6..b9bfebca401c 100644 --- a/x/ibc/07-tendermint/update.go +++ b/x/ibc/07-tendermint/update.go @@ -21,7 +21,7 @@ import ( // Tendermint client validity checking uses the bisection algorithm described // in the [Tendermint spec](https://github.com/tendermint/spec/blob/master/spec/consensus/light-client.md). func CheckValidityAndUpdateState( - clientState clientexported.ClientState, header clientexported.Header, chainID string, + clientState clientexported.ClientState, header clientexported.Header, currentTimestamp time.Time, ) (clientexported.ClientState, clientexported.ConsensusState, error) { tmClientState, ok := clientState.(types.ClientState) @@ -38,7 +38,7 @@ func CheckValidityAndUpdateState( ) } - if err := checkValidity(tmClientState, tmHeader, chainID, currentTimestamp); err != nil { + if err := checkValidity(tmClientState, tmHeader, currentTimestamp); err != nil { return nil, nil, err } @@ -50,7 +50,7 @@ func CheckValidityAndUpdateState( // // CONTRACT: assumes header.Height > consensusState.Height func checkValidity( - clientState types.ClientState, header types.Header, chainID string, currentTimestamp time.Time, + clientState types.ClientState, header types.Header, currentTimestamp time.Time, ) error { // assert trusting period has not yet passed if currentTimestamp.Sub(clientState.LatestTimestamp) >= clientState.TrustingPeriod { @@ -83,7 +83,7 @@ func checkValidity( } // basic consistency check - if err := header.ValidateBasic(chainID); err != nil { + if err := header.ValidateBasic(clientState.ChainID); err != nil { return err } diff --git a/x/ibc/07-tendermint/update_test.go b/x/ibc/07-tendermint/update_test.go index 33f693cae85f..5c465c398335 100644 --- a/x/ibc/07-tendermint/update_test.go +++ b/x/ibc/07-tendermint/update_test.go @@ -10,25 +10,21 @@ func (suite *TendermintTestSuite) TestCheckValidity() { testCases := []struct { name string clientState ibctmtypes.ClientState - chainID string expPass bool }{ { name: "successful update", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.clientTime), - chainID: chainID, + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height, suite.clientTime), expPass: true, }, { name: "header basic validation failed", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height, suite.clientTime), - chainID: "cosmoshub", + clientState: ibctmtypes.NewClientState(chainID, "cosmoshub", trustingPeriod, ubdPeriod, height, suite.clientTime), expPass: false, }, { name: "header height < latest client height", - clientState: ibctmtypes.NewClientState(chainID, trustingPeriod, ubdPeriod, height+1, suite.clientTime), - chainID: chainID, + clientState: ibctmtypes.NewClientState(chainID, chainID, trustingPeriod, ubdPeriod, height+1, suite.clientTime), expPass: false, }, } @@ -42,7 +38,7 @@ func (suite *TendermintTestSuite) TestCheckValidity() { ValidatorSet: suite.header.ValidatorSet, } - clientState, consensusState, err := tendermint.CheckValidityAndUpdateState(tc.clientState, suite.header, tc.chainID, suite.now) + clientState, consensusState, err := tendermint.CheckValidityAndUpdateState(tc.clientState, suite.header, suite.now) if tc.expPass { suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) diff --git a/x/ibc/20-transfer/handler_test.go b/x/ibc/20-transfer/handler_test.go index ca8deb292181..e792a9eded06 100644 --- a/x/ibc/20-transfer/handler_test.go +++ b/x/ibc/20-transfer/handler_test.go @@ -92,7 +92,7 @@ func (suite *HandlerTestSuite) createClient() { ValidatorSet: suite.valSet, } - clientState, err := ibctmtypes.Initialize(testClient, consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClient, testClient, consensusState, trustingPeriod, ubdPeriod) suite.NoError(err) _, err = suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientState, consensusState) suite.NoError(err) diff --git a/x/ibc/20-transfer/keeper/relay_test.go b/x/ibc/20-transfer/keeper/relay_test.go index 5e22240842a8..31357c6637e3 100644 --- a/x/ibc/20-transfer/keeper/relay_test.go +++ b/x/ibc/20-transfer/keeper/relay_test.go @@ -29,7 +29,7 @@ func (suite *KeeperTestSuite) createClient() { ValidatorSet: suite.valSet, } - clientState, err := ibctmtypes.Initialize(testClient, consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClient, testClient, consensusState, trustingPeriod, ubdPeriod) suite.NoError(err) _, err = suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientState, consensusState) suite.NoError(err) diff --git a/x/ibc/ante/ante_test.go b/x/ibc/ante/ante_test.go index ef96ecc02625..3c350a198c6c 100644 --- a/x/ibc/ante/ante_test.go +++ b/x/ibc/ante/ante_test.go @@ -83,7 +83,7 @@ func (suite *HandlerTestSuite) createClient() { ValidatorSet: suite.valSet, } - clientState, err := ibctmtypes.Initialize(testClient, consensusState, trustingPeriod, ubdPeriod) + clientState, err := ibctmtypes.Initialize(testClient, testClient, consensusState, trustingPeriod, ubdPeriod) suite.NoError(err) _, err = suite.app.IBCKeeper.ClientKeeper.CreateClient(suite.ctx, clientState, consensusState) suite.NoError(err) From de8e815332593bdb3e3cf08d328ab141249b303c Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Tue, 18 Feb 2020 04:53:34 -0800 Subject: [PATCH 12/12] address necessary fede review --- x/ibc/02-client/handler.go | 17 ++++++++++------- x/ibc/07-tendermint/types/client_state.go | 3 --- x/ibc/07-tendermint/types/msgs.go | 3 ++- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/x/ibc/02-client/handler.go b/x/ibc/02-client/handler.go index 1f7993366a2f..3354fe93b8c4 100644 --- a/x/ibc/02-client/handler.go +++ b/x/ibc/02-client/handler.go @@ -13,6 +13,7 @@ import ( // HandleMsgCreateClient defines the sdk.Handler for MsgCreateClient func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg exported.MsgCreateClient) (*sdk.Result, error) { clientType := exported.ClientTypeFromString(msg.GetClientType()) + var clientState exported.ClientState switch clientType { case 0: return nil, sdkerrors.Wrap(ErrInvalidClientType, msg.GetClientType()) @@ -21,13 +22,8 @@ func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg exported.MsgCreateClie if !ok { return nil, sdkerrors.Wrap(ErrInvalidClientType, "Msg is not a Tendermint CreateClient msg") } - clientState, err := ibctmtypes.InitializeFromMsg(tmMsg) - if err != nil { - return nil, err - } - _, err = k.CreateClient( - ctx, clientState, msg.GetConsensusState(), - ) + var err error + clientState, err = ibctmtypes.InitializeFromMsg(tmMsg) if err != nil { return nil, err } @@ -35,6 +31,13 @@ func HandleMsgCreateClient(ctx sdk.Context, k Keeper, msg exported.MsgCreateClie return nil, sdkerrors.Wrap(ErrInvalidClientType, msg.GetClientType()) } + _, err := k.CreateClient( + ctx, clientState, msg.GetConsensusState(), + ) + if err != nil { + return nil, err + } + attributes := make([]sdk.Attribute, len(msg.GetSigners())+1) attributes[0] = sdk.NewAttribute(sdk.AttributeKeyModule, AttributeValueCategory) for i, signer := range msg.GetSigners() { diff --git a/x/ibc/07-tendermint/types/client_state.go b/x/ibc/07-tendermint/types/client_state.go index d0ea9c87c3a6..e681d8f7199f 100644 --- a/x/ibc/07-tendermint/types/client_state.go +++ b/x/ibc/07-tendermint/types/client_state.go @@ -59,9 +59,6 @@ func Initialize( if trustingPeriod >= ubdPeriod { return ClientState{}, errors.New("trusting period should be < unbonding period") } - if chainID == "" { - return ClientState{}, errors.New("client state cannot have empty chain id") - } clientState := NewClientState( id, chainID, trustingPeriod, ubdPeriod, latestHeight, tmConsState.Timestamp, diff --git a/x/ibc/07-tendermint/types/msgs.go b/x/ibc/07-tendermint/types/msgs.go index 99d2ca209213..cc065a6ec308 100644 --- a/x/ibc/07-tendermint/types/msgs.go +++ b/x/ibc/07-tendermint/types/msgs.go @@ -1,6 +1,7 @@ package types import ( + "strings" "time" sdk "github.com/cosmos/cosmos-sdk/types" @@ -58,7 +59,7 @@ func (msg MsgCreateClient) Type() string { // ValidateBasic implements sdk.Msg func (msg MsgCreateClient) ValidateBasic() error { - if msg.ChainID == "" { + if strings.TrimSpace(msg.ChainID) == "" { return sdkerrors.Wrap(ErrInvalidChainID, "cannot have empty chain-id") } if err := msg.ConsensusState.ValidateBasic(); err != nil {