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
This commit is contained in:
parent
2e8f5e52bd
commit
0df0626604
|
@ -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()),
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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/<app>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/<app>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/<app>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/<app>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
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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(),
|
||||
)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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/<app>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/<app>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/<app>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)
|
||||
},
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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/<app>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/<app>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/<app>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
|
||||
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue