github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/02-client/client/cli/tx.go (about)

     1  package cli
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"strings"
     8  
     9  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/context"
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/flags"
    11  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    12  	interfacetypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec/types"
    13  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    14  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/version"
    15  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
    16  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/client/utils"
    17  	govcli "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/gov/client/cli"
    18  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
    19  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported"
    20  	tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/proto/types"
    21  	govtypes "github.com/fibonacci-chain/fbc/x/gov/types"
    22  	"github.com/pkg/errors"
    23  	"github.com/spf13/cobra"
    24  )
    25  
    26  // NewCreateClientCmd defines the command to create a new IBC light client.
    27  func NewCreateClientCmd(m *codec.CodecProxy, reg interfacetypes.InterfaceRegistry) *cobra.Command {
    28  	cmd := &cobra.Command{
    29  		Use:   "create [path/to/client_state.json] [path/to/consensus_state.json]",
    30  		Short: "create new IBC client",
    31  		Long: `create a new IBC client with the specified client state and consensus state
    32  	- 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}
    33  	- ConsensusState JSON example: {"@type":"/ibc.lightclients.solomachine.v1.ConsensusState","public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"}`,
    34  		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.ServerName, types.SubModuleName),
    35  		Args:    cobra.ExactArgs(2),
    36  		RunE: func(cmd *cobra.Command, args []string) error {
    37  			cdc := m.GetProtocMarshal()
    38  			inBuf := bufio.NewReader(cmd.InOrStdin())
    39  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(m.GetCdc()))
    40  			clientCtx := context.NewCLIContext().WithInterfaceRegistry(reg)
    41  
    42  			// attempt to unmarshal client state argument
    43  			var clientState exported.ClientState
    44  			clientContentOrFileName := args[0]
    45  			if err := cdc.UnmarshalInterfaceJSON([]byte(clientContentOrFileName), &clientState); err != nil {
    46  
    47  				// check for file path if JSON input is not provided
    48  				contents, err := ioutil.ReadFile(clientContentOrFileName)
    49  				if err != nil {
    50  					return errors.Wrap(err, "neither JSON input nor path to .json file for client state were provided")
    51  				}
    52  
    53  				if err := cdc.UnmarshalInterfaceJSON(contents, &clientState); err != nil {
    54  					return errors.Wrap(err, "error unmarshalling client state file")
    55  				}
    56  			}
    57  
    58  			// attempt to unmarshal consensus state argument
    59  			var consensusState exported.ConsensusState
    60  			consensusContentOrFileName := args[1]
    61  			if err := cdc.UnmarshalInterfaceJSON([]byte(consensusContentOrFileName), &consensusState); err != nil {
    62  
    63  				// check for file path if JSON input is not provided
    64  				contents, err := ioutil.ReadFile(consensusContentOrFileName)
    65  				if err != nil {
    66  					return errors.Wrap(err, "neither JSON input nor path to .json file for consensus state were provided")
    67  				}
    68  
    69  				if err := cdc.UnmarshalInterfaceJSON(contents, &consensusState); err != nil {
    70  					return errors.Wrap(err, "error unmarshalling consensus state file")
    71  				}
    72  			}
    73  
    74  			msg, err := types.NewMsgCreateClient(clientState, consensusState, clientCtx.GetFromAddress())
    75  			if err != nil {
    76  				return err
    77  			}
    78  
    79  			return utils.GenerateOrBroadcastMsgs(clientCtx, txBldr, []sdk.Msg{msg})
    80  		},
    81  	}
    82  
    83  	flags.AddTxFlagsToCmd(cmd)
    84  
    85  	return cmd
    86  }
    87  
    88  // NewUpdateClientCmd defines the command to update an IBC client.
    89  func NewUpdateClientCmd(m *codec.CodecProxy, reg interfacetypes.InterfaceRegistry) *cobra.Command {
    90  	cmd := &cobra.Command{
    91  		Use:     "update [client-id] [path/to/header.json]",
    92  		Short:   "update existing client with a header",
    93  		Long:    "update existing client with a header",
    94  		Example: fmt.Sprintf("%s tx ibc %s update [client-id] [path/to/header.json] --from node0 --home ../node0/<app>cli --chain-id $CID", version.ServerName, types.SubModuleName),
    95  		Args:    cobra.ExactArgs(2),
    96  		RunE: func(cmd *cobra.Command, args []string) error {
    97  			cdc := m.GetProtocMarshal()
    98  			inBuf := bufio.NewReader(cmd.InOrStdin())
    99  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(m.GetCdc()))
   100  			clientCtx := context.NewCLIContext().WithInterfaceRegistry(reg)
   101  
   102  			clientID := args[0]
   103  
   104  			var header exported.Header
   105  			headerContentOrFileName := args[1]
   106  			if err := cdc.UnmarshalInterfaceJSON([]byte(headerContentOrFileName), &header); err != nil {
   107  
   108  				// check for file path if JSON input is not provided
   109  				contents, err := ioutil.ReadFile(headerContentOrFileName)
   110  				if err != nil {
   111  					return errors.Wrap(err, "neither JSON input nor path to .json file for header were provided")
   112  				}
   113  
   114  				if err := cdc.UnmarshalInterfaceJSON(contents, &header); err != nil {
   115  					return errors.Wrap(err, "error unmarshalling header file")
   116  				}
   117  			}
   118  
   119  			msg, err := types.NewMsgUpdateClient(clientID, header, clientCtx.GetFromAddress())
   120  			if err != nil {
   121  				return err
   122  			}
   123  
   124  			return utils.GenerateOrBroadcastMsgs(clientCtx, txBldr, []sdk.Msg{msg})
   125  		},
   126  	}
   127  	flags.AddTxFlagsToCmd(cmd)
   128  	return cmd
   129  }
   130  
   131  // NewSubmitMisbehaviourCmd defines the command to submit a misbehaviour to prevent
   132  // future updates.
   133  func NewSubmitMisbehaviourCmd(m *codec.CodecProxy, reg interfacetypes.InterfaceRegistry) *cobra.Command {
   134  	cmd := &cobra.Command{
   135  		Use:     "misbehaviour [path/to/misbehaviour.json]",
   136  		Short:   "submit a client misbehaviour",
   137  		Long:    "submit a client misbehaviour to prevent future updates",
   138  		Example: fmt.Sprintf("%s tx ibc %s misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0/<app>cli --chain-id $CID", version.ServerName, types.SubModuleName),
   139  		Args:    cobra.ExactArgs(1),
   140  		RunE: func(cmd *cobra.Command, args []string) error {
   141  			cdc := m.GetProtocMarshal()
   142  			inBuf := bufio.NewReader(cmd.InOrStdin())
   143  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(m.GetCdc()))
   144  			clientCtx := context.NewCLIContext().WithInterfaceRegistry(reg)
   145  
   146  			var misbehaviour exported.Misbehaviour
   147  			misbehaviourContentOrFileName := args[0]
   148  			if err := cdc.UnmarshalInterfaceJSON([]byte(replaceMisbehaviourStr(misbehaviourContentOrFileName)), &misbehaviour); err != nil {
   149  
   150  				// check for file path if JSON input is not provided
   151  				contents, err := ioutil.ReadFile(misbehaviourContentOrFileName)
   152  				if err != nil {
   153  					return errors.Wrap(err, "neither JSON input nor path to .json file for misbehaviour were provided")
   154  				}
   155  
   156  				contents = []byte(replaceMisbehaviourStr(string(contents)))
   157  				if err := cdc.UnmarshalInterfaceJSON(contents, &misbehaviour); err != nil {
   158  					return errors.Wrap(err, "error unmarshalling misbehaviour file")
   159  				}
   160  			}
   161  
   162  			msg, err := types.NewMsgSubmitMisbehaviour(misbehaviour.GetClientID(), misbehaviour, clientCtx.GetFromAddress())
   163  			if err != nil {
   164  				return err
   165  			}
   166  
   167  			return utils.GenerateOrBroadcastMsgs(clientCtx, txBldr, []sdk.Msg{msg})
   168  		},
   169  	}
   170  	flags.AddTxFlagsToCmd(cmd)
   171  
   172  	return cmd
   173  }
   174  
   175  // convert cm40+ to cm39
   176  func replaceMisbehaviourStr(contents string) string {
   177  	str := strings.ReplaceAll(string(contents), "part_set_header", "parts_header")
   178  	for k, v := range tmtypes.BlockIDFlag_value {
   179  		before := fmt.Sprintf(`"block_id_flag": "%s"`, k)
   180  		after := fmt.Sprintf(`"block_id_flag": %d`, v)
   181  		str = strings.ReplaceAll(str, before, after)
   182  	}
   183  	return str
   184  }
   185  
   186  // NewUpgradeClientCmd defines the command to upgrade an IBC light client.
   187  func NewUpgradeClientCmd(m *codec.CodecProxy, reg interfacetypes.InterfaceRegistry) *cobra.Command {
   188  	cmd := &cobra.Command{
   189  		Use:   "upgrade [client-identifier] [path/to/client_state.json] [path/to/consensus_state.json] [upgrade-client-proof] [upgrade-consensus-state-proof]",
   190  		Short: "upgrade an IBC client",
   191  		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
   192  	- 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}
   193  	- ConsensusState JSON example: {"@type":"/ibc.lightclients.solomachine.v1.ConsensusState","public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"}`,
   194  		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.ServerName, types.SubModuleName),
   195  		Args:    cobra.ExactArgs(5),
   196  		RunE: func(cmd *cobra.Command, args []string) error {
   197  			cdc := m.GetProtocMarshal()
   198  			inBuf := bufio.NewReader(cmd.InOrStdin())
   199  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(m.GetCdc()))
   200  			clientCtx := context.NewCLIContext().WithInterfaceRegistry(reg)
   201  
   202  			clientID := args[0]
   203  
   204  			// attempt to unmarshal client state argument
   205  			var clientState exported.ClientState
   206  			clientContentOrFileName := args[1]
   207  			if err := cdc.UnmarshalInterfaceJSON([]byte(clientContentOrFileName), &clientState); err != nil {
   208  
   209  				// check for file path if JSON input is not provided
   210  				contents, err := ioutil.ReadFile(clientContentOrFileName)
   211  				if err != nil {
   212  					return errors.Wrap(err, "neither JSON input nor path to .json file for client state were provided")
   213  				}
   214  
   215  				if err := cdc.UnmarshalInterfaceJSON(contents, &clientState); err != nil {
   216  					return errors.Wrap(err, "error unmarshalling client state file")
   217  				}
   218  			}
   219  
   220  			// attempt to unmarshal consensus state argument
   221  			var consensusState exported.ConsensusState
   222  			consensusContentOrFileName := args[2]
   223  			if err := cdc.UnmarshalInterfaceJSON([]byte(consensusContentOrFileName), &consensusState); err != nil {
   224  
   225  				// check for file path if JSON input is not provided
   226  				contents, err := ioutil.ReadFile(consensusContentOrFileName)
   227  				if err != nil {
   228  					return errors.Wrap(err, "neither JSON input nor path to .json file for consensus state were provided")
   229  				}
   230  
   231  				if err := cdc.UnmarshalInterfaceJSON(contents, &consensusState); err != nil {
   232  					return errors.Wrap(err, "error unmarshalling consensus state file")
   233  				}
   234  			}
   235  
   236  			proofUpgradeClient := []byte(args[3])
   237  			proofUpgradeConsensus := []byte(args[4])
   238  
   239  			msg, err := types.NewMsgUpgradeClient(clientID, clientState, consensusState, proofUpgradeClient, proofUpgradeConsensus, clientCtx.GetFromAddress())
   240  			if err != nil {
   241  				return err
   242  			}
   243  
   244  			return utils.GenerateOrBroadcastMsgs(clientCtx, txBldr, []sdk.Msg{msg})
   245  		},
   246  	}
   247  
   248  	flags.AddTxFlagsToCmd(cmd)
   249  
   250  	return cmd
   251  }
   252  
   253  // NewCmdSubmitUpdateClientProposal implements a command handler for submitting an update IBC client proposal transaction.
   254  func NewCmdSubmitUpdateClientProposal(m *codec.CodecProxy, reg interfacetypes.InterfaceRegistry) *cobra.Command {
   255  	cmd := &cobra.Command{
   256  		Use:   "update-client [subject-client-id] [substitute-client-id]",
   257  		Args:  cobra.ExactArgs(2),
   258  		Short: "Submit an update IBC client proposal",
   259  		Long: "Submit an update IBC client proposal along with an initial deposit.\n" +
   260  			"Please specify a subject client identifier you want to update..\n" +
   261  			"Please specify the substitute client the subject client will be updated to.",
   262  		RunE: func(cmd *cobra.Command, args []string) error {
   263  			inBuf := bufio.NewReader(cmd.InOrStdin())
   264  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(m.GetCdc()))
   265  			clientCtx := context.NewCLIContext().WithCodec(m.GetCdc())
   266  
   267  			title, err := cmd.Flags().GetString(govcli.FlagTitle)
   268  			if err != nil {
   269  				return err
   270  			}
   271  
   272  			description, err := cmd.Flags().GetString(govcli.FlagDescription)
   273  			if err != nil {
   274  				return err
   275  			}
   276  
   277  			subjectClientID := args[0]
   278  			substituteClientID := args[1]
   279  
   280  			content := types.NewClientUpdateProposal(title, description, subjectClientID, substituteClientID)
   281  
   282  			from := clientCtx.GetFromAddress()
   283  
   284  			depositStr, err := cmd.Flags().GetString(govcli.FlagDeposit)
   285  			if err != nil {
   286  				return err
   287  			}
   288  			deposit, err := sdk.ParseCoinsNormalized(depositStr)
   289  			if err != nil {
   290  				return err
   291  			}
   292  
   293  			msg := govtypes.NewMsgSubmitProposal(content, deposit, from)
   294  
   295  			if err = msg.ValidateBasic(); err != nil {
   296  				return err
   297  			}
   298  
   299  			return utils.GenerateOrBroadcastMsgs(clientCtx, txBldr, []sdk.Msg{msg})
   300  		},
   301  	}
   302  
   303  	cmd.Flags().String(govcli.FlagTitle, "", "title of proposal")
   304  	cmd.Flags().String(govcli.FlagDescription, "", "description of proposal")
   305  	cmd.Flags().String(govcli.FlagDeposit, "", "deposit of proposal")
   306  
   307  	return cmd
   308  }