github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/auth/client/utils/tx.go (about)

     1  package utils
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"math/big"
     9  	"os"
    10  
    11  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client"
    12  	types2 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec/types"
    13  	txmsg "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/ibc-adapter"
    14  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/tx/signing"
    15  	ibctx "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/ibc-tx"
    16  	signingtypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/ibcsigning"
    17  
    18  	"github.com/pkg/errors"
    19  	"github.com/spf13/viper"
    20  
    21  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/context"
    22  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/flags"
    23  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/input"
    24  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/keys"
    25  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    26  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    27  	authtypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/types"
    28  )
    29  
    30  // GasEstimateResponse defines a response definition for tx gas estimation.
    31  type GasEstimateResponse struct {
    32  	GasEstimate uint64 `json:"gas_estimate" yaml:"gas_estimate"`
    33  }
    34  
    35  func (gr GasEstimateResponse) String() string {
    36  	return fmt.Sprintf("gas estimate: %d", gr.GasEstimate)
    37  }
    38  
    39  // GenerateOrBroadcastMsgs creates a StdTx given a series of messages. If
    40  // the provided context has generate-only enabled, the tx will only be printed
    41  // to STDOUT in a fully offline manner. Otherwise, the tx will be signed and
    42  // broadcasted.
    43  func GenerateOrBroadcastMsgs(cliCtx context.CLIContext, txBldr authtypes.TxBuilder, msgs []sdk.Msg) error {
    44  	if cliCtx.GenerateOnly {
    45  		return PrintUnsignedStdTx(txBldr, cliCtx, msgs)
    46  	}
    47  
    48  	return CompleteAndBroadcastTxCLI(txBldr, cliCtx, msgs)
    49  }
    50  
    51  // CompleteAndBroadcastTxCLI implements a utility function that facilitates
    52  // sending a series of messages in a signed transaction given a TxBuilder and a
    53  // QueryContext. It ensures that the account exists, has a proper number and
    54  // sequence set. In addition, it builds and signs a transaction with the
    55  // supplied messages. Finally, it broadcasts the signed transaction to a node.
    56  func CompleteAndBroadcastTxCLI(txBldr authtypes.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error {
    57  	txConfig := NewPbTxConfig(cliCtx.InterfaceRegistry)
    58  	txBldr, err := PrepareTxBuilder(txBldr, cliCtx)
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	fromName := cliCtx.GetFromName()
    64  
    65  	if txBldr.SimulateAndExecute() || cliCtx.Simulate {
    66  		txBldr, err = EnrichWithGas(txBldr, cliCtx, msgs)
    67  		if err != nil {
    68  			return err
    69  		}
    70  
    71  		gasEst := GasEstimateResponse{GasEstimate: txBldr.Gas()}
    72  		_, _ = fmt.Fprintf(os.Stderr, "%s\n", gasEst.String())
    73  	}
    74  
    75  	if cliCtx.Simulate {
    76  		return nil
    77  	}
    78  	txBytes := []byte{}
    79  	pbtxMsgs, isPbTxMsg := convertIfPbTx(msgs)
    80  	if !cliCtx.SkipConfirm {
    81  		var signData interface{}
    82  		var json []byte
    83  		if isPbTxMsg {
    84  
    85  			tx, err := buildUnsignedPbTx(txBldr, txConfig, pbtxMsgs...)
    86  			if err != nil {
    87  				return err
    88  			}
    89  			json, err = txConfig.TxJSONEncoder()(tx.GetTx())
    90  			if err != nil {
    91  				panic(err)
    92  			}
    93  		} else {
    94  			signData, err = txBldr.BuildSignMsg(msgs)
    95  			if err != nil {
    96  				return err
    97  			}
    98  
    99  			if viper.GetBool(flags.FlagIndentResponse) {
   100  				json, err = cliCtx.Codec.MarshalJSONIndent(signData, "", "  ")
   101  				if err != nil {
   102  					panic(err)
   103  				}
   104  			} else {
   105  				json = cliCtx.Codec.MustMarshalJSON(signData)
   106  			}
   107  		}
   108  
   109  		_, _ = fmt.Fprintf(os.Stderr, "%s\n\n", json)
   110  
   111  		buf := bufio.NewReader(os.Stdin)
   112  		ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf)
   113  		if err != nil || !ok {
   114  			_, _ = fmt.Fprintf(os.Stderr, "%s\n", "cancelled transaction")
   115  			return err
   116  		}
   117  
   118  	}
   119  
   120  	if isPbTxMsg {
   121  		txBytes, err = PbTxBuildAndSign(cliCtx, txConfig, txBldr, keys.DefaultKeyPass, pbtxMsgs)
   122  		if err != nil {
   123  			panic(err)
   124  		}
   125  	} else {
   126  		// build and sign the transaction
   127  		txBytes, err = txBldr.BuildAndSign(fromName, keys.DefaultKeyPass, msgs)
   128  		if err != nil {
   129  			return err
   130  		}
   131  	}
   132  	// broadcast to a Tendermint node
   133  	res, err := cliCtx.BroadcastTx(txBytes)
   134  	if err != nil {
   135  		return err
   136  	}
   137  
   138  	return cliCtx.PrintOutput(res)
   139  }
   140  
   141  func buildUnsignedPbTx(txf authtypes.TxBuilder, txConfig client.TxConfig, msgs ...txmsg.Msg) (client.TxBuilder, error) {
   142  	if txf.ChainID() == "" {
   143  		return nil, fmt.Errorf("chain ID required but not specified")
   144  	}
   145  
   146  	fees := txf.Fees()
   147  
   148  	if !txf.GasPrices().IsZero() {
   149  		if !fees.IsZero() {
   150  			return nil, errors.New("cannot provide both fees and gas prices")
   151  		}
   152  
   153  		glDec := sdk.NewDec(int64(txf.Gas()))
   154  
   155  		// Derive the fees based on the provided gas prices, where
   156  		// fee = ceil(gasPrice * gasLimit).
   157  		fees = make(sdk.Coins, len(txf.GasPrices()))
   158  
   159  		for i, gp := range txf.GasPrices() {
   160  			fee := gp.Amount.Mul(glDec)
   161  			fees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt())
   162  		}
   163  	}
   164  
   165  	tx := txConfig.NewTxBuilder()
   166  
   167  	if err := tx.SetMsgs(msgs...); err != nil {
   168  		return nil, err
   169  	}
   170  	tx.SetMemo(txf.Memo())
   171  	coins := []sdk.CoinAdapter{}
   172  	for _, fee := range txf.Fees() {
   173  		prec := newCoinFromDec()
   174  
   175  		am := sdk.NewIntFromBigInt(fee.Amount.BigInt().Div(fee.Amount.BigInt(), prec))
   176  
   177  		coins = append(coins, sdk.NewCoinAdapter(fee.Denom, am))
   178  	}
   179  	tx.SetFeeAmount(coins)
   180  
   181  	tx.SetGasLimit(txf.Gas())
   182  	//tx.SetTimeoutHeight(txf.TimeoutHeight())
   183  
   184  	return tx, nil
   185  }
   186  
   187  func newCoinFromDec() *big.Int {
   188  	n := big.Int{}
   189  	prec, ok := n.SetString(sdk.DefaultDecStr, 10)
   190  	if !ok {
   191  		panic(errors.New("newCoinFromDec setstring error"))
   192  	}
   193  	return prec
   194  }
   195  
   196  func PbTxBuildAndSign(clientCtx context.CLIContext, txConfig client.TxConfig, txbld authtypes.TxBuilder, passphrase string, msgs []txmsg.Msg) ([]byte, error) {
   197  	//txb := txConfig.NewTxBuilder()
   198  	txb, err := buildUnsignedPbTx(txbld, txConfig, msgs...)
   199  	if err != nil {
   200  		return nil, err
   201  	}
   202  	if !clientCtx.SkipConfirm {
   203  		out, err := txConfig.TxJSONEncoder()(txb.GetTx())
   204  		if err != nil {
   205  			return nil, err
   206  		}
   207  
   208  		_, _ = fmt.Fprintf(os.Stderr, "%s\n\n", out)
   209  
   210  		buf := bufio.NewReader(os.Stdin)
   211  		ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf)
   212  
   213  		if err != nil || !ok {
   214  			_, _ = fmt.Fprintf(os.Stderr, "%s\n", "cancelled transaction")
   215  			return nil, err
   216  		}
   217  	}
   218  
   219  	err = signPbTx(txConfig, txbld, clientCtx.GetFromName(), passphrase, &txb, true)
   220  	if err != nil {
   221  		return nil, err
   222  	}
   223  
   224  	return txConfig.TxEncoder()(txb.GetTx())
   225  }
   226  
   227  func signPbTx(txConfig client.TxConfig, txf authtypes.TxBuilder, name string, passwd string, pbTxBld *client.TxBuilder, overwriteSig bool) error {
   228  	if txf.Keybase() == nil {
   229  		return errors.New("keybase must be set prior to signing a transaction")
   230  	}
   231  	signMode := txConfig.SignModeHandler().DefaultMode()
   232  	privKey, err := txf.Keybase().ExportPrivateKeyObject(name, passwd)
   233  	if err != nil {
   234  		return err
   235  	}
   236  
   237  	pubKeyPB := ibctx.LagacyKey2PbKey(privKey.PubKey())
   238  
   239  	signerData := signingtypes.SignerData{
   240  		ChainID:       txf.ChainID(),
   241  		AccountNumber: txf.AccountNumber(),
   242  		Sequence:      txf.Sequence(),
   243  	}
   244  
   245  	// For SIGN_MODE_DIRECT, calling SetSignatures calls setSignerInfos on
   246  	// TxBuilder under the hood, and SignerInfos is needed to generated the
   247  	// sign bytes. This is the reason for setting SetSignatures here, with a
   248  	// nil signature.
   249  	//
   250  	// Note: this line is not needed for SIGN_MODE_LEGACY_AMINO, but putting it
   251  	// also doesn't affect its generated sign bytes, so for code's simplicity
   252  	// sake, we put it here.
   253  	sigData := signing.SingleSignatureData{
   254  		SignMode:  signMode,
   255  		Signature: nil,
   256  	}
   257  
   258  	sig := signing.SignatureV2{
   259  		PubKey:   pubKeyPB,
   260  		Data:     &sigData,
   261  		Sequence: txf.Sequence(),
   262  	}
   263  	var prevSignatures []signing.SignatureV2
   264  	if !overwriteSig {
   265  		prevSignatures, err = (*pbTxBld).GetTx().GetSignaturesV2()
   266  		if err != nil {
   267  			return err
   268  		}
   269  	}
   270  	if err := (*pbTxBld).SetSignatures(sig); err != nil {
   271  		return err
   272  	}
   273  
   274  	// Generate the bytes to be signed.
   275  	bytesToSign, err := txConfig.SignModeHandler().GetSignBytes(signMode, signerData, (*pbTxBld).GetTx())
   276  	if err != nil {
   277  		return err
   278  	}
   279  
   280  	sigBytes, err := privKey.Sign(bytesToSign)
   281  	if err != nil {
   282  		panic(err)
   283  	}
   284  	sigData = signing.SingleSignatureData{
   285  		SignMode:  signMode,
   286  		Signature: sigBytes,
   287  	}
   288  	sig = signing.SignatureV2{
   289  		PubKey:   pubKeyPB,
   290  		Data:     &sigData,
   291  		Sequence: txf.Sequence(),
   292  	}
   293  
   294  	if overwriteSig {
   295  		return (*pbTxBld).SetSignatures(sig)
   296  	}
   297  	prevSignatures = append(prevSignatures, sig)
   298  
   299  	return (*pbTxBld).SetSignatures(prevSignatures...)
   300  }
   301  
   302  func convertIfPbTx(msgs []sdk.Msg) ([]txmsg.Msg, bool) {
   303  	retmsg := []txmsg.Msg{}
   304  	for _, msg := range msgs {
   305  		if m, ok := msg.(txmsg.Msg); ok {
   306  			retmsg = append(retmsg, m)
   307  		}
   308  	}
   309  
   310  	if len(retmsg) > 0 {
   311  		return retmsg, true
   312  	}
   313  	return nil, false
   314  }
   315  
   316  // EnrichWithGas calculates the gas estimate that would be consumed by the
   317  // transaction and set the transaction's respective value accordingly.
   318  func EnrichWithGas(txBldr authtypes.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (authtypes.TxBuilder, error) {
   319  	_, adjusted, err := simulateMsgs(txBldr, cliCtx, msgs)
   320  	if err != nil {
   321  		return txBldr, err
   322  	}
   323  
   324  	return txBldr.WithGas(adjusted), nil
   325  }
   326  
   327  // CalculateGas simulates the execution of a transaction and returns
   328  // the simulation response obtained by the query and the adjusted gas amount.
   329  func CalculateGas(
   330  	queryFunc func(string, []byte) ([]byte, int64, error), cdc *codec.Codec,
   331  	txBytes []byte, adjustment float64,
   332  ) (sdk.SimulationResponse, uint64, error) {
   333  
   334  	// run a simulation (via /app/simulate query) to
   335  	// estimate gas and update TxBuilder accordingly
   336  	rawRes, _, err := queryFunc("/app/simulate", txBytes)
   337  	if err != nil {
   338  		return sdk.SimulationResponse{}, 0, err
   339  	}
   340  
   341  	simRes, err := parseQueryResponse(cdc, rawRes)
   342  	if err != nil {
   343  		return sdk.SimulationResponse{}, 0, err
   344  	}
   345  
   346  	adjusted := adjustGasEstimate(simRes.GasUsed, adjustment)
   347  	return simRes, adjusted, nil
   348  }
   349  func NewPbTxConfig(reg types2.InterfaceRegistry) client.TxConfig {
   350  	marshaler := codec.NewProtoCodec(reg)
   351  	return ibctx.NewTxConfig(marshaler, ibctx.DefaultSignModes)
   352  }
   353  
   354  // PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout.
   355  func PrintUnsignedStdTx(txBldr authtypes.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error {
   356  	stdTx, err := buildUnsignedStdTxOffline(txBldr, cliCtx, msgs)
   357  	if err != nil {
   358  		return err
   359  	}
   360  
   361  	var json []byte
   362  	pbTxMsgs, isPbTxMsg := convertIfPbTx(msgs)
   363  
   364  	if isPbTxMsg {
   365  		txConfig := NewPbTxConfig(cliCtx.InterfaceRegistry)
   366  		tx, err := buildUnsignedPbTx(txBldr, txConfig, pbTxMsgs...)
   367  		if err != nil {
   368  			return err
   369  		}
   370  		json, err = txConfig.TxJSONEncoder()(tx.GetTx())
   371  		if err != nil {
   372  			return err
   373  		}
   374  	} else {
   375  		if viper.GetBool(flags.FlagIndentResponse) {
   376  			json, err = cliCtx.Codec.MarshalJSONIndent(stdTx, "", "  ")
   377  		} else {
   378  			json, err = cliCtx.Codec.MarshalJSON(stdTx)
   379  		}
   380  		if err != nil {
   381  			return err
   382  		}
   383  	}
   384  
   385  	_, _ = fmt.Fprintf(cliCtx.Output, "%s\n", json)
   386  	return nil
   387  }
   388  
   389  // SignStdTx appends a signature to a StdTx and returns a copy of it. If appendSig
   390  // is false, it replaces the signatures already attached with the new signature.
   391  // Don't perform online validation or lookups if offline is true.
   392  func SignStdTx(
   393  	txBldr authtypes.TxBuilder, cliCtx context.CLIContext, name string,
   394  	stdTx *authtypes.StdTx, appendSig bool, offline bool,
   395  ) (*authtypes.StdTx, error) {
   396  
   397  	info, err := txBldr.Keybase().Get(name)
   398  	if err != nil {
   399  		return nil, err
   400  	}
   401  
   402  	addr := info.GetPubKey().Address()
   403  
   404  	// check whether the address is a signer
   405  	if !isTxSigner(sdk.AccAddress(addr), stdTx.GetSigners()) {
   406  		return nil, fmt.Errorf("%s: %s", errInvalidSigner, name)
   407  	}
   408  
   409  	if !offline {
   410  		txBldr, err = populateAccountFromState(txBldr, cliCtx, sdk.AccAddress(addr))
   411  		if err != nil {
   412  			return nil, err
   413  		}
   414  	}
   415  
   416  	return txBldr.SignStdTx(name, keys.DefaultKeyPass, stdTx, appendSig)
   417  }
   418  
   419  // SignStdTxWithSignerAddress attaches a signature to a StdTx and returns a copy of a it.
   420  // Don't perform online validation or lookups if offline is true, else
   421  // populate account and sequence numbers from a foreign account.
   422  func SignStdTxWithSignerAddress(txBldr authtypes.TxBuilder, cliCtx context.CLIContext,
   423  	addr sdk.AccAddress, name string, stdTx *authtypes.StdTx,
   424  	offline bool) (signedStdTx *authtypes.StdTx, err error) {
   425  
   426  	// check whether the address is a signer
   427  	if !isTxSigner(addr, stdTx.GetSigners()) {
   428  		return signedStdTx, fmt.Errorf("%s: %s", errInvalidSigner, name)
   429  	}
   430  
   431  	if !offline {
   432  		txBldr, err = populateAccountFromState(txBldr, cliCtx, addr)
   433  		if err != nil {
   434  			return signedStdTx, err
   435  		}
   436  	}
   437  
   438  	return txBldr.SignStdTx(name, keys.DefaultKeyPass, stdTx, false)
   439  }
   440  
   441  // Read and decode a StdTx from the given filename.  Can pass "-" to read from stdin.
   442  func ReadStdTxFromFile(cdc *codec.Codec, filename string) (*authtypes.StdTx, error) {
   443  	var bytes []byte
   444  	var tx authtypes.StdTx
   445  	var err error
   446  
   447  	if filename == "-" {
   448  		bytes, err = ioutil.ReadAll(os.Stdin)
   449  	} else {
   450  		bytes, err = ioutil.ReadFile(filename)
   451  	}
   452  
   453  	if err != nil {
   454  		return nil, err
   455  	}
   456  
   457  	if err = cdc.UnmarshalJSON(bytes, &tx); err != nil {
   458  		return nil, err
   459  	}
   460  
   461  	return &tx, nil
   462  }
   463  
   464  func populateAccountFromState(
   465  	txBldr authtypes.TxBuilder, cliCtx context.CLIContext, addr sdk.AccAddress,
   466  ) (authtypes.TxBuilder, error) {
   467  
   468  	num, seq, err := authtypes.NewAccountRetriever(cliCtx).GetAccountNumberSequence(addr)
   469  	if err != nil {
   470  		return txBldr, err
   471  	}
   472  
   473  	return txBldr.WithAccountNumber(num).WithSequence(seq), nil
   474  }
   475  
   476  type txEncoderConfig struct {
   477  	isEthereumTx bool
   478  }
   479  
   480  type Option func(config *txEncoderConfig)
   481  
   482  func WithEthereumTx() Option {
   483  	return func(cfg *txEncoderConfig) {
   484  		cfg.isEthereumTx = true
   485  	}
   486  }
   487  
   488  // GetTxEncoder return tx encoder from global sdk configuration if ones is defined.
   489  // Otherwise returns encoder with default logic.
   490  func GetTxEncoder(cdc *codec.Codec, options ...Option) (encoder sdk.TxEncoder) {
   491  	encoder = sdk.GetConfig().GetTxEncoder()
   492  	if encoder == nil {
   493  		var cfg txEncoderConfig
   494  		for _, op := range options {
   495  			op(&cfg)
   496  		}
   497  		if cfg.isEthereumTx {
   498  			encoder = authtypes.EthereumTxEncoder(cdc)
   499  		} else {
   500  			encoder = authtypes.DefaultTxEncoder(cdc)
   501  		}
   502  	}
   503  
   504  	return
   505  }
   506  
   507  // simulateMsgs simulates the transaction and returns the simulation response and
   508  // the adjusted gas value.
   509  func simulateMsgs(txBldr authtypes.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (sdk.SimulationResponse, uint64, error) {
   510  	txBytes, err := txBldr.BuildTxForSim(msgs)
   511  	if err != nil {
   512  		return sdk.SimulationResponse{}, 0, err
   513  	}
   514  
   515  	return CalculateGas(cliCtx.QueryWithData, cliCtx.Codec, txBytes, txBldr.GasAdjustment())
   516  }
   517  
   518  func adjustGasEstimate(estimate uint64, adjustment float64) uint64 {
   519  	return uint64(adjustment * float64(estimate))
   520  }
   521  
   522  func parseQueryResponse(cdc *codec.Codec, rawRes []byte) (sdk.SimulationResponse, error) {
   523  	var simRes sdk.SimulationResponse
   524  	if err := cdc.UnmarshalBinaryBare(rawRes, &simRes); err != nil {
   525  		return sdk.SimulationResponse{}, err
   526  	}
   527  
   528  	return simRes, nil
   529  }
   530  
   531  // PrepareTxBuilder populates a TxBuilder in preparation for the build of a Tx.
   532  func PrepareTxBuilder(txBldr authtypes.TxBuilder, cliCtx context.CLIContext) (authtypes.TxBuilder, error) {
   533  	from := cliCtx.GetFromAddress()
   534  
   535  	accGetter := authtypes.NewAccountRetriever(cliCtx)
   536  	if err := accGetter.EnsureExists(from); err != nil {
   537  		return txBldr, err
   538  	}
   539  
   540  	txbldrAccNum, txbldrAccSeq := txBldr.AccountNumber(), txBldr.Sequence()
   541  	// TODO: (ref #1903) Allow for user supplied account number without
   542  	// automatically doing a manual lookup.
   543  	if txbldrAccNum == 0 || txbldrAccSeq == 0 {
   544  		num, seq, err := authtypes.NewAccountRetriever(cliCtx).GetAccountNumberSequence(from)
   545  		if err != nil {
   546  			return txBldr, err
   547  		}
   548  
   549  		if txbldrAccNum == 0 {
   550  			txBldr = txBldr.WithAccountNumber(num)
   551  		}
   552  		if txbldrAccSeq == 0 {
   553  			txBldr = txBldr.WithSequence(seq)
   554  		}
   555  	}
   556  
   557  	return txBldr, nil
   558  }
   559  
   560  func buildUnsignedStdTxOffline(txBldr authtypes.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx *authtypes.StdTx, err error) {
   561  	if txBldr.SimulateAndExecute() {
   562  		if cliCtx.GenerateOnly {
   563  			return stdTx, errors.New("cannot estimate gas with generate-only")
   564  		}
   565  
   566  		txBldr, err = EnrichWithGas(txBldr, cliCtx, msgs)
   567  		if err != nil {
   568  			return stdTx, err
   569  		}
   570  
   571  		_, _ = fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.Gas())
   572  	}
   573  
   574  	stdSignMsg, err := txBldr.BuildSignMsg(msgs)
   575  	if err != nil {
   576  		return stdTx, err
   577  	}
   578  
   579  	return authtypes.NewStdTx(stdSignMsg.Msgs, stdSignMsg.Fee, nil, stdSignMsg.Memo), nil
   580  }
   581  
   582  func isTxSigner(user sdk.AccAddress, signers []sdk.AccAddress) bool {
   583  	for _, s := range signers {
   584  		if bytes.Equal(user.Bytes(), s.Bytes()) {
   585  			return true
   586  		}
   587  	}
   588  
   589  	return false
   590  }
   591  
   592  func CliConvertCoinToCoinAdapters(coins sdk.Coins) sdk.CoinAdapters {
   593  	ret := make(sdk.CoinAdapters, 0)
   594  	for _, v := range coins {
   595  		ret = append(ret, CliConvertCoinToCoinAdapter(v))
   596  	}
   597  	return ret
   598  }
   599  
   600  func CliConvertCoinToCoinAdapter(coin sdk.Coin) sdk.CoinAdapter {
   601  	prec := newCoinFromDec()
   602  
   603  	am := sdk.NewIntFromBigInt(coin.Amount.BigInt().Div(coin.Amount.BigInt(), prec))
   604  
   605  	return sdk.NewCoinAdapter(coin.Denom, am)
   606  }