feat: add cli for tips transactions (#10311)
<!-- The default pull request template is for types feat, fix, or refactor. For other templates, add one of the following parameters to the url: - template=docs.md - template=other.md --> ## Description Closes: #10264 This PR makes 2 changes in the CLI: ### 1. Add an `--aux` flag to all tx command. ```bash simd tx bank send <from> <to> <amount> --aux (optional: --tip <tipAmt> --tipper <tipper>) ``` This will print an AuxSignerData instead of broadcasting the tx. ### 2. Add a new `aux-to-fee` subcommand ```bash simd tx aux-to-fee <aux_signer_data.json> ``` This takes the output of the previous command, and broadcasts a 2-signer tx. <!-- Add a description of the changes that this PR introduces and the files that are the most critical to review. --> --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
This commit is contained in:
parent
779c7e2e17
commit
5f840be76a
|
@ -53,7 +53,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
* [\#10208](https://github.com/cosmos/cosmos-sdk/pull/10208) Add `TipsTxMiddleware` for transferring tips.
|
||||
* [\#10379](https://github.com/cosmos/cosmos-sdk/pull/10379) Add validation to `x/upgrade` CLI `software-upgrade` command `--plan-info` value.
|
||||
* [\#10561](https://github.com/cosmos/cosmos-sdk/pull/10561) Add configurable IAVL cache size to app.toml
|
||||
* [\10507](https://github.com/cosmos/cosmos-sdk/pull/10507) Add middleware for tx priority.
|
||||
* [\#10507](https://github.com/cosmos/cosmos-sdk/pull/10507) Add middleware for tx priority.
|
||||
* [\#10311](https://github.com/cosmos/cosmos-sdk/pull/10311) Adds cli to use tips transactions. It adds an `--aux` flag to all CLI tx commands to generate the aux signer data (with optional tip), and a new `tx aux-to-fee` subcommand to let the fee payer gather aux signer data and broadcast the tx
|
||||
|
||||
### Improvements
|
||||
|
||||
|
|
|
@ -264,6 +264,24 @@ func readTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, err
|
|||
}
|
||||
}
|
||||
|
||||
if !clientCtx.IsAux || flagSet.Changed(flags.FlagAux) {
|
||||
isAux, _ := flagSet.GetBool(flags.FlagAux)
|
||||
clientCtx = clientCtx.WithAux(isAux)
|
||||
if isAux {
|
||||
// If the user didn't explicity set an --output flag, use JSON by
|
||||
// default.
|
||||
if clientCtx.OutputFormat == "" || !flagSet.Changed(cli.OutputFlag) {
|
||||
clientCtx = clientCtx.WithOutputFormat("json")
|
||||
}
|
||||
|
||||
// If the user didn't explicity set a --sign-mode flag, use
|
||||
// DIRECT_AUX by default.
|
||||
if clientCtx.SignModeStr == "" || !flagSet.Changed(flags.FlagSignMode) {
|
||||
clientCtx = clientCtx.WithSignModeStr(flags.SignModeDirectAux)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clientCtx, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,9 @@ type Context struct {
|
|||
FeePayer sdk.AccAddress
|
||||
FeeGranter sdk.AccAddress
|
||||
Viper *viper.Viper
|
||||
|
||||
// IsAux is true when the signer is an auxiliary signer (e.g. the tipper).
|
||||
IsAux bool
|
||||
|
||||
// TODO: Deprecated (remove).
|
||||
LegacyAmino *codec.LegacyAmino
|
||||
|
@ -245,6 +248,12 @@ func (ctx Context) WithViper(prefix string) Context {
|
|||
return ctx
|
||||
}
|
||||
|
||||
// WithAux returns a copy of the context with an updated IsAux value.
|
||||
func (ctx Context) WithAux(isAux bool) Context {
|
||||
ctx.IsAux = isAux
|
||||
return ctx
|
||||
}
|
||||
|
||||
// PrintString prints the raw string to ctx.Output if it's defined, otherwise to os.Stdout
|
||||
func (ctx Context) PrintString(str string) error {
|
||||
return ctx.PrintBytes([]byte(str))
|
||||
|
|
|
@ -35,6 +35,8 @@ const (
|
|||
SignModeDirect = "direct"
|
||||
// SignModeLegacyAminoJSON is the value of the --sign-mode flag for SIGN_MODE_LEGACY_AMINO_JSON
|
||||
SignModeLegacyAminoJSON = "amino-json"
|
||||
// SignModeDirectAux is the value of the --sign-mode flag for SIGN_MODE_DIRECT_AUX
|
||||
SignModeDirectAux = "direct-aux"
|
||||
)
|
||||
|
||||
// List of CLI flags
|
||||
|
@ -73,6 +75,9 @@ const (
|
|||
FlagFeePayer = "fee-payer"
|
||||
FlagFeeGranter = "fee-granter"
|
||||
FlagReverse = "reverse"
|
||||
FlagTip = "tip"
|
||||
FlagAux = "aux"
|
||||
FlagTipper = "tipper"
|
||||
|
||||
// Tendermint logging flags
|
||||
FlagLogLevel = "log_level"
|
||||
|
@ -111,10 +116,13 @@ func AddTxFlagsToCmd(cmd *cobra.Command) {
|
|||
cmd.Flags().Bool(FlagOffline, false, "Offline mode (does not allow any online functionality)")
|
||||
cmd.Flags().BoolP(FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation")
|
||||
cmd.Flags().String(FlagKeyringBackend, DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test|memory)")
|
||||
cmd.Flags().String(FlagSignMode, "", "Choose sign mode (direct|amino-json), this is an advanced feature")
|
||||
cmd.Flags().String(FlagSignMode, "", "Choose sign mode (direct|amino-json|direct-aux), this is an advanced feature")
|
||||
cmd.Flags().Uint64(FlagTimeoutHeight, 0, "Set a block timeout height to prevent the tx from being committed past a certain height")
|
||||
cmd.Flags().String(FlagFeePayer, "", "Fee payer pays fees for the transaction instead of deducting from the signer")
|
||||
cmd.Flags().String(FlagFeeGranter, "", "Fee granter grants fees for the transaction")
|
||||
cmd.Flags().String(FlagTip, "", "Tip is the amount that is going to be transferred to the fee payer on the target chain. This flag is only valid when used with --aux")
|
||||
cmd.Flags().String(FlagTipper, "", "Tipper will pay for tips for executing the tx on the target chain. This flag is only valid when used with --aux")
|
||||
cmd.Flags().Bool(FlagAux, false, "Generate aux signer data instead of sending a tx")
|
||||
|
||||
// --gas can accept integers and "auto"
|
||||
cmd.Flags().String(FlagGas, "", fmt.Sprintf("gas limit to set per-transaction; set to %q to calculate sufficient gas automatically (default %d)", GasFlagAuto, DefaultGasLimit))
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
)
|
||||
|
||||
|
@ -29,6 +30,7 @@ type Factory struct {
|
|||
chainID string
|
||||
memo string
|
||||
fees sdk.Coins
|
||||
tip *tx.Tip
|
||||
gasPrices sdk.DecCoins
|
||||
signMode signing.SignMode
|
||||
simulateAndExecute bool
|
||||
|
@ -44,6 +46,8 @@ func NewFactoryCLI(clientCtx client.Context, flagSet *pflag.FlagSet) Factory {
|
|||
signMode = signing.SignMode_SIGN_MODE_DIRECT
|
||||
case flags.SignModeLegacyAminoJSON:
|
||||
signMode = signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON
|
||||
case flags.SignModeDirectAux:
|
||||
signMode = signing.SignMode_SIGN_MODE_DIRECT_AUX
|
||||
}
|
||||
|
||||
accNum, _ := flagSet.GetUint64(flags.FlagAccountNumber)
|
||||
|
@ -73,6 +77,10 @@ func NewFactoryCLI(clientCtx client.Context, flagSet *pflag.FlagSet) Factory {
|
|||
feesStr, _ := flagSet.GetString(flags.FlagFees)
|
||||
f = f.WithFees(feesStr)
|
||||
|
||||
tipsStr, _ := flagSet.GetString(flags.FlagTip)
|
||||
tipper, _ := flagSet.GetString(flags.FlagTipper)
|
||||
f = f.WithTips(tipsStr, tipper)
|
||||
|
||||
gasPricesStr, _ := flagSet.GetString(flags.FlagGasPrices)
|
||||
f = f.WithGasPrices(gasPricesStr)
|
||||
|
||||
|
@ -130,6 +138,20 @@ func (f Factory) WithFees(fees string) Factory {
|
|||
return f
|
||||
}
|
||||
|
||||
// WithTips returns a copy of the Factory with an updated tip.
|
||||
func (f Factory) WithTips(tip string, tipper string) Factory {
|
||||
parsedTips, err := sdk.ParseCoinsNormalized(tip)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
f.tip = &tx.Tip{
|
||||
Tipper: tipper,
|
||||
Amount: parsedTips,
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// WithGasPrices returns a copy of the Factory with updated gas prices.
|
||||
func (f Factory) WithGasPrices(gasPrices string) Factory {
|
||||
parsedGasPrices, err := sdk.ParseDecCoins(gasPrices)
|
||||
|
@ -254,12 +276,12 @@ func (f Factory) PrintUnsignedTx(clientCtx client.Context, msgs ...sdk.Msg) erro
|
|||
_, _ = fmt.Fprintf(os.Stderr, "%s\n", GasEstimateResponse{GasEstimate: f.Gas()})
|
||||
}
|
||||
|
||||
tx, err := f.BuildUnsignedTx(msgs...)
|
||||
unsignedTx, err := f.BuildUnsignedTx(msgs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
json, err := clientCtx.TxConfig.TxJSONEncoder()(tx.GetTx())
|
||||
json, err := clientCtx.TxConfig.TxJSONEncoder()(unsignedTx.GetTx())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
// or sign it and broadcast it returning an error upon failure.
|
||||
func GenerateOrBroadcastTxCLI(clientCtx client.Context, flagSet *pflag.FlagSet, msgs ...sdk.Msg) error {
|
||||
txf := NewFactoryCLI(clientCtx, flagSet)
|
||||
|
||||
return GenerateOrBroadcastTxWithFactory(clientCtx, txf, msgs...)
|
||||
}
|
||||
|
||||
|
@ -40,6 +41,16 @@ func GenerateOrBroadcastTxWithFactory(clientCtx client.Context, txf Factory, msg
|
|||
}
|
||||
}
|
||||
|
||||
// If the --aux flag is set, we simply generate and print the AuxSignerData.
|
||||
if clientCtx.IsAux {
|
||||
auxSignerData, err := makeAuxSignerData(clientCtx, txf, msgs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(&auxSignerData)
|
||||
}
|
||||
|
||||
if clientCtx.GenerateOnly {
|
||||
return txf.PrintUnsignedTx(clientCtx, msgs...)
|
||||
}
|
||||
|
@ -335,3 +346,75 @@ type GasEstimateResponse struct {
|
|||
func (gr GasEstimateResponse) String() string {
|
||||
return fmt.Sprintf("gas estimate: %d", gr.GasEstimate)
|
||||
}
|
||||
|
||||
// makeAuxSignerData generates an AuxSignerData from the client inputs.
|
||||
func makeAuxSignerData(clientCtx client.Context, f Factory, msgs ...sdk.Msg) (tx.AuxSignerData, error) {
|
||||
b := NewAuxTxBuilder()
|
||||
fromAddress, name, _, err := client.GetFromFields(clientCtx.Keyring, clientCtx.From, false)
|
||||
if err != nil {
|
||||
return tx.AuxSignerData{}, err
|
||||
}
|
||||
|
||||
b.SetAddress(fromAddress.String())
|
||||
if clientCtx.Offline {
|
||||
b.SetAccountNumber(f.accountNumber)
|
||||
b.SetSequence(f.sequence)
|
||||
} else {
|
||||
accNum, seq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, fromAddress)
|
||||
if err != nil {
|
||||
return tx.AuxSignerData{}, err
|
||||
}
|
||||
b.SetAccountNumber(accNum)
|
||||
b.SetSequence(seq)
|
||||
}
|
||||
|
||||
err = b.SetMsgs(msgs...)
|
||||
if err != nil {
|
||||
return tx.AuxSignerData{}, err
|
||||
}
|
||||
|
||||
if f.tip != nil {
|
||||
if f.tip.Tipper == "" {
|
||||
return tx.AuxSignerData{}, sdkerrors.Wrap(errors.New("tipper flag required"), "tipper")
|
||||
} else {
|
||||
if _, err := sdk.AccAddressFromBech32(f.tip.Tipper); err != nil {
|
||||
return tx.AuxSignerData{}, sdkerrors.ErrInvalidAddress.Wrap("tipper must be a bech32 address")
|
||||
}
|
||||
b.SetTip(f.tip)
|
||||
}
|
||||
}
|
||||
|
||||
err = b.SetSignMode(f.SignMode())
|
||||
if err != nil {
|
||||
return tx.AuxSignerData{}, err
|
||||
}
|
||||
|
||||
key, err := clientCtx.Keyring.Key(name)
|
||||
if err != nil {
|
||||
return tx.AuxSignerData{}, err
|
||||
}
|
||||
|
||||
pub, err := key.GetPubKey()
|
||||
if err != nil {
|
||||
return tx.AuxSignerData{}, err
|
||||
}
|
||||
|
||||
err = b.SetPubKey(pub)
|
||||
if err != nil {
|
||||
return tx.AuxSignerData{}, err
|
||||
}
|
||||
|
||||
b.SetChainID(clientCtx.ChainID)
|
||||
signBz, err := b.GetSignBytes()
|
||||
if err != nil {
|
||||
return tx.AuxSignerData{}, err
|
||||
}
|
||||
|
||||
sig, _, err := clientCtx.Keyring.Sign(name, signBz)
|
||||
if err != nil {
|
||||
return tx.AuxSignerData{}, err
|
||||
}
|
||||
b.SetSignature(sig)
|
||||
|
||||
return b.GetAuxSignerData()
|
||||
}
|
||||
|
|
|
@ -224,6 +224,7 @@ func TestSign(t *testing.T) {
|
|||
{"direct: should overwrite multi-signers tx with DIRECT sig",
|
||||
txfDirect, txb2, from1, true, []cryptotypes.PubKey{pubKey1}, nil},
|
||||
}
|
||||
|
||||
var prevSigs []signingtypes.SignatureV2
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
|
|
@ -41,10 +41,10 @@ type (
|
|||
SetSignatures(signatures ...signingtypes.SignatureV2) error
|
||||
SetMemo(memo string)
|
||||
SetFeeAmount(amount sdk.Coins)
|
||||
SetFeePayer(feePayer sdk.AccAddress)
|
||||
SetGasLimit(limit uint64)
|
||||
SetTip(tip *tx.Tip)
|
||||
SetTimeoutHeight(height uint64)
|
||||
SetFeePayer(feePayer sdk.AccAddress)
|
||||
SetFeeGranter(feeGranter sdk.AccAddress)
|
||||
AddAuxSignerData(tx.AuxSignerData) error
|
||||
}
|
||||
|
|
|
@ -215,6 +215,7 @@ func txCommand() *cobra.Command {
|
|||
authcmd.GetBroadcastCommand(),
|
||||
authcmd.GetEncodeCommand(),
|
||||
authcmd.GetDecodeCommand(),
|
||||
authcmd.GetAuxToFeeCommand(),
|
||||
)
|
||||
|
||||
simapp.ModuleBasics.AddTxCommands(cmd)
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clienttx "github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
)
|
||||
|
||||
func GetAuxToFeeCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "aux-to-fee <aux_signed_tx.json>",
|
||||
Short: "includes the aux signer data in the tx, broadcast the tx, and sends the tip amount to the broadcaster",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx, err := client.GetClientTxContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
auxSignerData := tx.AuxSignerData{}
|
||||
err = readAuxSignerData(clientCtx.Codec, &auxSignerData, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f := clienttx.NewFactoryCLI(clientCtx, cmd.Flags())
|
||||
|
||||
txBuilder := clientCtx.TxConfig.NewTxBuilder()
|
||||
err = txBuilder.AddAuxSignerData(auxSignerData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBuilder.SetFeePayer(clientCtx.FromAddress)
|
||||
txBuilder.SetFeeAmount(f.Fees())
|
||||
txBuilder.SetGasLimit(f.Gas())
|
||||
|
||||
if clientCtx.GenerateOnly {
|
||||
json, err := clientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
|
||||
}
|
||||
|
||||
err = authclient.SignTx(f, clientCtx, clientCtx.FromName, txBuilder, clientCtx.Offline, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txBytes, err := clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// broadcast to a Tendermint node
|
||||
res, err := clientCtx.BroadcastTx(txBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res)
|
||||
},
|
||||
}
|
||||
|
||||
flags.AddTxFlagsToCmd(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func readAuxSignerData(cdc codec.Codec, auxSignerData *tx.AuxSignerData, filename string) error {
|
||||
bytes, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return cdc.UnmarshalJSON(bytes, auxSignerData)
|
||||
}
|
|
@ -106,4 +106,13 @@ func TxMultiSignBatchExec(clientCtx client.Context, filename string, from string
|
|||
return clitestutil.ExecTestCLICmd(clientCtx, cli.GetMultiSignBatchCmd(), args)
|
||||
}
|
||||
|
||||
// TxAuxToFeeExec executes `GetAuxToFeeCommand` cli command with given args.
|
||||
func TxAuxToFeeExec(clientCtx client.Context, filename string, extraArgs ...string) (testutil.BufferWriter, error) {
|
||||
args := []string{
|
||||
filename,
|
||||
}
|
||||
|
||||
return clitestutil.ExecTestCLICmd(clientCtx, cli.GetAuxToFeeCommand(), append(args, extraArgs...))
|
||||
}
|
||||
|
||||
// DONTCOVER
|
||||
|
|
|
@ -34,6 +34,8 @@ import (
|
|||
bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
govtestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
)
|
||||
|
||||
type IntegrationTestSuite struct {
|
||||
|
@ -898,6 +900,7 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
|
|||
s.Require().NoError(err)
|
||||
intialCoins := balRes.Balances
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
// Send coins from validator to multisig.
|
||||
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
|
||||
_, err = s.createBankMsg(
|
||||
|
@ -986,10 +989,12 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
|||
|
||||
// Send coins from validator to multisig.
|
||||
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
_, err = s.createBankMsg(
|
||||
val1, addr,
|
||||
sdk.NewCoins(sendTokens),
|
||||
)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
|
@ -999,7 +1004,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
|
|||
var balRes banktypes.QueryAllBalancesResponse
|
||||
err = val1.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(sendTokens.Amount, balRes.Balances.AmountOf(s.cfg.BondDenom))
|
||||
s.Require().True(sendTokens.Amount.Equal(balRes.Balances.AmountOf(s.cfg.BondDenom)))
|
||||
|
||||
// Generate multisig transaction.
|
||||
multiGeneratedTx, err := bankcli.MsgSendExec(
|
||||
|
@ -1117,7 +1122,6 @@ func (s *IntegrationTestSuite) TestSignBatchMultisig() {
|
|||
file2 := testutil.WriteToNewTempFile(s.T(), res.String())
|
||||
_, err = TxMultiSignExec(val.ClientCtx, multisigRecord.Name, filename.Name(), file1.Name(), file2.Name())
|
||||
s.Require().NoError(err)
|
||||
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestMultisignBatch() {
|
||||
|
@ -1460,6 +1464,333 @@ func (s *IntegrationTestSuite) TestSignWithMultiSignersAminoJSON() {
|
|||
require.Equal(sdk.NewCoins(val0Coin, val1Coin), queryRes.Balances)
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestAuxSigner() {
|
||||
require := s.Require()
|
||||
val := s.network.Validators[0]
|
||||
val0Coin := sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10))
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
"error with SIGN_MODE_DIRECT_AUX and --aux unset",
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirectAux),
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"no error with SIGN_MDOE_DIRECT_AUX mode and generate-only set (ignores generate-only)",
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirectAux),
|
||||
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"no error with SIGN_MDOE_DIRECT_AUX mode and generate-only, tip flag set",
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirectAux),
|
||||
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTip, val0Coin.String()),
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
s.Run(tc.name, func() {
|
||||
_, err := govtestutil.MsgSubmitProposal(
|
||||
val.ClientCtx,
|
||||
val.Address.String(),
|
||||
"test",
|
||||
"test desc",
|
||||
govtypes.ProposalTypeText,
|
||||
tc.args...,
|
||||
)
|
||||
if tc.expectErr {
|
||||
require.Error(err)
|
||||
} else {
|
||||
require.NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) TestAuxToFee() {
|
||||
require := s.Require()
|
||||
val := s.network.Validators[0]
|
||||
|
||||
kb := s.network.Validators[0].ClientCtx.Keyring
|
||||
acc, _, err := kb.NewMnemonic("tipperAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
||||
require.NoError(err)
|
||||
|
||||
tipper, err := acc.GetAddress()
|
||||
require.NoError(err)
|
||||
tipperInitialBal := sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10000))
|
||||
|
||||
feePayer := val.Address
|
||||
fee := sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(1000))
|
||||
tip := sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(1000))
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
_, err = s.createBankMsg(val, tipper, sdk.NewCoins(tipperInitialBal))
|
||||
require.NoError(err)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
bal := s.getBalances(val.ClientCtx, tipper, tip.Denom)
|
||||
s.Require().True(bal.Equal(tipperInitialBal.Amount))
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
tipper sdk.AccAddress
|
||||
feePayer sdk.AccAddress
|
||||
tip sdk.Coin
|
||||
expectErrAux bool
|
||||
expectErrBroadCast bool
|
||||
errMsg string
|
||||
tipperArgs []string
|
||||
feePayerArgs []string
|
||||
}{
|
||||
{
|
||||
name: "when --aux and --sign-mode = direct set: error",
|
||||
tipper: tipper,
|
||||
feePayer: feePayer,
|
||||
tip: tip,
|
||||
tipperArgs: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirect),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTip, tip),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTipper, tipper.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagAux),
|
||||
},
|
||||
expectErrAux: true,
|
||||
feePayerArgs: []string{
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, feePayer),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fee.String()),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "when --aux and --sign-mode = direct set: error",
|
||||
tipper: tipper,
|
||||
feePayer: feePayer,
|
||||
tip: tip,
|
||||
tipperArgs: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirect),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTip, tip),
|
||||
fmt.Sprintf("--%s=true", flags.FlagAux),
|
||||
},
|
||||
expectErrAux: true,
|
||||
feePayerArgs: []string{
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, feePayer),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fee.String()),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "both tipper, fee payer uses AMINO: no error",
|
||||
tipper: tipper,
|
||||
feePayer: feePayer,
|
||||
tip: tip,
|
||||
tipperArgs: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTip, tip),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTipper, tipper.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagAux),
|
||||
},
|
||||
feePayerArgs: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, feePayer),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fee.String()),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "tipper uses DIRECT_AUX, fee payer uses AMINO: no error",
|
||||
tipper: tipper,
|
||||
feePayer: feePayer,
|
||||
tip: tip,
|
||||
tipperArgs: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirectAux),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTip, tip),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTipper, tipper.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagAux),
|
||||
},
|
||||
feePayerArgs: []string{
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, feePayer),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fee.String()),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "--tip flag unset: no error",
|
||||
tipper: tipper,
|
||||
feePayer: feePayer,
|
||||
tip: sdk.Coin{Denom: fmt.Sprintf("%stoken", val.Moniker), Amount: sdk.NewInt(0)},
|
||||
tipperArgs: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirectAux),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTipper, tipper.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagAux),
|
||||
},
|
||||
feePayerArgs: []string{
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, feePayer),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fee.String()),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "legacy amino json: no error",
|
||||
tipper: tipper,
|
||||
feePayer: feePayer,
|
||||
tip: tip,
|
||||
tipperArgs: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTip, tip),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTipper, tipper.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagAux),
|
||||
},
|
||||
feePayerArgs: []string{
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, feePayer),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fee.String()),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "tipper uses direct aux, fee payer uses direct: happy case",
|
||||
tipper: tipper,
|
||||
feePayer: feePayer,
|
||||
tip: tip,
|
||||
tipperArgs: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirectAux),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTip, tip),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTipper, tipper.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagAux),
|
||||
},
|
||||
feePayerArgs: []string{
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, feePayer),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fee.String()),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "wrong tipper address: error",
|
||||
tipper: tipper,
|
||||
feePayer: feePayer,
|
||||
tip: tip,
|
||||
tipperArgs: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirectAux),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTip, tip),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTipper, "foobar"),
|
||||
fmt.Sprintf("--%s=true", flags.FlagAux),
|
||||
},
|
||||
expectErrAux: true,
|
||||
feePayerArgs: []string{
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, feePayer),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fee.String()),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "wrong denom in tip: error",
|
||||
tipper: tipper,
|
||||
feePayer: feePayer,
|
||||
tip: sdk.Coin{Denom: fmt.Sprintf("%stoken", val.Moniker), Amount: sdk.NewInt(0)},
|
||||
tipperArgs: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTip, "1000wrongDenom"),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirectAux),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTipper, tipper.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagAux),
|
||||
},
|
||||
feePayerArgs: []string{
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirect),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, feePayer),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fee.String()),
|
||||
},
|
||||
errMsg: "insufficient funds",
|
||||
},
|
||||
{
|
||||
name: "insufficient fees: error",
|
||||
tipper: tipper,
|
||||
feePayer: feePayer,
|
||||
tip: sdk.Coin{Denom: fmt.Sprintf("%stoken", val.Moniker), Amount: sdk.NewInt(0)},
|
||||
tipperArgs: []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTip, tip),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirectAux),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagTipper, tipper.String()),
|
||||
fmt.Sprintf("--%s=true", flags.FlagAux),
|
||||
},
|
||||
feePayerArgs: []string{
|
||||
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeDirect),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, feePayer),
|
||||
},
|
||||
errMsg: "insufficient fees",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
s.Run(tc.name, func() {
|
||||
res, err := govtestutil.MsgSubmitProposal(
|
||||
val.ClientCtx,
|
||||
tipper.String(),
|
||||
"test",
|
||||
"test desc",
|
||||
govtypes.ProposalTypeText,
|
||||
tc.tipperArgs...,
|
||||
)
|
||||
|
||||
if tc.expectErrAux {
|
||||
require.Error(err)
|
||||
} else {
|
||||
require.NoError(err)
|
||||
genTxFile := testutil.WriteToNewTempFile(s.T(), string(res.Bytes()))
|
||||
|
||||
// broadcast the tx
|
||||
res, err = TxAuxToFeeExec(
|
||||
val.ClientCtx,
|
||||
genTxFile.Name(),
|
||||
tc.feePayerArgs...,
|
||||
)
|
||||
|
||||
var txRes sdk.TxResponse
|
||||
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &txRes))
|
||||
|
||||
if tc.expectErrBroadCast {
|
||||
require.Error(err)
|
||||
} else if tc.errMsg != "" {
|
||||
require.Contains(txRes.RawLog, tc.errMsg)
|
||||
} else {
|
||||
require.NoError(err)
|
||||
|
||||
s.Require().Equal(uint32(0), txRes.Code)
|
||||
s.Require().NotNil(int64(0), txRes.Height)
|
||||
|
||||
bal = s.getBalances(val.ClientCtx, tipper, tc.tip.Denom)
|
||||
tipperInitialBal = tipperInitialBal.Sub(tc.tip)
|
||||
s.Require().True(bal.Equal(tipperInitialBal.Amount))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) createBankMsg(val *network.Validator, toAddr sdk.AccAddress, amount sdk.Coins, extraFlags ...string) (testutil.BufferWriter, error) {
|
||||
flags := []string{fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
||||
|
@ -1470,3 +1801,14 @@ func (s *IntegrationTestSuite) createBankMsg(val *network.Validator, toAddr sdk.
|
|||
flags = append(flags, extraFlags...)
|
||||
return bankcli.MsgSendExec(val.ClientCtx, val.Address, toAddr, amount, flags...)
|
||||
}
|
||||
|
||||
func (s *IntegrationTestSuite) getBalances(clientCtx client.Context, addr sdk.AccAddress, denom string) sdk.Int {
|
||||
resp, err := bankcli.QueryBalancesExec(clientCtx, addr)
|
||||
s.Require().NoError(err)
|
||||
|
||||
var balRes banktypes.QueryAllBalancesResponse
|
||||
err = clientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes)
|
||||
s.Require().NoError(err)
|
||||
startTokens := balRes.Balances.AmountOf(denom)
|
||||
return startTokens
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
)
|
||||
|
||||
|
@ -107,28 +106,28 @@ func (tx StdTx) GetMsgs() []sdk.Msg { return tx.Msgs }
|
|||
|
||||
// ValidateBasic does a simple and lightweight validation check that doesn't
|
||||
// require access to any other information.
|
||||
func (tx StdTx) ValidateBasic() error {
|
||||
stdSigs := tx.GetSignatures()
|
||||
func (stdTx StdTx) ValidateBasic() error {
|
||||
stdSigs := stdTx.GetSignatures()
|
||||
|
||||
if tx.Fee.Gas > txtypes.MaxGasWanted {
|
||||
if stdTx.Fee.Gas > tx.MaxGasWanted {
|
||||
return sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInvalidRequest,
|
||||
"invalid gas supplied; %d > %d", tx.Fee.Gas, txtypes.MaxGasWanted,
|
||||
"invalid gas supplied; %d > %d", stdTx.Fee.Gas, tx.MaxGasWanted,
|
||||
)
|
||||
}
|
||||
if tx.Fee.Amount.IsAnyNegative() {
|
||||
if stdTx.Fee.Amount.IsAnyNegative() {
|
||||
return sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInsufficientFee,
|
||||
"invalid fee provided: %s", tx.Fee.Amount,
|
||||
"invalid fee provided: %s", stdTx.Fee.Amount,
|
||||
)
|
||||
}
|
||||
if len(stdSigs) == 0 {
|
||||
return sdkerrors.ErrNoSignatures
|
||||
}
|
||||
if len(stdSigs) != len(tx.GetSigners()) {
|
||||
if len(stdSigs) != len(stdTx.GetSigners()) {
|
||||
return sdkerrors.Wrapf(
|
||||
sdkerrors.ErrUnauthorized,
|
||||
"wrong number of signers; expected %d, got %d", len(tx.GetSigners()), len(stdSigs),
|
||||
"wrong number of signers; expected %d, got %d", len(stdTx.GetSigners()), len(stdSigs),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -255,7 +254,7 @@ func TestSignatureV2Conversions(t *testing.T) {
|
|||
pubKey, pubKey2,
|
||||
})
|
||||
dummy2 := []byte("dummySig2")
|
||||
bitArray := types.NewCompactBitArray(2)
|
||||
bitArray := cryptotypes.NewCompactBitArray(2)
|
||||
bitArray.SetIndex(0, true)
|
||||
bitArray.SetIndex(1, true)
|
||||
msigData := &signing.MultiSignatureData{
|
||||
|
|
|
@ -17,7 +17,7 @@ type SigVerifiableTx interface {
|
|||
}
|
||||
|
||||
// Tx defines a transaction interface that supports all standard message, signature
|
||||
// fee, memo, and auxiliary interfaces.
|
||||
// fee, memo, tips, and auxiliary interfaces.
|
||||
type Tx interface {
|
||||
SigVerifiableTx
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ type wrapper struct {
|
|||
var (
|
||||
_ authsigning.Tx = &wrapper{}
|
||||
_ client.TxBuilder = &wrapper{}
|
||||
_ tx.TipTx = &wrapper{}
|
||||
_ middleware.HasExtensionOptionsTx = &wrapper{}
|
||||
_ ExtensionOptionsTxBuilder = &wrapper{}
|
||||
_ tx.TipTx = &wrapper{}
|
||||
|
|
|
@ -10,8 +10,8 @@ import (
|
|||
// DefaultSignModes are the default sign modes enabled for protobuf transactions.
|
||||
var DefaultSignModes = []signingtypes.SignMode{
|
||||
signingtypes.SignMode_SIGN_MODE_DIRECT,
|
||||
signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||
signingtypes.SignMode_SIGN_MODE_DIRECT_AUX,
|
||||
signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||
}
|
||||
|
||||
// makeSignModeHandler returns the default protobuf SignModeHandler supporting
|
||||
|
|
Loading…
Reference in New Issue