From 0df0626604bf4b5ed2a7dd8204bb10b9e3f9d920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Fri, 8 Jan 2021 14:00:07 +0100 Subject: [PATCH] Generic 02-client cli cmds, removes light client specific ones (#8259) * remove old light client cli cmds and replace with generic ones housed in client * remove print and add client cli getter cmds * use any as arguments * revert back to single pub key * fix tests * typo * remove todo * add upgrade cli cmd cc @AdityaSripal * register upgrade cmd --- x/auth/client/rest/rest_test.go | 20 +- x/ibc/core/02-client/client/cli/cli.go | 20 ++ x/ibc/core/02-client/client/cli/query.go | 6 +- x/ibc/core/02-client/client/cli/tx.go | 246 +++++++++++++++ x/ibc/core/02-client/module.go | 5 + x/ibc/core/client/cli/cli.go | 5 +- .../06-solomachine/client/cli/cli.go | 27 -- .../06-solomachine/client/cli/tx.go | 169 ----------- x/ibc/light-clients/06-solomachine/module.go | 8 - .../06-solomachine/types/misbehaviour.go | 4 +- .../07-tendermint/client/cli/cli.go | 25 -- .../07-tendermint/client/cli/tx.go | 281 ------------------ x/ibc/light-clients/07-tendermint/module.go | 8 - 13 files changed, 290 insertions(+), 534 deletions(-) create mode 100644 x/ibc/core/02-client/client/cli/tx.go delete mode 100644 x/ibc/light-clients/06-solomachine/client/cli/cli.go delete mode 100644 x/ibc/light-clients/06-solomachine/client/cli/tx.go delete mode 100644 x/ibc/light-clients/07-tendermint/client/cli/cli.go delete mode 100644 x/ibc/light-clients/07-tendermint/client/cli/tx.go diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index e20874f6e716..d485467249a5 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -25,8 +25,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" "github.com/cosmos/cosmos-sdk/x/bank/types" + ibcclientcli "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/client/cli" ibccli "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/client/cli" - ibcsolomachinecli "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/client/cli" ) type IntegrationTestSuite struct { @@ -480,10 +480,20 @@ func (s *IntegrationTestSuite) testQueryIBCTx(txRes sdk.TxResponse, cmd *cobra.C func (s *IntegrationTestSuite) TestLegacyRestErrMessages() { val := s.network.Validators[0] + // Write client state json to temp file, used for an IBC message. + // Generated by printing the result of cdc.MarshalIntefaceJSON on + // a solo machine client state + clientStateJSON := testutil.WriteToNewTempFile( + s.T(), + `{"@type":"/ibc.lightclients.solomachine.v1.ClientState","sequence":"1","frozen_sequence":"0","consensus_state":{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"},"allow_update_after_proposal":false}`, + ) + // Write consensus json to temp file, used for an IBC message. + // Generated by printing the result of cdc.MarshalIntefaceJSON on + // a solo machine consensus state consensusJSON := testutil.WriteToNewTempFile( s.T(), - `{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A/3SXL2ONYaOkxpdR5P8tHTlSlPv1AwQwSFxKRee5JQW"},"diversifier":"diversifier","timestamp":"10"}`, + `{"@type":"/ibc.lightclients.solomachine.v1.ConsensusState","public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"}`, ) testCases := []struct { @@ -509,10 +519,10 @@ func (s *IntegrationTestSuite) TestLegacyRestErrMessages() { }, { "Successful IBC message", - ibcsolomachinecli.NewCreateClientCmd(), + ibcclientcli.NewCreateClientCmd(), []string{ - "1", // dummy sequence - consensusJSON.Name(), // path to consensus json, + clientStateJSON.Name(), // path to client state json + consensusJSON.Name(), // path to consensus json, fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), diff --git a/x/ibc/core/02-client/client/cli/cli.go b/x/ibc/core/02-client/client/cli/cli.go index 375d8f63693c..33c991521582 100644 --- a/x/ibc/core/02-client/client/cli/cli.go +++ b/x/ibc/core/02-client/client/cli/cli.go @@ -29,3 +29,23 @@ func GetQueryCmd() *cobra.Command { return queryCmd } + +// NewTxCmd returns the command to create and handle IBC clients +func NewTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: types.SubModuleName, + Short: "IBC client transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + NewCreateClientCmd(), + NewUpdateClientCmd(), + NewSubmitMisbehaviourCmd(), + NewUpgradeClientCmd(), + ) + + return txCmd +} diff --git a/x/ibc/core/02-client/client/cli/query.go b/x/ibc/core/02-client/client/cli/query.go index a1e9b45d22cf..7c49b12e0220 100644 --- a/x/ibc/core/02-client/client/cli/query.go +++ b/x/ibc/core/02-client/client/cli/query.go @@ -193,12 +193,11 @@ func GetCmdQueryHeader() *cobra.Command { if err != nil { return err } - header, height, err := utils.QueryTendermintHeader(clientCtx) + header, _, err := utils.QueryTendermintHeader(clientCtx) if err != nil { return err } - clientCtx = clientCtx.WithHeight(height) return clientCtx.PrintProto(&header) }, } @@ -222,12 +221,11 @@ func GetCmdNodeConsensusState() *cobra.Command { if err != nil { return err } - state, height, err := utils.QueryNodeConsensusState(clientCtx) + state, _, err := utils.QueryNodeConsensusState(clientCtx) if err != nil { return err } - clientCtx = clientCtx.WithHeight(height) return clientCtx.PrintProto(state) }, } diff --git a/x/ibc/core/02-client/client/cli/tx.go b/x/ibc/core/02-client/client/cli/tx.go new file mode 100644 index 000000000000..d036a5766d84 --- /dev/null +++ b/x/ibc/core/02-client/client/cli/tx.go @@ -0,0 +1,246 @@ +package cli + +import ( + "fmt" + "io/ioutil" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" + "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" +) + +// NewCreateClientCmd defines the command to create a new IBC light client. +func NewCreateClientCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "create [path/to/client_state.json] [path/to/consensus_state.json]", + Short: "create new IBC client", + Long: `create a new IBC client with the specified client state and consensus state + - ClientState JSON example: {"@type":"/ibc.lightclients.solomachine.v1.ClientState","sequence":"1","frozen_sequence":"0","consensus_state":{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"},"allow_update_after_proposal":false} + - ConsensusState JSON example: {"@type":"/ibc.lightclients.solomachine.v1.ConsensusState","public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"}`, + Example: fmt.Sprintf("%s tx ibc %s create [path/to/client_state.json] [path/to/consensus_state.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) + + // attempt to unmarshal client state argument + var clientState exported.ClientState + clientContentOrFileName := args[0] + if err := cdc.UnmarshalInterfaceJSON([]byte(clientContentOrFileName), &clientState); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(clientContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for client state were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, &clientState); err != nil { + return errors.Wrap(err, "error unmarshalling client state file") + } + } + + // attempt to unmarshal consensus state argument + var consensusState exported.ConsensusState + consensusContentOrFileName := args[1] + if err := cdc.UnmarshalInterfaceJSON([]byte(consensusContentOrFileName), &consensusState); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(consensusContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for consensus state were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, &consensusState); err != nil { + return errors.Wrap(err, "error unmarshalling consensus state file") + } + } + + msg, err := types.NewMsgCreateClient(clientState, consensusState, clientCtx.GetFromAddress()) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// NewUpdateClientCmd defines the command to update an IBC client. +func NewUpdateClientCmd() *cobra.Command { + return &cobra.Command{ + Use: "update [client-id] [path/to/header.json]", + Short: "update existing client with a header", + Long: "update existing client with a header", + Example: fmt.Sprintf("%s tx ibc %s update [client-id] [path/to/header.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + clientID := args[0] + + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) + + var header exported.Header + headerContentOrFileName := args[1] + if err := cdc.UnmarshalInterfaceJSON([]byte(headerContentOrFileName), &header); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(headerContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for header were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, &header); err != nil { + return errors.Wrap(err, "error unmarshalling header file") + } + } + + msg, err := types.NewMsgUpdateClient(clientID, header, clientCtx.GetFromAddress()) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } +} + +// NewSubmitMisbehaviourCmd defines the command to submit a misbehaviour to prevent +// future updates. +func NewSubmitMisbehaviourCmd() *cobra.Command { + return &cobra.Command{ + Use: "misbehaviour [path/to/misbehaviour.json]", + Short: "submit a client misbehaviour", + Long: "submit a client misbehaviour to prevent future updates", + Example: fmt.Sprintf("%s tx ibc %s misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) + + var misbehaviour exported.Misbehaviour + misbehaviourContentOrFileName := args[0] + if err := cdc.UnmarshalInterfaceJSON([]byte(misbehaviourContentOrFileName), &misbehaviour); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(misbehaviourContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for misbehaviour were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, misbehaviour); err != nil { + return errors.Wrap(err, "error unmarshalling misbehaviour file") + } + } + + msg, err := types.NewMsgSubmitMisbehaviour(misbehaviour.GetClientID(), misbehaviour, clientCtx.GetFromAddress()) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } +} + +// NewUpgradeClientCmd defines the command to upgrade an IBC light client. +func NewUpgradeClientCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "upgrade [client-identifier] [path/to/client_state.json] [path/to/consensus_state.json] [upgrade-client-proof] [upgrade-consensus-state-proof]", + Short: "upgrade an IBC client", + Long: `upgrade the IBC client associated with the provided client identifier while providing proof committed by the counterparty chain to the new client and consensus states + - ClientState JSON example: {"@type":"/ibc.lightclients.solomachine.v1.ClientState","sequence":"1","frozen_sequence":"0","consensus_state":{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"},"allow_update_after_proposal":false} + - ConsensusState JSON example: {"@type":"/ibc.lightclients.solomachine.v1.ConsensusState","public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"}`, + Example: fmt.Sprintf("%s tx ibc %s upgrade [client-identifier] [path/to/client_state.json] [path/to/consensus_state.json] [client-state-proof] [consensus-state-proof] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), + Args: cobra.ExactArgs(5), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) + clientID := args[0] + + // attempt to unmarshal client state argument + var clientState exported.ClientState + clientContentOrFileName := args[1] + if err := cdc.UnmarshalInterfaceJSON([]byte(clientContentOrFileName), &clientState); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(clientContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for client state were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, &clientState); err != nil { + return errors.Wrap(err, "error unmarshalling client state file") + } + } + + // attempt to unmarshal consensus state argument + var consensusState exported.ConsensusState + consensusContentOrFileName := args[2] + if err := cdc.UnmarshalInterfaceJSON([]byte(consensusContentOrFileName), &consensusState); err != nil { + + // check for file path if JSON input is not provided + contents, err := ioutil.ReadFile(consensusContentOrFileName) + if err != nil { + return errors.Wrap(err, "neither JSON input nor path to .json file for consensus state were provided") + } + + if err := cdc.UnmarshalInterfaceJSON(contents, &consensusState); err != nil { + return errors.Wrap(err, "error unmarshalling consensus state file") + } + } + + proofUpgradeClient := []byte(args[3]) + proofUpgradeConsensus := []byte(args[4]) + + msg, err := types.NewMsgUpgradeClient(clientID, clientState, consensusState, proofUpgradeClient, proofUpgradeConsensus, clientCtx.GetFromAddress()) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/ibc/core/02-client/module.go b/x/ibc/core/02-client/module.go index 9a051ba1abcf..08efee8b1adc 100644 --- a/x/ibc/core/02-client/module.go +++ b/x/ibc/core/02-client/module.go @@ -18,6 +18,11 @@ func GetQueryCmd() *cobra.Command { return cli.GetQueryCmd() } +// GetTxCmd returns the root tx command for 02-client. +func GetTxCmd() *cobra.Command { + return cli.NewTxCmd() +} + // RegisterQueryService registers the gRPC query service for IBC client. func RegisterQueryService(server grpc.Server, queryServer types.QueryServer) { types.RegisterQueryServer(server, queryServer) diff --git a/x/ibc/core/client/cli/cli.go b/x/ibc/core/client/cli/cli.go index 51bb063a6a0b..bda4123be0ec 100644 --- a/x/ibc/core/client/cli/cli.go +++ b/x/ibc/core/client/cli/cli.go @@ -8,8 +8,6 @@ import ( connection "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection" channel "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel" host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - solomachine "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine" - tendermint "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint" ) // GetTxCmd returns the transaction commands for this module @@ -23,8 +21,7 @@ func GetTxCmd() *cobra.Command { } ibcTxCmd.AddCommand( - solomachine.GetTxCmd(), - tendermint.GetTxCmd(), + ibcclient.GetTxCmd(), connection.GetTxCmd(), channel.GetTxCmd(), ) diff --git a/x/ibc/light-clients/06-solomachine/client/cli/cli.go b/x/ibc/light-clients/06-solomachine/client/cli/cli.go deleted file mode 100644 index ab44926204f1..000000000000 --- a/x/ibc/light-clients/06-solomachine/client/cli/cli.go +++ /dev/null @@ -1,27 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" -) - -// NewTxCmd returns a root CLI command handler for all solo machine transaction commands. -func NewTxCmd() *cobra.Command { - txCmd := &cobra.Command{ - Use: types.SubModuleName, - Short: "Solo Machine transaction subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - txCmd.AddCommand( - NewCreateClientCmd(), - NewUpdateClientCmd(), - NewSubmitMisbehaviourCmd(), - ) - - return txCmd -} diff --git a/x/ibc/light-clients/06-solomachine/client/cli/tx.go b/x/ibc/light-clients/06-solomachine/client/cli/tx.go deleted file mode 100644 index dea2d2ae7388..000000000000 --- a/x/ibc/light-clients/06-solomachine/client/cli/tx.go +++ /dev/null @@ -1,169 +0,0 @@ -package cli - -import ( - "fmt" - "io/ioutil" - "strconv" - - "github.com/pkg/errors" - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/version" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" -) - -const ( - flagAllowUpdateAfterProposal = "allow_update_after_proposal" -) - -// NewCreateClientCmd defines the command to create a new solo machine client. -func NewCreateClientCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "create [sequence] [path/to/consensus_state.json]", - Short: "create new solo machine client", - Long: `create a new solo machine client with the specified identifier and public key - - ConsensusState json example: {"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A/3SXL2ONYaOkxpdR5P8tHTlSlPv1AwQwSFxKRee5JQW"},"diversifier":"diversifier","timestamp":"10"}`, - Example: fmt.Sprintf("%s tx ibc %s create [sequence] [path/to/consensus_state] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - sequence, err := strconv.ParseUint(args[0], 10, 64) - if err != nil { - return err - } - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - // attempt to unmarshal consensus state argument - consensusState := &types.ConsensusState{} - if err := cdc.UnmarshalJSON([]byte(args[1]), consensusState); err != nil { - - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[1]) - if err != nil { - return errors.Wrap(err, "neither JSON input nor path to .json file for consensus state were provided") - } - - if err := cdc.UnmarshalJSON(contents, consensusState); err != nil { - return errors.Wrap(err, "error unmarshalling consensus state file") - } - } - - allowUpdateAfterProposal, _ := cmd.Flags().GetBool(flagAllowUpdateAfterProposal) - - clientState := types.NewClientState(sequence, consensusState, allowUpdateAfterProposal) - msg, err := clienttypes.NewMsgCreateClient(clientState, consensusState, clientCtx.GetFromAddress()) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - cmd.Flags().Bool(flagAllowUpdateAfterProposal, false, "allow governance proposal to update client") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewUpdateClientCmd defines the command to update a solo machine client. -func NewUpdateClientCmd() *cobra.Command { - return &cobra.Command{ - Use: "update [client-id] [path/to/header.json]", - Short: "update existing client with a header", - Long: "update existing client with a solo machine header", - Example: fmt.Sprintf("%s tx ibc %s update [client-id] [path/to/header.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - clientID := args[0] - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - header := &types.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]) - if err != nil { - return errors.Wrap(err, "neither JSON input nor path to .json file for header were provided") - } - - if err := cdc.UnmarshalJSON(contents, header); err != nil { - return errors.Wrap(err, "error unmarshalling header file") - } - } - - msg, err := clienttypes.NewMsgUpdateClient(clientID, header, clientCtx.GetFromAddress()) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } -} - -// NewSubmitMisbehaviourCmd defines the command to submit a misbehaviour to prevent -// future updates. -func NewSubmitMisbehaviourCmd() *cobra.Command { - return &cobra.Command{ - Use: "misbehaviour [path/to/misbehaviour.json]", - Short: "submit a client misbehaviour", - Long: "submit a client misbehaviour to prevent future updates", - Example: fmt.Sprintf("%s tx ibc %s misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - m := &types.Misbehaviour{} - if err := cdc.UnmarshalJSON([]byte(args[0]), m); err != nil { - - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[0]) - if err != nil { - return errors.Wrap(err, "neither JSON input nor path to .json file for misbehaviour were provided") - } - - if err := cdc.UnmarshalJSON(contents, m); err != nil { - return errors.Wrap(err, "error unmarshalling misbehaviour file") - } - } - - msg, err := clienttypes.NewMsgSubmitMisbehaviour(m.ClientId, m, clientCtx.GetFromAddress()) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } -} diff --git a/x/ibc/light-clients/06-solomachine/module.go b/x/ibc/light-clients/06-solomachine/module.go index bdc7d9c04838..bafbd0152f1c 100644 --- a/x/ibc/light-clients/06-solomachine/module.go +++ b/x/ibc/light-clients/06-solomachine/module.go @@ -1,9 +1,6 @@ package solomachine import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/client/cli" "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" ) @@ -11,8 +8,3 @@ import ( func Name() string { return types.SubModuleName } - -// GetTxCmd returns the root tx command for the solo machine client. -func GetTxCmd() *cobra.Command { - return cli.NewTxCmd() -} diff --git a/x/ibc/light-clients/06-solomachine/types/misbehaviour.go b/x/ibc/light-clients/06-solomachine/types/misbehaviour.go index 65b8a4ee4753..f5b218ccf208 100644 --- a/x/ibc/light-clients/06-solomachine/types/misbehaviour.go +++ b/x/ibc/light-clients/06-solomachine/types/misbehaviour.go @@ -9,9 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) -var ( - _ exported.Misbehaviour = (*Misbehaviour)(nil) -) +var _ exported.Misbehaviour = &Misbehaviour{} // ClientType is a Solo Machine light client. func (misbehaviour Misbehaviour) ClientType() string { diff --git a/x/ibc/light-clients/07-tendermint/client/cli/cli.go b/x/ibc/light-clients/07-tendermint/client/cli/cli.go deleted file mode 100644 index a214869d089e..000000000000 --- a/x/ibc/light-clients/07-tendermint/client/cli/cli.go +++ /dev/null @@ -1,25 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -// NewTxCmd returns a root CLI command handler for all x/ibc/light-clients/07-tendermint transaction commands. -func NewTxCmd() *cobra.Command { - txCmd := &cobra.Command{ - Use: types.SubModuleName, - Short: "Tendermint client transaction subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - } - - txCmd.AddCommand( - NewCreateClientCmd(), - NewUpdateClientCmd(), - NewSubmitMisbehaviourCmd(), - ) - - return txCmd -} diff --git a/x/ibc/light-clients/07-tendermint/client/cli/tx.go b/x/ibc/light-clients/07-tendermint/client/cli/tx.go deleted file mode 100644 index f8b925e4f0cc..000000000000 --- a/x/ibc/light-clients/07-tendermint/client/cli/tx.go +++ /dev/null @@ -1,281 +0,0 @@ -package cli - -import ( - "fmt" - "io/ioutil" - "strconv" - "strings" - "time" - - ics23 "github.com/confio/ics23/go" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/tendermint/tendermint/light" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/version" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -const ( - flagTrustLevel = "trust-level" - flagProofSpecs = "proof-specs" - flagUpgradePath = "upgrade-path" - flagAllowUpdateAfterExpiry = "allow_update_after_expiry" - flagAllowUpdateAfterMisbehaviour = "allow_update_after_misbehaviour" -) - -// NewCreateClientCmd defines the command to create a new IBC Client as defined -// in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create -func NewCreateClientCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "create [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift]", - Short: "create new tendermint client", - Long: `Create a new tendermint IBC client. - - 'trust-level' flag can be a fraction (eg: '1/3') or 'default' - - 'proof-specs' flag can be JSON input, a path to a .json file or 'default' - - 'upgrade-path' flag is a string specifying the upgrade path for this chain where a future upgraded client will be stored. The path is a comma-separated list representing the keys in order of the keyPath to the committed upgraded client. - e.g. 'upgrade/upgradedClient'`, - Example: fmt.Sprintf("%s tx ibc %s create [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift] --trust-level default --consensus-params [path/to/consensus-params.json] --proof-specs [path/to/proof-specs.json] --upgrade-path upgrade/upgradedClient --from node0 --home ../node0/cli --chain-id $CID", version.AppName, types.SubModuleName), - Args: cobra.ExactArgs(4), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - legacyAmino := codec.NewLegacyAmino() - - var header *types.Header - if err := cdc.UnmarshalJSON([]byte(args[0]), header); err != nil { - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[0]) - if err != nil { - return errors.New("neither JSON input nor path to .json file were provided for consensus header") - } - if err := cdc.UnmarshalJSON(contents, header); err != nil { - return errors.Wrap(err, "error unmarshalling consensus header file") - } - } - - var ( - trustLevel types.Fraction - specs []*ics23.ProofSpec - ) - - lvl, _ := cmd.Flags().GetString(flagTrustLevel) - - if lvl == "default" { - trustLevel = types.NewFractionFromTm(light.DefaultTrustLevel) - } else { - trustLevel, err = parseFraction(lvl) - if err != nil { - return err - } - } - - trustingPeriod, err := time.ParseDuration(args[1]) - if err != nil { - return err - } - - ubdPeriod, err := time.ParseDuration(args[2]) - if err != nil { - return err - } - - maxClockDrift, err := time.ParseDuration(args[3]) - if err != nil { - return err - } - - spc, _ := cmd.Flags().GetString(flagProofSpecs) - if spc == "default" { - specs = commitmenttypes.GetSDKSpecs() - // TODO migrate to use JSONMarshaler (implement MarshalJSONArray - // or wrap lists of proto.Message in some other message) - } else if err := legacyAmino.UnmarshalJSON([]byte(spc), &specs); err != nil { - // check for file path if JSON input not provided - contents, err := ioutil.ReadFile(spc) - if err != nil { - return errors.New("neither JSON input nor path to .json file was provided for proof specs flag") - } - // TODO migrate to use JSONMarshaler (implement MarshalJSONArray - // or wrap lists of proto.Message in some other message) - if err := legacyAmino.UnmarshalJSON(contents, &specs); err != nil { - return errors.Wrap(err, "error unmarshalling proof specs file") - } - } - - allowUpdateAfterExpiry, _ := cmd.Flags().GetBool(flagAllowUpdateAfterExpiry) - allowUpdateAfterMisbehaviour, _ := cmd.Flags().GetBool(flagAllowUpdateAfterMisbehaviour) - - upgradePathStr, _ := cmd.Flags().GetString(flagUpgradePath) - upgradePath := strings.Split(upgradePathStr, ",") - - // validate header - if err := header.ValidateBasic(); err != nil { - return err - } - - height := header.GetHeight().(clienttypes.Height) - - clientState := types.NewClientState( - header.GetHeader().GetChainID(), trustLevel, trustingPeriod, ubdPeriod, maxClockDrift, - height, specs, upgradePath, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, - ) - - consensusState := header.ConsensusState() - - msg, err := clienttypes.NewMsgCreateClient( - clientState, consensusState, clientCtx.GetFromAddress(), - ) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - cmd.Flags().String(flagTrustLevel, "default", "light client trust level fraction for header updates") - cmd.Flags().String(flagProofSpecs, "default", "proof specs format to be used for verification") - cmd.Flags().Bool(flagAllowUpdateAfterExpiry, false, "allow governance proposal to update client after expiry") - cmd.Flags().Bool(flagAllowUpdateAfterMisbehaviour, false, "allow governance proposal to update client after misbehaviour") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewUpdateClientCmd defines the command to update a client as defined in -// https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#update -func NewUpdateClientCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "update [client-id] [path/to/header.json]", - Short: "update existing client with a header", - Long: "update existing tendermint client with a tendermint header", - Example: fmt.Sprintf( - "$ %s tx ibc %s update [client-id] [path/to/header.json] --from node0 --home ../node0/cli --chain-id $CID", - version.AppName, types.SubModuleName, - ), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - clientID := args[0] - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - var header *types.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]) - if err != nil { - return errors.New("neither JSON input nor path to .json file were provided") - } - if err := cdc.UnmarshalJSON(contents, header); err != nil { - return errors.Wrap(err, "error unmarshalling header file") - } - } - - msg, err := clienttypes.NewMsgUpdateClient(clientID, header, clientCtx.GetFromAddress()) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewSubmitMisbehaviourCmd defines the command to submit a misbehaviour to invalidate -// previous state roots and prevent future updates as defined in -// https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#misbehaviour -func NewSubmitMisbehaviourCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "misbehaviour [path/to/misbehaviour.json]", - Short: "submit a client misbehaviour", - Long: "submit a client misbehaviour to invalidate to invalidate previous state roots and prevent future updates", - Example: fmt.Sprintf( - "$ %s tx ibc %s misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0/cli --chain-id $CID", - version.AppName, types.SubModuleName, - ), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - var m *types.Misbehaviour - if err := cdc.UnmarshalJSON([]byte(args[0]), m); err != nil { - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[0]) - if err != nil { - return errors.New("neither JSON input nor path to .json file were provided") - } - if err := cdc.UnmarshalJSON(contents, m); err != nil { - return errors.Wrap(err, "error unmarshalling misbehaviour file") - } - } - - msg, err := clienttypes.NewMsgSubmitMisbehaviour(m.ClientId, m, clientCtx.GetFromAddress()) - if err != nil { - return err - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -func parseFraction(fraction string) (types.Fraction, error) { - fr := strings.Split(fraction, "/") - if len(fr) != 2 || fr[0] == fraction { - return types.Fraction{}, fmt.Errorf("fraction must have format 'numerator/denominator' got %s", fraction) - } - - numerator, err := strconv.ParseUint(fr[0], 10, 64) - if err != nil { - return types.Fraction{}, fmt.Errorf("invalid trust-level numerator: %w", err) - } - - denominator, err := strconv.ParseUint(fr[1], 10, 64) - if err != nil { - return types.Fraction{}, fmt.Errorf("invalid trust-level denominator: %w", err) - } - - return types.Fraction{ - Numerator: numerator, - Denominator: denominator, - }, nil - -} diff --git a/x/ibc/light-clients/07-tendermint/module.go b/x/ibc/light-clients/07-tendermint/module.go index 38c7fa621b11..4c5cc2f947f4 100644 --- a/x/ibc/light-clients/07-tendermint/module.go +++ b/x/ibc/light-clients/07-tendermint/module.go @@ -1,9 +1,6 @@ package tendermint import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/client/cli" "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" ) @@ -11,8 +8,3 @@ import ( func Name() string { return types.SubModuleName } - -// GetTxCmd returns the root tx command for the IBC client -func GetTxCmd() *cobra.Command { - return cli.NewTxCmd() -}