From cfc80d26253011ceb08756991391d2f6e3e1ba37 Mon Sep 17 00:00:00 2001 From: atheesh Date: Mon, 25 Sep 2023 12:36:53 +0530 Subject: [PATCH 01/20] feat(x/bank): autocli tx support --- testutil/cli/cmd.go | 31 +++++++++++- x/authz/keeper/keeper_test.go | 4 ++ x/bank/autocli.go | 14 ++++++ x/bank/client/cli/tx.go | 88 +++++++++++++++++------------------ x/bank/client/cli/tx_test.go | 85 --------------------------------- x/crisis/autocli.go | 8 +++- 6 files changed, 97 insertions(+), 133 deletions(-) diff --git a/testutil/cli/cmd.go b/testutil/cli/cmd.go index 57b5b11ee6e5..e26cbdc12df1 100644 --- a/testutil/cli/cmd.go +++ b/testutil/cli/cmd.go @@ -8,9 +8,14 @@ import ( "cosmossdk.io/core/address" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/testutil" - "github.com/cosmos/cosmos-sdk/x/bank/client/cli" + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/bank" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) // ExecTestCLICmd builds the client context, mocks the output and executes the command. @@ -34,5 +39,27 @@ func MsgSendExec(clientCtx client.Context, from, to, amount fmt.Stringer, ac add args := []string{from.String(), to.String(), amount.String()} args = append(args, extraArgs...) - return ExecTestCLICmd(clientCtx, cli.NewSendTxCmd(ac), args) + coins, err := sdk.ParseCoinsNormalized(amount.String()) + if err != nil { + return nil, err + } + + cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}).Codec + router := baseapp.NewMsgServiceRouter() + + router.SetInterfaceRegistry(cdc.InterfaceRegistry()) + + msgSend := banktypes.MsgSend{ + FromAddress: from.String(), + ToAddress: to.String(), + Amount: coins, + } + + // router.RegisterService(router, banktypes.MsgServer{}) + handler := router.Handler(&msgSend) + + fmt.Printf("handler: %v\n", handler) + + return nil, nil + // return ExecTestCLICmd(clientCtx, cli.NewSendTxCmd(ac), args) } diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index 5dc8ac76c93f..f043154df50f 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + "fmt" "testing" "time" @@ -60,7 +61,10 @@ func (s *TestSuite) SetupTest() { s.encCfg.TxConfig.TxDecoder(), ) s.baseApp.SetCMS(testCtx.CMS) + fmt.Printf("s.baseApp.MsgServiceRouter()1: %v\n", s.baseApp.MsgServiceRouter()) s.baseApp.SetInterfaceRegistry(s.encCfg.InterfaceRegistry) + fmt.Printf("s.encCfg.InterfaceRegistry: %v\n", s.encCfg.InterfaceRegistry) + fmt.Printf("s.baseApp.MsgServiceRouter()2: %v\n", s.baseApp.MsgServiceRouter()) s.addrs = simtestutil.CreateIncrementalAccounts(7) diff --git a/x/bank/autocli.go b/x/bank/autocli.go index 25d65feecb97..2c92ef5b99dd 100644 --- a/x/bank/autocli.go +++ b/x/bank/autocli.go @@ -87,5 +87,19 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { }, }, }, + Tx: &autocliv1.ServiceCommandDescriptor{ + Service: bankv1beta1.Msg_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Send", + Use: "send [from_key_or_address] [to_address] [amount]", + Short: "Send funds from one account to another.", + Long: `Send funds from one account to another. +Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. +When using '--dry-run' a key name cannot be used, only a bech32 address.`, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "invariant_module_name"}, {ProtoField: "invariant_route"}}, + }, + }, + }, } } diff --git a/x/bank/client/cli/tx.go b/x/bank/client/cli/tx.go index 11beeabd137e..289ffea4db75 100644 --- a/x/bank/client/cli/tx.go +++ b/x/bank/client/cli/tx.go @@ -29,56 +29,56 @@ func NewTxCmd(ac address.Codec) *cobra.Command { } txCmd.AddCommand( - NewSendTxCmd(ac), + // NewSendTxCmd(ac), NewMultiSendTxCmd(ac), ) return txCmd } -// NewSendTxCmd returns a CLI command handler for creating a MsgSend transaction. -func NewSendTxCmd(ac address.Codec) *cobra.Command { - cmd := &cobra.Command{ - Use: "send [from_key_or_address] [to_address] [amount]", - Short: "Send funds from one account to another.", - Long: `Send funds from one account to another. -Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. -When using '--dry-run' a key name cannot be used, only a bech32 address. -`, - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) error { - err := cmd.Flags().Set(flags.FlagFrom, args[0]) - if err != nil { - return err - } - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - toAddr, err := ac.StringToBytes(args[1]) - if err != nil { - return err - } - - coins, err := sdk.ParseCoinsNormalized(args[2]) - if err != nil { - return err - } - - if len(coins) == 0 { - return fmt.Errorf("invalid coins") - } - - msg := types.NewMsgSend(clientCtx.GetFromAddress(), toAddr, coins) - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} +// // NewSendTxCmd returns a CLI command handler for creating a MsgSend transaction. +// func NewSendTxCmd(ac address.Codec) *cobra.Command { +// cmd := &cobra.Command{ +// Use: "send [from_key_or_address] [to_address] [amount]", +// Short: "Send funds from one account to another.", +// Long: `Send funds from one account to another. +// Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. +// When using '--dry-run' a key name cannot be used, only a bech32 address. +// `, +// Args: cobra.ExactArgs(3), +// RunE: func(cmd *cobra.Command, args []string) error { +// err := cmd.Flags().Set(flags.FlagFrom, args[0]) +// if err != nil { +// return err +// } +// clientCtx, err := client.GetClientTxContext(cmd) +// if err != nil { +// return err +// } +// toAddr, err := ac.StringToBytes(args[1]) +// if err != nil { +// return err +// } + +// coins, err := sdk.ParseCoinsNormalized(args[2]) +// if err != nil { +// return err +// } + +// if len(coins) == 0 { +// return fmt.Errorf("invalid coins") +// } + +// msg := types.NewMsgSend(clientCtx.GetFromAddress(), toAddr, coins) + +// return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) +// }, +// } + +// flags.AddTxFlagsToCmd(cmd) + +// return cmd +// } // NewMultiSendTxCmd returns a CLI command handler for creating a MsgMultiSend transaction. // For a better UX this command is limited to send funds from one account to two or more accounts. diff --git a/x/bank/client/cli/tx_test.go b/x/bank/client/cli/tx_test.go index 197093aa788a..e3f4e418ea01 100644 --- a/x/bank/client/cli/tx_test.go +++ b/x/bank/client/cli/tx_test.go @@ -51,91 +51,6 @@ func (s *CLITestSuite) SetupSuite() { WithConsensusAddressCodec(addresscodec.NewBech32Codec("cosmosvalcons")) } -func (s *CLITestSuite) TestSendTxCmd() { - accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - cmd := cli.NewSendTxCmd(addresscodec.NewBech32Codec("cosmos")) - cmd.SetOutput(io.Discard) - - extraArgs := []string{ - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("photon", sdkmath.NewInt(10))).String()), - fmt.Sprintf("--%s=test-chain", flags.FlagChainID), - } - - testCases := []struct { - name string - ctxGen func() client.Context - from, to sdk.AccAddress - amount sdk.Coins - extraArgs []string - expectErrMsg string - }{ - { - "valid transaction", - func() client.Context { - return s.baseCtx - }, - accounts[0].Address, - accounts[0].Address, - sdk.NewCoins( - sdk.NewCoin("stake", sdkmath.NewInt(10)), - sdk.NewCoin("photon", sdkmath.NewInt(40)), - ), - extraArgs, - "", - }, - { - "invalid to Address", - func() client.Context { - return s.baseCtx - }, - accounts[0].Address, - sdk.AccAddress{}, - sdk.NewCoins( - sdk.NewCoin("stake", sdkmath.NewInt(10)), - sdk.NewCoin("photon", sdkmath.NewInt(40)), - ), - extraArgs, - "empty address string is not allowed", - }, - { - "invalid coins", - func() client.Context { - return s.baseCtx - }, - accounts[0].Address, - accounts[0].Address, - nil, - extraArgs, - "invalid coins", - }, - } - - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - args := append([]string{tc.from.String(), tc.to.String(), tc.amount.String()}, tc.extraArgs...) - - ctx := svrcmd.CreateExecuteContext(context.Background()) - cmd.SetContext(ctx) - cmd.SetArgs(args) - s.Require().NoError(client.SetCmdClientContextHandler(tc.ctxGen(), cmd)) - - out, err := clitestutil.ExecTestCLICmd(tc.ctxGen(), cmd, args) - if tc.expectErrMsg != "" { - s.Require().Error(err) - s.Require().Contains(out.String(), tc.expectErrMsg) - } else { - s.Require().NoError(err) - msg := &sdk.TxResponse{} - s.Require().NoError(tc.ctxGen().Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) - } - }) - } -} - func (s *CLITestSuite) TestMultiSendTxCmd() { accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 3) diff --git a/x/crisis/autocli.go b/x/crisis/autocli.go index 2a979f63cfc8..a99fd4c713b5 100644 --- a/x/crisis/autocli.go +++ b/x/crisis/autocli.go @@ -9,13 +9,17 @@ import ( func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { return &autocliv1.ModuleOptions{ Tx: &autocliv1.ServiceCommandDescriptor{ - Service: crisisv1beta1.Msg_ServiceDesc.ServiceName, + Service: crisisv1beta1.Msg_ServiceDesc.ServiceName, + EnhanceCustomCommand: true, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { RpcMethod: "VerifyInvariant", Use: "invariant-broken [module-name] [invariant-route]", Short: "Submit proof that an invariant broken to halt the chain", - PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "invariant_module_name"}, {ProtoField: "invariant_route"}}, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to"}, {ProtoField: "amount"}}, + FlagOptions: map[string]*autocliv1.FlagOptions{ + "sender": {Name: "from", Shorthand: "f", Usage: "Address of the sender"}, + }, }, }, }, From f52a56291ae7d352a5492ad0f14d071c6017384c Mon Sep 17 00:00:00 2001 From: atheesh Date: Mon, 25 Sep 2023 12:37:50 +0530 Subject: [PATCH 02/20] remove comment --- testutil/cli/cmd.go | 1 - 1 file changed, 1 deletion(-) diff --git a/testutil/cli/cmd.go b/testutil/cli/cmd.go index e26cbdc12df1..ff0f0fe683d6 100644 --- a/testutil/cli/cmd.go +++ b/testutil/cli/cmd.go @@ -55,7 +55,6 @@ func MsgSendExec(clientCtx client.Context, from, to, amount fmt.Stringer, ac add Amount: coins, } - // router.RegisterService(router, banktypes.MsgServer{}) handler := router.Handler(&msgSend) fmt.Printf("handler: %v\n", handler) From 893615fab840f4c83922d5606e6298f6aa771703 Mon Sep 17 00:00:00 2001 From: atheesh Date: Mon, 25 Sep 2023 18:54:51 +0530 Subject: [PATCH 03/20] changes --- testutil/cli/cmd.go | 62 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/testutil/cli/cmd.go b/testutil/cli/cmd.go index ff0f0fe683d6..d2b1e58aed92 100644 --- a/testutil/cli/cmd.go +++ b/testutil/cli/cmd.go @@ -8,13 +8,12 @@ import ( "cosmossdk.io/core/address" - "github.com/cosmos/cosmos-sdk/baseapp" + sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" - moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/bank" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -44,21 +43,60 @@ func MsgSendExec(clientCtx client.Context, from, to, amount fmt.Stringer, ac add return nil, err } - cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}).Codec - router := baseapp.NewMsgServiceRouter() - - router.SetInterfaceRegistry(cdc.InterfaceRegistry()) - + txBuilder := clientCtx.TxConfig.NewTxBuilder() msgSend := banktypes.MsgSend{ FromAddress: from.String(), ToAddress: to.String(), Amount: coins, } - handler := router.Handler(&msgSend) + fee := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(0))) + txBuilder.SetFeeAmount(fee) // Arbitrary fee + txBuilder.SetGasLimit(1000000) // Need at least 100386 + + err = txBuilder.SetMsgs(&msgSend) + if err != nil { + return nil, err + } + + txFactory := tx.Factory{} + txFactory = txFactory. + WithChainID(clientCtx.ChainID). + WithKeybase(clientCtx.Keyring). + WithTxConfig(clientCtx.TxConfig) + + accBytes, err := clientCtx.AddressCodec.StringToBytes(from.String()) + if err != nil { + return nil, err + } + + keyRecord, err := clientCtx.Keyring.KeyByAddress(accBytes) + if err != nil { + return nil, err + } + + err = tx.Sign(context.Background(), txFactory, keyRecord.Name, txBuilder, true) + if err != nil { + return nil, err + } + + txBz, err := clientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) + if err != nil { + return nil, err + } + + fmt.Println("txBz", string(txBz)) + + req := &txtypes.BroadcastTxRequest{ + TxBytes: txBz, + Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC, + } + + serviceClient := txtypes.NewServiceClient(clientCtx) + resp, err := serviceClient.BroadcastTx(context.Background(), req) - fmt.Printf("handler: %v\n", handler) + fmt.Println("Resp", resp, err) + // return resp, err return nil, nil - // return ExecTestCLICmd(clientCtx, cli.NewSendTxCmd(ac), args) } From 04c3c4a645d490d6c17ed20e2acf20e357739f3b Mon Sep 17 00:00:00 2001 From: atheesh Date: Wed, 27 Sep 2023 14:17:40 +0530 Subject: [PATCH 04/20] refactor --- tests/e2e/auth/suite.go | 302 +++++++++++++++++++++------------- tests/e2e/authz/tx.go | 93 ++++++----- testutil/cli/cmd.go | 161 +++++++++++++++++- testutil/network/network.go | 14 ++ x/authz/client/cli/tx_test.go | 79 ++++----- x/group/client/cli/tx_test.go | 20 ++- 6 files changed, 469 insertions(+), 200 deletions(-) diff --git a/tests/e2e/auth/suite.go b/tests/e2e/auth/suite.go index a8e4a64c4511..b02015e4c0ee 100644 --- a/tests/e2e/auth/suite.go +++ b/tests/e2e/auth/suite.go @@ -16,7 +16,6 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" - addresscodec "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" @@ -31,7 +30,6 @@ import ( authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli" authclitestutil "github.com/cosmos/cosmos-sdk/x/auth/client/testutil" authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil" - bank "github.com/cosmos/cosmos-sdk/x/bank/client/cli" 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" @@ -99,15 +97,20 @@ func (s *E2ETestSuite) TestCLISignGenOnly() { s.Require().NoError(err) sendTokens := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(10))) - args := []string{ - keyName, // from keyname - val2.Address.String(), - sendTokens.String(), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), // shouldn't break if we use keyname with --generate-only flag - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + msgSend := &banktypes.MsgSend{ + FromAddress: val.Address.String(), + ToAddress: val2.Address.String(), + Amount: sendTokens, } - generatedStd, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.NewSendTxCmd(addresscodec.NewBech32Codec("cosmos")), args) + + generatedStd, err := clitestutil.SubmitTestTx( + val, + msgSend, + val.Address, + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, + ) s.Require().NoError(err) opFile := testutil.WriteToNewTempFile(s.T(), generatedStd.String()) defer opFile.Close() @@ -208,11 +211,16 @@ func (s *E2ETestSuite) TestCLISignBatch() { sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10)), ) - generatedStd, err := s.createBankMsg(val, val.Address, - sendTokens, fmt.Sprintf("--%s=true", flags.FlagGenerateOnly)) + generatedStd, err := s.createBankMsg( + val, + val.Address, + sendTokens, clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, + ) s.Require().NoError(err) - outputFile := testutil.WriteToNewTempFile(s.T(), strings.Repeat(generatedStd.String(), 3)) + outputFile := testutil.WriteToNewTempFile(s.T(), strings.Repeat(generatedStd.String()+"\n", 3)) defer outputFile.Close() val.ClientCtx.HomeDir = strings.Replace(val.ClientCtx.HomeDir, "simd", "simcli", 1) @@ -244,7 +252,7 @@ func (s *E2ETestSuite) TestCLISignBatch() { s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n"))) // Sign batch malformed tx file. - malformedFile := testutil.WriteToNewTempFile(s.T(), fmt.Sprintf("%smalformed", generatedStd)) + malformedFile := testutil.WriteToNewTempFile(s.T(), fmt.Sprintf("malformed%s", generatedStd)) defer malformedFile.Close() _, err = authclitestutil.TxSignBatchExec(val.ClientCtx, val.Address, malformedFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID)) s.Require().Error(err) @@ -268,6 +276,9 @@ func (s *E2ETestSuite) TestCLISignBatch() { val, addr, sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 1000)), + clitestutil.SubmitTestTxConfig{ + GenOnly: false, + }, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -300,15 +311,19 @@ func (s *E2ETestSuite) TestCLIQueryTxCmdByHash() { s.Require().NoError(err) // Send coins. - out, err := s.createBankMsg( - val, addr, + res, err := s.createBankMsg( + val, + addr, sdk.NewCoins(sendTokens), + clitestutil.SubmitTestTxConfig{ + GenOnly: false, + }, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) - var txRes sdk.TxResponse - s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes)) + var txRes tx.BroadcastTxResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &txRes)) testCases := []struct { name string @@ -333,7 +348,7 @@ func (s *E2ETestSuite) TestCLIQueryTxCmdByHash() { }, { "happy case", - []string{txRes.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}, + []string{txRes.TxResponse.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}, false, sdk.MsgTypeURL(&banktypes.MsgSend{}), }, @@ -380,21 +395,27 @@ func (s *E2ETestSuite) TestCLIQueryTxCmdByEvents() { s.Require().NoError(err) // Send coins. - out, err := s.createBankMsg( - val, addr2, + res, err := s.createBankMsg( + val, + addr2, sdk.NewCoins(sendTokens), + clitestutil.SubmitTestTxConfig{ + GenOnly: false, + }, ) s.Require().NoError(err) - var txRes sdk.TxResponse - s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes)) + var bankTxRes tx.BroadcastTxResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &bankTxRes)) s.Require().NoError(s.network.WaitForNextBlock()) + var out testutil.BufferWriter // Query the tx by hash to get the inner tx. err = s.network.RetryForBlocks(func() error { - out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, authcli.QueryTxCmd(), []string{txRes.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}) + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, authcli.QueryTxCmd(), []string{bankTxRes.TxResponse.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}) return err }, 3) s.Require().NoError(err) + var txRes sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes)) protoTx := txRes.GetTx().(*tx.Tx) @@ -500,22 +521,27 @@ func (s *E2ETestSuite) TestCLIQueryTxsCmdByEvents() { addr2, err := account2.GetAddress() s.Require().NoError(err) // Send coins. - out, err := s.createBankMsg( + res, err := s.createBankMsg( val, addr2, sdk.NewCoins(sendTokens), + clitestutil.SubmitTestTxConfig{ + GenOnly: false, + }, ) s.Require().NoError(err) - var txRes sdk.TxResponse - s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes)) + var sendTxRes tx.BroadcastTxResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &sendTxRes)) s.Require().NoError(s.network.WaitForNextBlock()) + var out testutil.BufferWriter // Query the tx by hash to get the inner tx. err = s.network.RetryForBlocks(func() error { - out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, authcli.QueryTxCmd(), []string{txRes.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}) + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, authcli.QueryTxCmd(), []string{sendTxRes.TxResponse.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}) return err }, 3) s.Require().NoError(err) + var txRes sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes)) testCases := []struct { @@ -579,8 +605,14 @@ func (s *E2ETestSuite) TestCLISendGenerateSignAndBroadcast() { addr, err := account.GetAddress() s.Require().NoError(err) - normalGeneratedTx, err := s.createBankMsg(val1, addr, - sdk.NewCoins(sendTokens), fmt.Sprintf("--%s=true", flags.FlagGenerateOnly)) + normalGeneratedTx, err := s.createBankMsg( + val1, + addr, + sdk.NewCoins(sendTokens), + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, + ) s.Require().NoError(err) txCfg := val1.ClientCtx.TxConfig @@ -597,8 +629,10 @@ func (s *E2ETestSuite) TestCLISendGenerateSignAndBroadcast() { // Test generate sendTx with --gas=$amount limitedGasGeneratedTx, err := s.createBankMsg(val1, addr, - sdk.NewCoins(sendTokens), fmt.Sprintf("--gas=%d", 100), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + sdk.NewCoins(sendTokens), clitestutil.SubmitTestTxConfig{ + GenOnly: true, + Gas: 100, + }, ) s.Require().NoError(err) @@ -621,9 +655,13 @@ func (s *E2ETestSuite) TestCLISendGenerateSignAndBroadcast() { startTokens := balRes.Balances.AmountOf(s.cfg.BondDenom) // Test generate sendTx, estimate gas - finalGeneratedTx, err := s.createBankMsg(val1, addr, - sdk.NewCoins(sendTokens), fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly)) + finalGeneratedTx, err := s.createBankMsg( + val1, + addr, + sdk.NewCoins(sendTokens), clitestutil.SubmitTestTxConfig{ + GenOnly: true, + Gas: flags.DefaultGasLimit, + }) s.Require().NoError(err) finalStdTx, err := txCfg.TxJSONDecoder()(finalGeneratedTx.Bytes()) @@ -736,23 +774,28 @@ func (s *E2ETestSuite) TestCLIMultisignInsufficientCosigners() { sdk.NewCoins( sdk.NewInt64Coin(s.cfg.BondDenom, 10), ), + clitestutil.SubmitTestTxConfig{ + GenOnly: false, + }, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) + coins := sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 5)) + msgSend := &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: val1.Address.String(), + Amount: coins, + } + // Generate multisig transaction. - multiGeneratedTx, err := clitestutil.MsgSendExec( - val1.ClientCtx, + multiGeneratedTx, err := clitestutil.SubmitTestTx( + val1, + msgSend, addr, - val1.Address, - sdk.NewCoins( - sdk.NewInt64Coin(s.cfg.BondDenom, 5), - ), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, ) s.Require().NoError(err) @@ -789,8 +832,10 @@ func (s *E2ETestSuite) TestCLIEncode() { normalGeneratedTx, err := s.createBankMsg( val1, val1.Address, sdk.NewCoins(sendTokens), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), - fmt.Sprintf("--%s=deadbeef", flags.FlagNote), + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + Memo: "deadbeef", + }, ) s.Require().NoError(err) savedTxFile := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String()) @@ -846,6 +891,9 @@ func (s *E2ETestSuite) TestCLIMultisignSortSignatures() { val1, addr, sdk.NewCoins(sendTokens), + clitestutil.SubmitTestTxConfig{ + GenOnly: false, + }, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -857,19 +905,21 @@ func (s *E2ETestSuite) TestCLIMultisignSortSignatures() { diff, _ := balRes.Balances.SafeSub(intialCoins...) s.Require().Equal(sendTokens.Amount, diff.AmountOf(s.cfg.BondDenom)) + tokens := sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 5)) + msgSend := &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: val1.Address.String(), + Amount: tokens, + } + // Generate multisig transaction. - multiGeneratedTx, err := clitestutil.MsgSendExec( - val1.ClientCtx, + multiGeneratedTx, err := clitestutil.SubmitTestTx( + val1, + msgSend, addr, - val1.Address, - sdk.NewCoins( - sdk.NewInt64Coin(s.cfg.BondDenom, 5), - ), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, ) s.Require().NoError(err) @@ -935,19 +985,23 @@ func (s *E2ETestSuite) TestSignWithMultisig() { multisigAddr, err := sdk.AccAddressFromBech32(multisig) s.Require().NoError(err) + tokens := sdk.NewCoins( + sdk.NewInt64Coin(s.cfg.BondDenom, 5), + ) + msgSend := &banktypes.MsgSend{ + FromAddress: val1.Address.String(), + ToAddress: val1.Address.String(), + Amount: tokens, + } + // Generate a transaction for testing --multisig with an address not in the keyring. - multisigTx, err := clitestutil.MsgSendExec( - val1.ClientCtx, - val1.Address, + multisigTx, err := clitestutil.SubmitTestTx( + val1, + msgSend, val1.Address, - sdk.NewCoins( - sdk.NewInt64Coin(s.cfg.BondDenom, 5), - ), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, ) s.Require().NoError(err) @@ -985,6 +1039,9 @@ func (s *E2ETestSuite) TestCLIMultisign() { _, err = s.createBankMsg( val1, addr, sdk.NewCoins(sendTokens), + clitestutil.SubmitTestTxConfig{ + GenOnly: false, + }, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -1000,19 +1057,21 @@ func (s *E2ETestSuite) TestCLIMultisign() { s.Require().NoError(err) s.Require().True(sendTokens.Amount.Equal(balRes.Balances.AmountOf(s.cfg.BondDenom))) + tokens := sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 5)) + msgSend := &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: val1.Address.String(), + Amount: tokens, + } + // Generate multisig transaction. - multiGeneratedTx, err := clitestutil.MsgSendExec( - val1.ClientCtx, + multiGeneratedTx, err := clitestutil.SubmitTestTx( + val1, + msgSend, addr, - val1.Address, - sdk.NewCoins( - sdk.NewInt64Coin(s.cfg.BondDenom, 5), - ), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, ) s.Require().NoError(err) @@ -1091,22 +1150,29 @@ func (s *E2ETestSuite) TestSignBatchMultisig() { val, addr, sdk.NewCoins(sendTokens), + clitestutil.SubmitTestTxConfig{ + GenOnly: false, + }, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) - generatedStd, err := clitestutil.MsgSendExec( - val.ClientCtx, + tokens := sdk.NewCoins( + sdk.NewCoin(s.cfg.BondDenom, math.NewInt(1)), + ) + msgSend := &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: val.Address.String(), + Amount: tokens, + } + + generatedStd, err := clitestutil.SubmitTestTx( + val, + msgSend, addr, - val.Address, - sdk.NewCoins( - sdk.NewCoin(s.cfg.BondDenom, math.NewInt(1)), - ), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, ) s.Require().NoError(err) @@ -1157,27 +1223,32 @@ func (s *E2ETestSuite) TestMultisignBatch() { val, addr, sdk.NewCoins(sendTokens), + clitestutil.SubmitTestTxConfig{ + GenOnly: false, + }, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) - generatedStd, err := clitestutil.MsgSendExec( - val.ClientCtx, + tokens := sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(1))) + msgSend := &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: val.Address.String(), + Amount: tokens, + } + + generatedStd, err := clitestutil.SubmitTestTx( + val, + msgSend, addr, - val.Address, - sdk.NewCoins( - sdk.NewCoin(s.cfg.BondDenom, math.NewInt(1)), - ), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, ) s.Require().NoError(err) // Write the output to disk - filename := testutil.WriteToNewTempFile(s.T(), strings.Repeat(generatedStd.String(), 3)) + filename := testutil.WriteToNewTempFile(s.T(), strings.Repeat(generatedStd.String()+"\n", 3)) defer filename.Close() val.ClientCtx.HomeDir = strings.Replace(val.ClientCtx.HomeDir, "simd", "simcli", 1) @@ -1476,7 +1547,14 @@ func (s *E2ETestSuite) TestAuxToFeeWithTips() { tip := sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), math.NewInt(1000)) require.NoError(s.network.WaitForNextBlock()) - _, err = s.createBankMsg(val, tipper, sdk.NewCoins(tipperInitialBal)) + _, err = s.createBankMsg( + val, + tipper, + sdk.NewCoins(tipperInitialBal), + clitestutil.SubmitTestTxConfig{ + GenOnly: false, + }, + ) require.NoError(err) require.NoError(s.network.WaitForNextBlock()) @@ -1709,16 +1787,14 @@ func (s *E2ETestSuite) TestAuxToFeeWithTips() { } } -func (s *E2ETestSuite) 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), - fmt.Sprintf("--%s=%s", flags.FlagFees, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), +func (s *E2ETestSuite) createBankMsg(val *network.Validator, toAddr sdk.AccAddress, amount sdk.Coins, config clitestutil.SubmitTestTxConfig) (testutil.BufferWriter, error) { + msgSend := &banktypes.MsgSend{ + FromAddress: val.Address.String(), + ToAddress: toAddr.String(), + Amount: amount, } - flags = append(flags, extraFlags...) - return clitestutil.MsgSendExec(val.ClientCtx, val.Address, toAddr, amount, addresscodec.NewBech32Codec("cosmos"), flags...) + return clitestutil.SubmitTestTx(val, msgSend, val.Address, config) } func (s *E2ETestSuite) getBalances(clientCtx client.Context, addr sdk.AccAddress, denom string) math.Int { diff --git a/tests/e2e/authz/tx.go b/tests/e2e/authz/tx.go index 225a8332e8ad..d40c96ad1c1e 100644 --- a/tests/e2e/authz/tx.go +++ b/tests/e2e/authz/tx.go @@ -147,14 +147,24 @@ func (s *E2ETestSuite) createAccount(uid string) sdk.AccAddress { func (s *E2ETestSuite) msgSendExec(grantee sdk.AccAddress) { val := s.network.Validators[0] // Send some funds to the new account. - out, err := clitestutil.MsgSendExec( - val.ClientCtx, - val.Address, - grantee, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(200))), addresscodec.NewBech32Codec("cosmos"), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), + + from := val.Address + coins := sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(200))) + msgSend := &bank.MsgSend{ + FromAddress: from.String(), + ToAddress: grantee.String(), + Amount: coins, + } + + out, err := clitestutil.SubmitTestTx( + val, + msgSend, + from, + clitestutil.SubmitTestTxConfig{ + GenOnly: false, + }, ) + s.Require().NoError(err) s.Require().Contains(out.String(), `"code":0`) s.Require().NoError(s.network.WaitForNextBlock()) @@ -495,20 +505,24 @@ func (s *E2ETestSuite) TestNewExecGrantAuthorized() { s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) + from := val.Address tokens := sdk.NewCoins( sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), math.NewInt(12)), ) - normalGeneratedTx, err := clitestutil.MsgSendExec( - val.ClientCtx, - val.Address, - grantee, - tokens, - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + msgSend := &bank.MsgSend{ + FromAddress: from.String(), + ToAddress: grantee.String(), + Amount: tokens, + } + normalGeneratedTx, err := clitestutil.SubmitTestTx( + val, + msgSend, + from, + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, ) + s.Require().NoError(err) execMsg := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String()) defer execMsg.Close() @@ -609,35 +623,40 @@ func (s *E2ETestSuite) TestExecSendAuthzWithAllowList() { s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) + from := val.Address tokens := sdk.NewCoins( sdk.NewCoin("stake", math.NewInt(12)), ) + msgSend := &bank.MsgSend{ + FromAddress: from.String(), + ToAddress: allowedAddr.String(), + Amount: tokens, + } - validGeneratedTx, err := clitestutil.MsgSendExec( - val.ClientCtx, - val.Address, - allowedAddr, - tokens, - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + validGeneratedTx, err := clitestutil.SubmitTestTx( + val, + msgSend, + from, + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, ) s.Require().NoError(err) execMsg := testutil.WriteToNewTempFile(s.T(), validGeneratedTx.String()) defer execMsg.Close() - invalidGeneratedTx, err := clitestutil.MsgSendExec( - val.ClientCtx, - val.Address, - notAllowedAddr, - tokens, - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + msgSend1 := &bank.MsgSend{ + FromAddress: from.String(), + ToAddress: notAllowedAddr.String(), + Amount: tokens, + } + invalidGeneratedTx, err := clitestutil.SubmitTestTx( + val, + msgSend1, + from, + clitestutil.SubmitTestTxConfig{ + GenOnly: true, + }, ) s.Require().NoError(err) execMsg1 := testutil.WriteToNewTempFile(s.T(), invalidGeneratedTx.String()) diff --git a/testutil/cli/cmd.go b/testutil/cli/cmd.go index d2b1e58aed92..67d419155079 100644 --- a/testutil/cli/cmd.go +++ b/testutil/cli/cmd.go @@ -1,19 +1,24 @@ package cli import ( + "bytes" "context" "fmt" + "github.com/cosmos/gogoproto/proto" "github.com/spf13/cobra" "cosmossdk.io/core/address" sdkmath "cosmossdk.io/math" "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/testutil" + "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" txtypes "github.com/cosmos/cosmos-sdk/types/tx" + "github.com/cosmos/cosmos-sdk/types/tx/signing" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -85,8 +90,6 @@ func MsgSendExec(clientCtx client.Context, from, to, amount fmt.Stringer, ac add return nil, err } - fmt.Println("txBz", string(txBz)) - req := &txtypes.BroadcastTxRequest{ TxBytes: txBz, Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC, @@ -95,8 +98,160 @@ func MsgSendExec(clientCtx client.Context, from, to, amount fmt.Stringer, ac add serviceClient := txtypes.NewServiceClient(clientCtx) resp, err := serviceClient.BroadcastTx(context.Background(), req) - fmt.Println("Resp", resp, err) + fmt.Println("Resp", resp, err, resp.TxResponse.Code) // return resp, err return nil, nil } + +func GenOrBroadcastTestTx(clientCtx client.Context, msg proto.Message, from sdk.AccAddress, generateonly bool) (testutil.BufferWriter, error) { + txBuilder := clientCtx.TxConfig.NewTxBuilder() + + fee := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))) + txBuilder.SetFeeAmount(fee) // Arbitrary fee + txBuilder.SetGasLimit(1000000) // Need at least 100386 + + err := txBuilder.SetMsgs(msg) + if err != nil { + return nil, err + } + + if generateonly { + txBz, err := clientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) + if err != nil { + return nil, err + } + + out := bytes.NewBuffer(txBz) + return out, nil + } + + txFactory := tx.Factory{} + txFactory = txFactory. + WithChainID(clientCtx.ChainID). + WithKeybase(clientCtx.Keyring). + WithTxConfig(clientCtx.TxConfig). + WithSignMode(signing.SignMode_SIGN_MODE_DIRECT) + + accBytes, err := clientCtx.AddressCodec.StringToBytes(from.String()) + if err != nil { + return nil, err + } + + keyRecord, err := clientCtx.Keyring.KeyByAddress(accBytes) + if err != nil { + return nil, err + } + + err = tx.Sign(context.Background(), txFactory, keyRecord.Name, txBuilder, true) + if err != nil { + return nil, err + } + + txBz, err := clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx()) + if err != nil { + return nil, err + } + + req := &txtypes.BroadcastTxRequest{ + TxBytes: txBz, + Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC, + } + + serviceClient := txtypes.NewServiceClient(clientCtx) + resp, err := serviceClient.BroadcastTx(context.Background(), req) + if err != nil { + return nil, err + } + + respBz, err := clientCtx.Codec.Marshal(resp) + if err != nil { + return nil, err + } + + out := bytes.NewBuffer(respBz) + return out, nil +} + +type SubmitTestTxConfig struct { + Simulate bool + GenOnly bool + Memo string + Gas uint64 +} + +func SubmitTestTx(val *network.Validator, msg proto.Message, from sdk.AccAddress, config SubmitTestTxConfig) (testutil.BufferWriter, error) { + clientCtx := val.ClientCtx + txBuilder := clientCtx.TxConfig.NewTxBuilder() + + err := txBuilder.SetMsgs(msg) + if err != nil { + return nil, err + } + + fee := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))) + txBuilder.SetFeeAmount(fee) // Arbitrary fee + + if config.Gas != 0 { + txBuilder.SetGasLimit(config.Gas) + } else { + txBuilder.SetGasLimit(flags.DefaultGasLimit) // Need at least 100386 + } + + if config.Memo != "" { + txBuilder.SetMemo(config.Memo) + } + + if config.GenOnly { + txBz, err := val.ClientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) + if err != nil { + return nil, err + } + + out := bytes.NewBuffer(txBz) + return out, nil + } + + acc, err := clientCtx.AccountRetriever.GetAccount(clientCtx, from) + if err != nil { + return nil, err + } + + txFactory := tx.Factory{} + txFactory = txFactory. + WithChainID(clientCtx.ChainID). + WithKeybase(clientCtx.Keyring). + WithTxConfig(clientCtx.TxConfig). + WithSignMode(signing.SignMode_SIGN_MODE_DIRECT). + WithAccountNumber(acc.GetAccountNumber()). + WithSequence(acc.GetSequence()) + + if config.Simulate { + txFactory = txFactory.WithSimulateAndExecute(true) + } + + accBytes, err := clientCtx.AddressCodec.StringToBytes(from.String()) + if err != nil { + return nil, err + } + + keyRecord, err := clientCtx.Keyring.KeyByAddress(accBytes) + if err != nil { + return nil, err + } + + err = tx.Sign(context.Background(), txFactory, keyRecord.Name, txBuilder, true) + if err != nil { + return nil, err + } + + txBz, err := val.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx()) + if err != nil { + return nil, err + } + + res, err := val.BroadcastTx(txBz) + out := bytes.NewBuffer(res) + + return out, err +} diff --git a/testutil/network/network.go b/testutil/network/network.go index 8fc1266045f8..661120cc9a86 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -52,6 +52,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" _ "github.com/cosmos/cosmos-sdk/x/auth" // import auth as a blank _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import auth tx config as a blank authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -327,6 +328,19 @@ func (v Validator) GetAppConfig() *srvconfig.Config { return v.AppConfig } +func (v Validator) BroadcastTx(txBytes []byte) ([]byte, error) { + txReq := &txtypes.BroadcastTxRequest{ + Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC, + TxBytes: txBytes, + } + req, err := v.ClientCtx.Codec.MarshalJSON(txReq) + if err != nil { + return nil, err + } + + return testutil.PostRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs", v.APIAddress), "application/json", req) +} + // CLILogger wraps a cobra.Command and provides command logging methods. type CLILogger struct { cmd *cobra.Command diff --git a/x/authz/client/cli/tx_test.go b/x/authz/client/cli/tx_test.go index 546042524ad7..bc4dba6de1ae 100644 --- a/x/authz/client/cli/tx_test.go +++ b/x/authz/client/cli/tx_test.go @@ -180,18 +180,16 @@ func (s *CLITestSuite) msgSendExec(grantee sdk.AccAddress) { _, err := s.ac.StringToBytes("cosmos16zex22087zs656t0vedytv5wqhm6axxd5679ry") s.Require().NoError(err) - out, err := clitestutil.MsgSendExec( - s.clientCtx, - val[0].Address, - grantee, - sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(200))), - s.ac, - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), - ) + coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(200))) + from := val[0].Address + msgSend := &banktypes.MsgSend{ + FromAddress: from.String(), + ToAddress: grantee.String(), + Amount: coins, + } + + _, err = clitestutil.GenOrBroadcastTestTx(s.clientCtx, msgSend, from, false) s.Require().NoError(err) - s.Require().Contains(out.String(), `"code":0`) } func (s *CLITestSuite) TestCLITxGrantAuthorization() { @@ -766,19 +764,20 @@ func (s *CLITestSuite) TestNewExecGrantAuthorized() { ) s.Require().NoError(err) + from := val[0].Address tokens := sdk.NewCoins( sdk.NewCoin("testtoken", sdkmath.NewInt(12)), ) - normalGeneratedTx, err := clitestutil.MsgSendExec( + msgSend := &banktypes.MsgSend{ + FromAddress: from.String(), + ToAddress: grantee.String(), + Amount: tokens, + } + normalGeneratedTx, err := clitestutil.GenOrBroadcastTestTx( s.clientCtx, - val[0].Address, - grantee, - tokens, - s.ac, - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + msgSend, + from, + true, ) s.Require().NoError(err) execMsg := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String()) @@ -863,36 +862,38 @@ func (s *CLITestSuite) TestExecSendAuthzWithAllowList() { ) s.Require().NoError(err) + from := val[0].Address tokens := sdk.NewCoins( sdk.NewCoin("stake", sdkmath.NewInt(12)), ) - - validGeneratedTx, err := clitestutil.MsgSendExec( + msgSend := &banktypes.MsgSend{ + FromAddress: from.String(), + ToAddress: grantee.String(), + Amount: tokens, + } + validGeneratedTx, err := clitestutil.GenOrBroadcastTestTx( s.clientCtx, - val[0].Address, - allowedAddr, - tokens, - s.ac, - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + msgSend, + from, + true, ) + s.Require().NoError(err) execMsg := testutil.WriteToNewTempFile(s.T(), validGeneratedTx.String()) defer execMsg.Close() - invalidGeneratedTx, err := clitestutil.MsgSendExec( + msgSend1 := &banktypes.MsgSend{ + FromAddress: from.String(), + ToAddress: notAllowedAddr.String(), + Amount: tokens, + } + invalidGeneratedTx, err := clitestutil.GenOrBroadcastTestTx( s.clientCtx, - val[0].Address, - notAllowedAddr, - tokens, - s.ac, - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + msgSend1, + from, + true, ) + s.Require().NoError(err) execMsg1 := testutil.WriteToNewTempFile(s.T(), invalidGeneratedTx.String()) defer execMsg1.Close() diff --git a/x/group/client/cli/tx_test.go b/x/group/client/cli/tx_test.go index 3dd17517c1f4..c8337df7f453 100644 --- a/x/group/client/cli/tx_test.go +++ b/x/group/client/cli/tx_test.go @@ -25,6 +25,7 @@ import ( clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" sdk "github.com/cosmos/cosmos-sdk/types" testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/group" groupcli "github.com/cosmos/cosmos-sdk/x/group/client/cli" groupmodule "github.com/cosmos/cosmos-sdk/x/group/module" @@ -88,14 +89,17 @@ func (s *CLITestSuite) SetupSuite() { s.Require().NoError(err) account := sdk.AccAddress(pk.Address()) - _, err = clitestutil.MsgSendExec( - s.clientCtx, - val.Address, - account, - sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(2000))), addresscodec.NewBech32Codec("cosmos"), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()), - ) + + from := val.Address + coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(2000))) + + msgSend := &banktypes.MsgSend{ + FromAddress: from.String(), + ToAddress: account.String(), + Amount: coins, + } + + clitestutil.GenOrBroadcastTestTx(s.clientCtx, msgSend, from, false) s.Require().NoError(err) // create a group From 581f8681375afe3deea3dcc567ede410a39b8157 Mon Sep 17 00:00:00 2001 From: atheesh Date: Thu, 28 Sep 2023 20:04:46 +0530 Subject: [PATCH 05/20] refactor --- tests/e2e/auth/suite.go | 100 ++++----- tests/e2e/authz/tx.go | 18 +- tests/e2e/bank/suite.go | 104 ++++----- tests/e2e/distribution/withdraw_all_suite.go | 16 +- tests/e2e/group/suite.go | 39 +++- tests/e2e/staking/suite.go | 15 +- tests/e2e/tx/benchmarks_test.go | 72 +++--- tests/e2e/tx/service_test.go | 120 +++++----- .../integration/auth/client/cli/suite_test.go | 141 +++++------- testutil/cli/cmd.go | 209 +++++------------- testutil/network/network.go | 14 -- x/authz/client/cli/tx_test.go | 15 +- x/group/client/cli/tx_test.go | 2 +- x/nft/client/cli/tx_test.go | 21 +- 14 files changed, 375 insertions(+), 511 deletions(-) diff --git a/tests/e2e/auth/suite.go b/tests/e2e/auth/suite.go index b02015e4c0ee..39b2231fa1d4 100644 --- a/tests/e2e/auth/suite.go +++ b/tests/e2e/auth/suite.go @@ -104,10 +104,10 @@ func (s *E2ETestSuite) TestCLISignGenOnly() { } generatedStd, err := clitestutil.SubmitTestTx( - val, + val.ClientCtx, msgSend, val.Address, - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, }, ) @@ -214,7 +214,7 @@ func (s *E2ETestSuite) TestCLISignBatch() { generatedStd, err := s.createBankMsg( val, val.Address, - sendTokens, clitestutil.SubmitTestTxConfig{ + sendTokens, clitestutil.TestTxConfig{ GenOnly: true, }, ) @@ -276,9 +276,7 @@ func (s *E2ETestSuite) TestCLISignBatch() { val, addr, sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 1000)), - clitestutil.SubmitTestTxConfig{ - GenOnly: false, - }, + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -315,14 +313,12 @@ func (s *E2ETestSuite) TestCLIQueryTxCmdByHash() { val, addr, sdk.NewCoins(sendTokens), - clitestutil.SubmitTestTxConfig{ - GenOnly: false, - }, + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) - var txRes tx.BroadcastTxResponse + var txRes sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &txRes)) testCases := []struct { @@ -348,7 +344,7 @@ func (s *E2ETestSuite) TestCLIQueryTxCmdByHash() { }, { "happy case", - []string{txRes.TxResponse.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}, + []string{txRes.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}, false, sdk.MsgTypeURL(&banktypes.MsgSend{}), }, @@ -399,23 +395,20 @@ func (s *E2ETestSuite) TestCLIQueryTxCmdByEvents() { val, addr2, sdk.NewCoins(sendTokens), - clitestutil.SubmitTestTxConfig{ - GenOnly: false, - }, + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) - var bankTxRes tx.BroadcastTxResponse - s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &bankTxRes)) + var txRes sdk.TxResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &txRes)) s.Require().NoError(s.network.WaitForNextBlock()) var out testutil.BufferWriter // Query the tx by hash to get the inner tx. err = s.network.RetryForBlocks(func() error { - out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, authcli.QueryTxCmd(), []string{bankTxRes.TxResponse.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}) + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, authcli.QueryTxCmd(), []string{txRes.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}) return err }, 3) s.Require().NoError(err) - var txRes sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes)) protoTx := txRes.GetTx().(*tx.Tx) @@ -525,23 +518,20 @@ func (s *E2ETestSuite) TestCLIQueryTxsCmdByEvents() { val, addr2, sdk.NewCoins(sendTokens), - clitestutil.SubmitTestTxConfig{ - GenOnly: false, - }, + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) - var sendTxRes tx.BroadcastTxResponse - s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &sendTxRes)) + var txRes sdk.TxResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(res.Bytes(), &txRes)) s.Require().NoError(s.network.WaitForNextBlock()) var out testutil.BufferWriter // Query the tx by hash to get the inner tx. err = s.network.RetryForBlocks(func() error { - out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, authcli.QueryTxCmd(), []string{sendTxRes.TxResponse.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}) + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, authcli.QueryTxCmd(), []string{txRes.TxHash, fmt.Sprintf("--%s=json", flags.FlagOutput)}) return err }, 3) s.Require().NoError(err) - var txRes sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes)) testCases := []struct { @@ -609,7 +599,7 @@ func (s *E2ETestSuite) TestCLISendGenerateSignAndBroadcast() { val1, addr, sdk.NewCoins(sendTokens), - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, }, ) @@ -629,7 +619,7 @@ func (s *E2ETestSuite) TestCLISendGenerateSignAndBroadcast() { // Test generate sendTx with --gas=$amount limitedGasGeneratedTx, err := s.createBankMsg(val1, addr, - sdk.NewCoins(sendTokens), clitestutil.SubmitTestTxConfig{ + sdk.NewCoins(sendTokens), clitestutil.TestTxConfig{ GenOnly: true, Gas: 100, }, @@ -658,7 +648,7 @@ func (s *E2ETestSuite) TestCLISendGenerateSignAndBroadcast() { finalGeneratedTx, err := s.createBankMsg( val1, addr, - sdk.NewCoins(sendTokens), clitestutil.SubmitTestTxConfig{ + sdk.NewCoins(sendTokens), clitestutil.TestTxConfig{ GenOnly: true, Gas: flags.DefaultGasLimit, }) @@ -774,9 +764,7 @@ func (s *E2ETestSuite) TestCLIMultisignInsufficientCosigners() { sdk.NewCoins( sdk.NewInt64Coin(s.cfg.BondDenom, 10), ), - clitestutil.SubmitTestTxConfig{ - GenOnly: false, - }, + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -790,10 +778,10 @@ func (s *E2ETestSuite) TestCLIMultisignInsufficientCosigners() { // Generate multisig transaction. multiGeneratedTx, err := clitestutil.SubmitTestTx( - val1, + val1.ClientCtx, msgSend, addr, - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, }, ) @@ -832,7 +820,7 @@ func (s *E2ETestSuite) TestCLIEncode() { normalGeneratedTx, err := s.createBankMsg( val1, val1.Address, sdk.NewCoins(sendTokens), - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, Memo: "deadbeef", }, @@ -891,9 +879,7 @@ func (s *E2ETestSuite) TestCLIMultisignSortSignatures() { val1, addr, sdk.NewCoins(sendTokens), - clitestutil.SubmitTestTxConfig{ - GenOnly: false, - }, + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -914,10 +900,10 @@ func (s *E2ETestSuite) TestCLIMultisignSortSignatures() { // Generate multisig transaction. multiGeneratedTx, err := clitestutil.SubmitTestTx( - val1, + val1.ClientCtx, msgSend, addr, - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, }, ) @@ -996,10 +982,10 @@ func (s *E2ETestSuite) TestSignWithMultisig() { // Generate a transaction for testing --multisig with an address not in the keyring. multisigTx, err := clitestutil.SubmitTestTx( - val1, + val1.ClientCtx, msgSend, val1.Address, - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, }, ) @@ -1039,9 +1025,7 @@ func (s *E2ETestSuite) TestCLIMultisign() { _, err = s.createBankMsg( val1, addr, sdk.NewCoins(sendTokens), - clitestutil.SubmitTestTxConfig{ - GenOnly: false, - }, + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -1066,10 +1050,10 @@ func (s *E2ETestSuite) TestCLIMultisign() { // Generate multisig transaction. multiGeneratedTx, err := clitestutil.SubmitTestTx( - val1, + val1.ClientCtx, msgSend, addr, - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, }, ) @@ -1150,9 +1134,7 @@ func (s *E2ETestSuite) TestSignBatchMultisig() { val, addr, sdk.NewCoins(sendTokens), - clitestutil.SubmitTestTxConfig{ - GenOnly: false, - }, + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -1167,10 +1149,10 @@ func (s *E2ETestSuite) TestSignBatchMultisig() { } generatedStd, err := clitestutil.SubmitTestTx( - val, + val.ClientCtx, msgSend, addr, - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, }, ) @@ -1223,9 +1205,7 @@ func (s *E2ETestSuite) TestMultisignBatch() { val, addr, sdk.NewCoins(sendTokens), - clitestutil.SubmitTestTxConfig{ - GenOnly: false, - }, + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -1238,10 +1218,10 @@ func (s *E2ETestSuite) TestMultisignBatch() { } generatedStd, err := clitestutil.SubmitTestTx( - val, + val.ClientCtx, msgSend, addr, - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, }, ) @@ -1551,9 +1531,7 @@ func (s *E2ETestSuite) TestAuxToFeeWithTips() { val, tipper, sdk.NewCoins(tipperInitialBal), - clitestutil.SubmitTestTxConfig{ - GenOnly: false, - }, + clitestutil.TestTxConfig{}, ) require.NoError(err) require.NoError(s.network.WaitForNextBlock()) @@ -1787,14 +1765,14 @@ func (s *E2ETestSuite) TestAuxToFeeWithTips() { } } -func (s *E2ETestSuite) createBankMsg(val *network.Validator, toAddr sdk.AccAddress, amount sdk.Coins, config clitestutil.SubmitTestTxConfig) (testutil.BufferWriter, error) { +func (s *E2ETestSuite) createBankMsg(val *network.Validator, toAddr sdk.AccAddress, amount sdk.Coins, config clitestutil.TestTxConfig) (testutil.BufferWriter, error) { msgSend := &banktypes.MsgSend{ FromAddress: val.Address.String(), ToAddress: toAddr.String(), Amount: amount, } - return clitestutil.SubmitTestTx(val, msgSend, val.Address, config) + return clitestutil.SubmitTestTx(val.ClientCtx, msgSend, val.Address, config) } func (s *E2ETestSuite) getBalances(clientCtx client.Context, addr sdk.AccAddress, denom string) math.Int { diff --git a/tests/e2e/authz/tx.go b/tests/e2e/authz/tx.go index d40c96ad1c1e..194a26c8019f 100644 --- a/tests/e2e/authz/tx.go +++ b/tests/e2e/authz/tx.go @@ -157,12 +157,10 @@ func (s *E2ETestSuite) msgSendExec(grantee sdk.AccAddress) { } out, err := clitestutil.SubmitTestTx( - val, + val.ClientCtx, msgSend, from, - clitestutil.SubmitTestTxConfig{ - GenOnly: false, - }, + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) @@ -515,10 +513,10 @@ func (s *E2ETestSuite) TestNewExecGrantAuthorized() { Amount: tokens, } normalGeneratedTx, err := clitestutil.SubmitTestTx( - val, + val.ClientCtx, msgSend, from, - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, }, ) @@ -634,10 +632,10 @@ func (s *E2ETestSuite) TestExecSendAuthzWithAllowList() { } validGeneratedTx, err := clitestutil.SubmitTestTx( - val, + val.ClientCtx, msgSend, from, - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, }, ) @@ -651,10 +649,10 @@ func (s *E2ETestSuite) TestExecSendAuthzWithAllowList() { Amount: tokens, } invalidGeneratedTx, err := clitestutil.SubmitTestTx( - val, + val.ClientCtx, msgSend1, from, - clitestutil.SubmitTestTxConfig{ + clitestutil.TestTxConfig{ GenOnly: true, }, ) diff --git a/tests/e2e/bank/suite.go b/tests/e2e/bank/suite.go index 48b34f12b483..0cb3d837fe24 100644 --- a/tests/e2e/bank/suite.go +++ b/tests/e2e/bank/suite.go @@ -2,8 +2,6 @@ package client import ( "fmt" - "io" - "os" "github.com/cosmos/gogoproto/proto" "github.com/stretchr/testify/suite" @@ -98,23 +96,29 @@ func (s *E2ETestSuite) TearDownSuite() { func (s *E2ETestSuite) TestNewSendTxCmdGenOnly() { val := s.network.Validators[0] - clientCtx := val.ClientCtx - from := val.Address to := val.Address amount := sdk.NewCoins( sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), math.NewInt(10)), sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10)), ) - args := []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + + msgSend := &types.MsgSend{ + FromAddress: from.String(), + ToAddress: to.String(), + Amount: amount, } - bz, err := clitestutil.MsgSendExec(clientCtx, from, to, amount, addresscodec.NewBech32Codec("cosmos"), args...) + bz, err := clitestutil.SubmitTestTx( + val.ClientCtx, + msgSend, + from, + clitestutil.TestTxConfig{ + GenOnly: true, + }, + ) s.Require().NoError(err) + tx, err := s.cfg.TxConfig.TxJSONDecoder()(bz.Bytes()) s.Require().NoError(err) s.Require().Equal([]sdk.Msg{types.NewMsgSend(from, to, amount)}, tx.GetMsgs()) @@ -123,33 +127,30 @@ func (s *E2ETestSuite) TestNewSendTxCmdGenOnly() { func (s *E2ETestSuite) TestNewSendTxCmdDryRun() { val := s.network.Validators[0] - clientCtx := val.ClientCtx - from := val.Address to := val.Address amount := sdk.NewCoins( sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), math.NewInt(10)), sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10)), ) - args := []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagDryRun), - } - oldSterr := os.Stderr - r, w, _ := os.Pipe() - os.Stderr = w + msgSend := &types.MsgSend{ + FromAddress: from.String(), + ToAddress: to.String(), + Amount: amount, + } - _, err := clitestutil.MsgSendExec(clientCtx, from, to, amount, addresscodec.NewBech32Codec("cosmos"), args...) + out, err := clitestutil.SubmitTestTx( + val.ClientCtx, + msgSend, + from, + clitestutil.TestTxConfig{ + Simulate: true, + }, + ) s.Require().NoError(err) - - w.Close() - out, _ := io.ReadAll(r) - os.Stderr = oldSterr - - s.Require().Regexp("gas estimate: [0-9]+", string(out)) + s.Require().Regexp("\"gas_info\"", out.String()) + s.Require().Regexp("\"gas_used\":\"[0-9]+\"", out.String()) } func (s *E2ETestSuite) TestNewSendTxCmd() { @@ -159,7 +160,7 @@ func (s *E2ETestSuite) TestNewSendTxCmd() { name string from, to sdk.AccAddress amount sdk.Coins - args []string + config clitestutil.TestTxConfig expectErr bool expectedCode uint32 respType proto.Message @@ -172,30 +173,11 @@ func (s *E2ETestSuite) TestNewSendTxCmd() { sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), math.NewInt(10)), sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10)), ), - []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), + clitestutil.TestTxConfig{ + Fee: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))), }, false, 0, &sdk.TxResponse{}, }, - { - "chain-id shouldn't be used with offline and generate-only flags", - val.Address, - val.Address, - sdk.NewCoins( - sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), math.NewInt(10)), - sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10)), - ), - []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagOffline), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), - }, - true, 0, &sdk.TxResponse{}, - }, { "not enough fees", val.Address, @@ -204,11 +186,10 @@ func (s *E2ETestSuite) TestNewSendTxCmd() { sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), math.NewInt(10)), sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10)), ), - []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(1))).String()), + clitestutil.TestTxConfig{ + Fee: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(1))), }, + false, sdkerrors.ErrInsufficientFee.ABCICode(), &sdk.TxResponse{}, @@ -221,11 +202,9 @@ func (s *E2ETestSuite) TestNewSendTxCmd() { sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), math.NewInt(10)), sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10)), ), - []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - "--gas=10", + clitestutil.TestTxConfig{ + Gas: 10, + Fee: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))), }, false, sdkerrors.ErrOutOfGas.ABCICode(), @@ -240,7 +219,12 @@ func (s *E2ETestSuite) TestNewSendTxCmd() { s.Run(tc.name, func() { clientCtx := val.ClientCtx - bz, err := clitestutil.MsgSendExec(clientCtx, tc.from, tc.to, tc.amount, addresscodec.NewBech32Codec("cosmos"), tc.args...) + msgSend := types.MsgSend{ + FromAddress: tc.from.String(), + ToAddress: tc.to.String(), + Amount: tc.amount, + } + bz, err := clitestutil.SubmitTestTx(val.ClientCtx, &msgSend, tc.from, tc.config) if tc.expectErr { s.Require().Error(err) } else { diff --git a/tests/e2e/distribution/withdraw_all_suite.go b/tests/e2e/distribution/withdraw_all_suite.go index 18a7a5b11555..4110f88bf077 100644 --- a/tests/e2e/distribution/withdraw_all_suite.go +++ b/tests/e2e/distribution/withdraw_all_suite.go @@ -17,6 +17,7 @@ import ( clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/distribution/client/cli" stakingcli "github.com/cosmos/cosmos-sdk/x/staking/client/cli" ) @@ -62,14 +63,19 @@ func (s *WithdrawAllTestSuite) TestNewWithdrawAllRewardsGenerateOnly() { require.NoError(err) newAddr := sdk.AccAddress(pubkey.Address()) - _, err = clitestutil.MsgSendExec( + + msgSend := &banktypes.MsgSend{ + FromAddress: val.Address.String(), + ToAddress: newAddr.String(), + Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(2000))), + } + _, err = clitestutil.SubmitTestTx( val.ClientCtx, + msgSend, val.Address, - newAddr, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(2000))), address.NewBech32Codec("cosmos"), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), + clitestutil.TestTxConfig{}, ) + require.NoError(err) require.NoError(s.network.WaitForNextBlock()) diff --git a/tests/e2e/group/suite.go b/tests/e2e/group/suite.go index 6d1525e543aa..d2c1b6a14afd 100644 --- a/tests/e2e/group/suite.go +++ b/tests/e2e/group/suite.go @@ -12,7 +12,6 @@ import ( "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/testutil" @@ -68,16 +67,21 @@ func (s *E2ETestSuite) SetupSuite() { s.Require().NoError(err) account := sdk.AccAddress(pk.Address()) - _, err = clitestutil.MsgSendExec( + msgSend := &banktypes.MsgSend{ + FromAddress: val.Address.String(), + ToAddress: account.String(), + Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(2000))), + } + + _, err = clitestutil.SubmitTestTx( val.ClientCtx, + msgSend, val.Address, - account, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(2000))), - address.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), + clitestutil.TestTxConfig{ + GenOnly: true, + }, ) + s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -269,11 +273,22 @@ func (s *E2ETestSuite) createGroupThresholdPolicyWithBalance(adminAddress, group addr, err := sdk.AccAddressFromBech32(groupPolicyAddress) s.Require().NoError(err) - _, err = clitestutil.MsgSendExec(clientCtx, val.Address, addr, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(tokens))), - address.NewBech32Codec("cosmos"), - s.commonFlags..., + + msgSend := &banktypes.MsgSend{ + FromAddress: val.Address.String(), + ToAddress: addr.String(), + Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(tokens))), + } + + _, err = clitestutil.SubmitTestTx( + val.ClientCtx, + msgSend, + val.Address, + clitestutil.TestTxConfig{ + GenOnly: true, + }, ) s.Require().NoError(err) + return groupPolicyAddress } diff --git a/tests/e2e/staking/suite.go b/tests/e2e/staking/suite.go index 174138281967..fc5b3bb9277b 100644 --- a/tests/e2e/staking/suite.go +++ b/tests/e2e/staking/suite.go @@ -19,6 +19,7 @@ import ( clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/staking/client/cli" ) @@ -102,14 +103,18 @@ func (s *E2ETestSuite) TestBlockResults() { require.NoError(err) newAddr := sdk.AccAddress(pub.Address()) + msgSend := &banktypes.MsgSend{ + FromAddress: val.Address.String(), + ToAddress: newAddr.String(), + Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(200))), + } + // Send some funds to the new account. - _, err = clitestutil.MsgSendExec( + _, err = clitestutil.SubmitTestTx( val.ClientCtx, + msgSend, val.Address, - newAddr, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(200))), addresscodec.NewBech32Codec("cosmos"), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), + clitestutil.TestTxConfig{}, ) require.NoError(err) require.NoError(s.network.WaitForNextBlock()) diff --git a/tests/e2e/tx/benchmarks_test.go b/tests/e2e/tx/benchmarks_test.go index e323ddb91e26..a5875e727279 100644 --- a/tests/e2e/tx/benchmarks_test.go +++ b/tests/e2e/tx/benchmarks_test.go @@ -2,7 +2,6 @@ package tx_test import ( "context" - "fmt" "testing" "gotest.tools/v3/assert" @@ -11,9 +10,7 @@ import ( "cosmossdk.io/simapp" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" clienttx "github.com/cosmos/cosmos-sdk/client/tx" - addresscodec "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" "github.com/cosmos/cosmos-sdk/testutil/testdata" @@ -30,7 +27,6 @@ type E2EBenchmarkSuite struct { txHeight int64 queryClient tx.ServiceClient - txRes sdk.TxResponse } // BenchmarkTx is lifted from E2ETestSuite from this package, with irrelevant state checks removed. @@ -80,7 +76,7 @@ func BenchmarkTx(b *testing.B) { // - tx.* events: tx.fee, tx.acc_seq, tx.signature // - Sending Amount to recipient: coin_spent, coin_received, transfer and message.sender= // - Msg events: message.module=bank and message.action=/cosmos.bank.v1beta1.MsgSend (in one message) - assert.Equal(b, 12, len(res.GetResult().GetEvents())) + assert.Equal(b, 10, len(res.GetResult().GetEvents())) assert.Assert(b, res.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty. } } @@ -104,48 +100,52 @@ func NewE2EBenchmarkSuite(tb testing.TB) *E2EBenchmarkSuite { s.queryClient = tx.NewServiceClient(val.ClientCtx) + msgSend := &banktypes.MsgSend{ + FromAddress: val.Address.String(), + ToAddress: val.Address.String(), + Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdkmath.NewInt(10))), + } + // Create a new MsgSend tx from val to itself. - out, err := cli.MsgSendExec( + out, err := cli.SubmitTestTx( val.ClientCtx, + msgSend, val.Address, - val.Address, - sdk.NewCoins( - sdk.NewCoin(s.cfg.BondDenom, sdkmath.NewInt(10)), - ), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdkmath.NewInt(10))).String()), - fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), - fmt.Sprintf("--%s=foobar", flags.FlagNote), + cli.TestTxConfig{ + Memo: "foobar", + }, ) + assert.NilError(tb, err) - assert.NilError(tb, val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &s.txRes)) - assert.Equal(tb, uint32(0), s.txRes.Code, s.txRes) - out, err = cli.MsgSendExec( + var txRes tx.BroadcastTxResponse + assert.NilError(tb, val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes)) + assert.Equal(tb, uint32(0), txRes.TxResponse.Code, txRes) + + msgSend1 := &banktypes.MsgSend{ + FromAddress: val.Address.String(), + ToAddress: val.Address.String(), + Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdkmath.NewInt(1))), + } + + out1, err := cli.SubmitTestTx( val.ClientCtx, + msgSend1, val.Address, - val.Address, - sdk.NewCoins( - sdk.NewCoin(s.cfg.BondDenom, sdkmath.NewInt(1)), - ), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s", flags.FlagOffline), - fmt.Sprintf("--%s=0", flags.FlagAccountNumber), - fmt.Sprintf("--%s=2", flags.FlagSequence), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdkmath.NewInt(10))).String()), - fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), - fmt.Sprintf("--%s=foobar", flags.FlagNote), + cli.TestTxConfig{ + Offline: true, + AccNum: 0, + Seq: 2, + Memo: "foobar", + }, ) + assert.NilError(tb, err) - var tr sdk.TxResponse - assert.NilError(tb, val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &tr)) - assert.Equal(tb, uint32(0), tr.Code) + var tr tx.BroadcastTxResponse + assert.NilError(tb, val.ClientCtx.Codec.UnmarshalJSON(out1.Bytes(), &tr)) + assert.Equal(tb, uint32(0), tr.TxResponse.Code) - resp, err := cli.GetTxResponse(s.network, val.ClientCtx, tr.TxHash) + resp, err := cli.GetTxResponse(s.network, val.ClientCtx, tr.TxResponse.TxHash) assert.NilError(tb, err) s.txHeight = resp.Height return s diff --git a/tests/e2e/tx/service_test.go b/tests/e2e/tx/service_test.go index fa878a901f84..9b93fab6ba87 100644 --- a/tests/e2e/tx/service_test.go +++ b/tests/e2e/tx/service_test.go @@ -15,9 +15,7 @@ import ( "cosmossdk.io/simapp" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" clienttx "github.com/cosmos/cosmos-sdk/client/tx" - addresscodec "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" @@ -48,7 +46,7 @@ type E2ETestSuite struct { txHeight int64 queryClient tx.ServiceClient - txRes sdk.TxResponse + goodTxHash string } func (s *E2ETestSuite) SetupSuite() { @@ -67,48 +65,53 @@ func (s *E2ETestSuite) SetupSuite() { s.queryClient = tx.NewServiceClient(val.ClientCtx) + msgSend := &banktypes.MsgSend{ + FromAddress: val.Address.String(), + ToAddress: val.Address.String(), + Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))), + } + // Create a new MsgSend tx from val to itself. - out, err := cli.MsgSendExec( + out, err := cli.SubmitTestTx( val.ClientCtx, + msgSend, val.Address, - val.Address, - sdk.NewCoins( - sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10)), - ), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), - fmt.Sprintf("--%s=foobar", flags.FlagNote), + cli.TestTxConfig{ + Memo: "foobar", + }, ) + s.Require().NoError(err) - s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &s.txRes)) - s.Require().Equal(uint32(0), s.txRes.Code, s.txRes) - out, err = cli.MsgSendExec( + var txRes tx.BroadcastTxResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes)) + s.Require().Equal(uint32(0), txRes.TxResponse.Code, txRes) + s.goodTxHash = txRes.TxResponse.TxHash + + msgSend1 := &banktypes.MsgSend{ + FromAddress: val.Address.String(), + ToAddress: val.Address.String(), + Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(1))), + } + + out1, err := cli.SubmitTestTx( val.ClientCtx, + msgSend1, val.Address, - val.Address, - sdk.NewCoins( - sdk.NewCoin(s.cfg.BondDenom, math.NewInt(1)), - ), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s", flags.FlagOffline), - fmt.Sprintf("--%s=0", flags.FlagAccountNumber), - fmt.Sprintf("--%s=2", flags.FlagSequence), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), - fmt.Sprintf("--%s=foobar", flags.FlagNote), + cli.TestTxConfig{ + Offline: true, + AccNum: 0, + Seq: 2, + Memo: "foobar", + }, ) + s.Require().NoError(err) - var tr sdk.TxResponse - s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &tr)) - s.Require().Equal(uint32(0), tr.Code) + var tr tx.BroadcastTxResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out1.Bytes(), &tr)) + s.Require().Equal(uint32(0), tr.TxResponse.Code) - resp, err := cli.GetTxResponse(s.network, val.ClientCtx, tr.TxHash) + resp, err := cli.GetTxResponse(s.network, val.ClientCtx, tr.TxResponse.TxHash) s.Require().NoError(err) s.txHeight = resp.Height } @@ -419,7 +422,7 @@ func (s *E2ETestSuite) TestGetTx_GRPC() { {"nil request", nil, true, "request cannot be nil"}, {"empty request", &tx.GetTxRequest{}, true, "tx hash cannot be empty"}, {"request with dummy hash", &tx.GetTxRequest{Hash: "deadbeef"}, true, "code = NotFound desc = tx not found: deadbeef"}, - {"good request", &tx.GetTxRequest{Hash: s.txRes.TxHash}, false, ""}, + {"good request", &tx.GetTxRequest{Hash: s.goodTxHash}, false, ""}, } for _, tc := range testCases { s.Run(tc.name, func() { @@ -456,7 +459,7 @@ func (s *E2ETestSuite) TestGetTx_GRPCGateway() { }, { "good hash", - fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", val.APIAddress, s.txRes.TxHash), + fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", val.APIAddress, s.goodTxHash), false, "", }, } @@ -594,18 +597,20 @@ func (s *E2ETestSuite) TestSimMultiSigTx() { s.Require().NoError(err) // Send coins from validator to multisig. - coins := sdk.NewInt64Coin(s.cfg.BondDenom, 15) - _, err = cli.MsgSendExec( + coin := sdk.NewInt64Coin(s.cfg.BondDenom, 15) + msgSend := &banktypes.MsgSend{ + FromAddress: val1.Address.String(), + ToAddress: addr.String(), + Amount: sdk.NewCoins(coin), + } + + _, err = cli.SubmitTestTx( val1.ClientCtx, + msgSend, val1.Address, - addr, - sdk.NewCoins(coins), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), + cli.TestTxConfig{}, ) + s.Require().NoError(err) height, err = s.network.LatestHeight() @@ -613,21 +618,24 @@ func (s *E2ETestSuite) TestSimMultiSigTx() { _, err = s.network.WaitForHeight(height + 1) s.Require().NoError(err) + msgSend1 := &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: val1.Address.String(), + Amount: sdk.NewCoins( + sdk.NewInt64Coin(s.cfg.BondDenom, 5), + ), + } // Generate multisig transaction. - multiGeneratedTx, err := cli.MsgSendExec( + multiGeneratedTx, err := cli.SubmitTestTx( val1.ClientCtx, - addr, + msgSend1, val1.Address, - sdk.NewCoins( - sdk.NewInt64Coin(s.cfg.BondDenom, 5), - ), - addresscodec.NewBech32Codec("cosmos"), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), - fmt.Sprintf("--%s=foobar", flags.FlagNote), + cli.TestTxConfig{ + GenOnly: true, + Memo: "foobar", + }, ) + s.Require().NoError(err) // Save tx to file diff --git a/tests/integration/auth/client/cli/suite_test.go b/tests/integration/auth/client/cli/suite_test.go index 80b0c7b24bd6..41c6380b5538 100644 --- a/tests/integration/auth/client/cli/suite_test.go +++ b/tests/integration/auth/client/cli/suite_test.go @@ -114,7 +114,7 @@ func (s *CLITestSuite) TestCLIValidateSignatures() { sdk.NewCoin("stake", math.NewInt(10))) res, err := s.createBankMsg(s.clientCtx, s.val, sendTokens, - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly)) + clitestutil.TestTxConfig{GenOnly: true}) s.Require().NoError(err) // write unsigned tx to file @@ -151,7 +151,7 @@ func (s *CLITestSuite) TestCLISignBatch() { ) generatedStd, err := s.createBankMsg(s.clientCtx, s.val, - sendTokens, fmt.Sprintf("--%s=true", flags.FlagGenerateOnly)) + sendTokens, clitestutil.TestTxConfig{GenOnly: true}) s.Require().NoError(err) outputFile := testutil.WriteToNewTempFile(s.T(), strings.Repeat(generatedStd.String(), 3)) @@ -178,6 +178,7 @@ func (s *CLITestSuite) TestCLIQueryTxCmdByHash() { out, err := s.createBankMsg( s.clientCtx, s.val, sdk.NewCoins(sendTokens), + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) @@ -336,7 +337,7 @@ func (s *CLITestSuite) TestCLISendGenerateSignAndBroadcast() { sendTokens := sdk.NewCoin("stake", sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction)) normalGeneratedTx, err := s.createBankMsg(s.clientCtx, s.val, - sdk.NewCoins(sendTokens), fmt.Sprintf("--%s=true", flags.FlagGenerateOnly)) + sdk.NewCoins(sendTokens), clitestutil.TestTxConfig{GenOnly: true}) s.Require().NoError(err) txCfg := s.clientCtx.TxConfig @@ -353,8 +354,8 @@ func (s *CLITestSuite) TestCLISendGenerateSignAndBroadcast() { // Test generate sendTx with --gas=$amount limitedGasGeneratedTx, err := s.createBankMsg(s.clientCtx, s.val, - sdk.NewCoins(sendTokens), fmt.Sprintf("--gas=%d", 100), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + sdk.NewCoins(sendTokens), + clitestutil.TestTxConfig{GenOnly: true, Gas: 100}, ) s.Require().NoError(err) @@ -370,8 +371,7 @@ func (s *CLITestSuite) TestCLISendGenerateSignAndBroadcast() { // Test generate sendTx, estimate gas finalGeneratedTx, err := s.createBankMsg(s.clientCtx, s.val, - sdk.NewCoins(sendTokens), fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly)) + sdk.NewCoins(sendTokens), clitestutil.TestTxConfig{GenOnly: true}) s.Require().NoError(err) finalStdTx, err := txCfg.TxJSONDecoder()(finalGeneratedTx.Bytes()) @@ -454,23 +454,23 @@ func (s *CLITestSuite) TestCLIMultisignInsufficientCosigners() { sdk.NewCoins( sdk.NewInt64Coin("stake", 10), ), + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) - // Generate multisig transaction. - multiGeneratedTx, err := clitestutil.MsgSendExec( + msgSend := &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: s.val.String(), + Amount: sdk.NewCoins(sdk.NewInt64Coin("stake", 5)), + } + + multiGeneratedTx, err := clitestutil.SubmitTestTx( s.clientCtx, + msgSend, addr, - s.val, - sdk.NewCoins( - sdk.NewInt64Coin("stake", 5), - ), - s.ac, - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), - ) + clitestutil.TestTxConfig{ + GenOnly: true, + }) s.Require().NoError(err) // Save tx to file @@ -504,8 +504,10 @@ func (s *CLITestSuite) TestCLIEncode() { normalGeneratedTx, err := s.createBankMsg( s.clientCtx, s.val, sdk.NewCoins(sendTokens), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), - fmt.Sprintf("--%s=deadbeef", flags.FlagNote), + clitestutil.TestTxConfig{ + GenOnly: true, + Memo: "deadbeef", + }, ) s.Require().NoError(err) savedTxFile := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String()) @@ -546,20 +548,14 @@ func (s *CLITestSuite) TestCLIMultisignSortSignatures() { addr, err := multisigRecord.GetAddress() s.Require().NoError(err) + msgSend := &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: s.val.String(), + Amount: sdk.NewCoins(sdk.NewInt64Coin("stake", 5)), + } + // Generate multisig transaction. - multiGeneratedTx, err := clitestutil.MsgSendExec( - s.clientCtx, - addr, - s.val, - sdk.NewCoins( - sdk.NewInt64Coin("stake", 5), - ), - s.ac, - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), - ) + multiGeneratedTx, err := clitestutil.SubmitTestTx(s.clientCtx, msgSend, addr, clitestutil.TestTxConfig{GenOnly: true}) s.Require().NoError(err) // Save tx to file @@ -620,20 +616,14 @@ func (s *CLITestSuite) TestSignWithMultisig() { _, err = s.ac.StringToBytes(multisig) s.Require().NoError(err) + msgSend := &banktypes.MsgSend{ + FromAddress: s.val.String(), + ToAddress: s.val.String(), + Amount: sdk.NewCoins(sdk.NewInt64Coin("stake", 5)), + } + // Generate a transaction for testing --multisig with an address not in the keyring. - multisigTx, err := clitestutil.MsgSendExec( - s.clientCtx, - s.val, - s.val, - sdk.NewCoins( - sdk.NewInt64Coin("stake", 5), - ), - s.ac, - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), - ) + multisigTx, err := clitestutil.SubmitTestTx(s.clientCtx, msgSend, s.val, clitestutil.TestTxConfig{GenOnly: true}) s.Require().NoError(err) // Save multi tx to file @@ -662,20 +652,14 @@ func (s *CLITestSuite) TestCLIMultisign() { addr, err := multisigRecord.GetAddress() s.Require().NoError(err) + msgSend := &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: s.val.String(), + Amount: sdk.NewCoins(sdk.NewInt64Coin("stake", 5)), + } + // Generate multisig transaction. - multiGeneratedTx, err := clitestutil.MsgSendExec( - s.clientCtx, - addr, - s.val, - sdk.NewCoins( - sdk.NewInt64Coin("stake", 5), - ), - s.ac, - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), - ) + multiGeneratedTx, err := clitestutil.SubmitTestTx(s.clientCtx, msgSend, addr, clitestutil.TestTxConfig{GenOnly: true}) s.Require().NoError(err) // Save tx to file @@ -734,22 +718,17 @@ func (s *CLITestSuite) TestSignBatchMultisig() { s.clientCtx, addr, sdk.NewCoins(sendTokens), + clitestutil.TestTxConfig{}, ) s.Require().NoError(err) - generatedStd, err := clitestutil.MsgSendExec( - s.clientCtx, - addr, - s.val, - sdk.NewCoins( - sdk.NewCoin("stake", math.NewInt(1)), - ), - s.ac, - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), - ) + msgSend := &banktypes.MsgSend{ + FromAddress: addr.String(), + ToAddress: s.val.String(), + Amount: sdk.NewCoins(sdk.NewInt64Coin("stake", 5)), + } + + generatedStd, err := clitestutil.SubmitTestTx(s.clientCtx, msgSend, addr, clitestutil.TestTxConfig{GenOnly: true}) s.Require().NoError(err) // Write the output to disk @@ -1008,7 +987,7 @@ func (s *CLITestSuite) TestAuxToFeeWithTips() { fee := sdk.NewCoin("stake", math.NewInt(1000)) tip := sdk.NewCoin("testtoken", math.NewInt(1000)) - _, err = s.createBankMsg(s.clientCtx, tipper, sdk.NewCoins(tipperInitialBal)) + _, err = s.createBankMsg(s.clientCtx, tipper, sdk.NewCoins(tipperInitialBal), clitestutil.TestTxConfig{}) require.NoError(err) bal := s.getBalances(s.clientCtx, tipper, tip.Denom) @@ -1249,14 +1228,12 @@ func (s *CLITestSuite) getBalances(clientCtx client.Context, addr sdk.AccAddress return startTokens } -func (s *CLITestSuite) createBankMsg(clientCtx client.Context, 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), - fmt.Sprintf("--%s=%s", flags.FlagFees, - sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), +func (s *CLITestSuite) createBankMsg(clientCtx client.Context, toAddr sdk.AccAddress, amount sdk.Coins, cfg clitestutil.TestTxConfig) (testutil.BufferWriter, error) { + msgSend := &banktypes.MsgSend{ + FromAddress: s.val.String(), + ToAddress: toAddr.String(), + Amount: amount, } - flags = append(flags, extraFlags...) - return clitestutil.MsgSendExec(clientCtx, s.val, toAddr, amount, s.ac, flags...) + return clitestutil.SubmitTestTx(clientCtx, msgSend, s.val, cfg) } diff --git a/testutil/cli/cmd.go b/testutil/cli/cmd.go index 67d419155079..11aaa4e38ca4 100644 --- a/testutil/cli/cmd.go +++ b/testutil/cli/cmd.go @@ -3,23 +3,18 @@ package cli import ( "bytes" "context" - "fmt" "github.com/cosmos/gogoproto/proto" "github.com/spf13/cobra" - "cosmossdk.io/core/address" - sdkmath "cosmossdk.io/math" "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/testutil" - "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" txtypes "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/types/tx/signing" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) // ExecTestCLICmd builds the client context, mocks the output and executes the command. @@ -39,84 +34,43 @@ func ExecTestCLICmd(clientCtx client.Context, cmd *cobra.Command, extraArgs []st return out, nil } -func MsgSendExec(clientCtx client.Context, from, to, amount fmt.Stringer, ac address.Codec, extraArgs ...string) (testutil.BufferWriter, error) { - args := []string{from.String(), to.String(), amount.String()} - args = append(args, extraArgs...) - - coins, err := sdk.ParseCoinsNormalized(amount.String()) - if err != nil { - return nil, err - } +type TestTxConfig struct { + Simulate bool + GenOnly bool + Offline bool + Memo string + Gas uint64 + AccNum uint64 + Seq uint64 + Fee sdk.Coins + IsAsyncBroadcastMode bool +} +func SubmitTestTx(clientCtx client.Context, msg proto.Message, from sdk.AccAddress, config TestTxConfig) (testutil.BufferWriter, error) { txBuilder := clientCtx.TxConfig.NewTxBuilder() - msgSend := banktypes.MsgSend{ - FromAddress: from.String(), - ToAddress: to.String(), - Amount: coins, - } - - fee := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(0))) - txBuilder.SetFeeAmount(fee) // Arbitrary fee - txBuilder.SetGasLimit(1000000) // Need at least 100386 - - err = txBuilder.SetMsgs(&msgSend) - if err != nil { - return nil, err - } - - txFactory := tx.Factory{} - txFactory = txFactory. - WithChainID(clientCtx.ChainID). - WithKeybase(clientCtx.Keyring). - WithTxConfig(clientCtx.TxConfig) - - accBytes, err := clientCtx.AddressCodec.StringToBytes(from.String()) - if err != nil { - return nil, err - } - keyRecord, err := clientCtx.Keyring.KeyByAddress(accBytes) - if err != nil { - return nil, err - } - - err = tx.Sign(context.Background(), txFactory, keyRecord.Name, txBuilder, true) + err := txBuilder.SetMsgs(msg) if err != nil { return nil, err } - txBz, err := clientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) - if err != nil { - return nil, err + if config.Fee != nil { + txBuilder.SetFeeAmount(config.Fee) + } else { + txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10)))) // Arbitrary fee } - req := &txtypes.BroadcastTxRequest{ - TxBytes: txBz, - Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC, + if config.Gas != 0 { + txBuilder.SetGasLimit(config.Gas) + } else { + txBuilder.SetGasLimit(flags.DefaultGasLimit) // Need at least 100386 } - serviceClient := txtypes.NewServiceClient(clientCtx) - resp, err := serviceClient.BroadcastTx(context.Background(), req) - - fmt.Println("Resp", resp, err, resp.TxResponse.Code) - - // return resp, err - return nil, nil -} - -func GenOrBroadcastTestTx(clientCtx client.Context, msg proto.Message, from sdk.AccAddress, generateonly bool) (testutil.BufferWriter, error) { - txBuilder := clientCtx.TxConfig.NewTxBuilder() - - fee := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))) - txBuilder.SetFeeAmount(fee) // Arbitrary fee - txBuilder.SetGasLimit(1000000) // Need at least 100386 - - err := txBuilder.SetMsgs(msg) - if err != nil { - return nil, err + if config.Memo != "" { + txBuilder.SetMemo(config.Memo) } - if generateonly { + if config.GenOnly { txBz, err := clientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) if err != nil { return nil, err @@ -133,6 +87,21 @@ func GenOrBroadcastTestTx(clientCtx client.Context, msg proto.Message, from sdk. WithTxConfig(clientCtx.TxConfig). WithSignMode(signing.SignMode_SIGN_MODE_DIRECT) + if config.Offline { + txFactory = txFactory. + WithAccountNumber(config.AccNum). + WithSequence(config.Seq) + } else { + accNum, accSeq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, from) + if err != nil { + return nil, err + } + + txFactory = txFactory. + WithAccountNumber(accNum). + WithSequence(accSeq) + } + accBytes, err := clientCtx.AddressCodec.StringToBytes(from.String()) if err != nil { return nil, err @@ -153,105 +122,35 @@ func GenOrBroadcastTestTx(clientCtx client.Context, msg proto.Message, from sdk. return nil, err } - req := &txtypes.BroadcastTxRequest{ - TxBytes: txBz, - Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC, - } - - serviceClient := txtypes.NewServiceClient(clientCtx) - resp, err := serviceClient.BroadcastTx(context.Background(), req) - if err != nil { - return nil, err - } - - respBz, err := clientCtx.Codec.Marshal(resp) - if err != nil { - return nil, err + clientCtx.BroadcastMode = flags.BroadcastSync + if config.IsAsyncBroadcastMode { + clientCtx.BroadcastMode = flags.BroadcastAsync } - out := bytes.NewBuffer(respBz) - return out, nil -} - -type SubmitTestTxConfig struct { - Simulate bool - GenOnly bool - Memo string - Gas uint64 -} - -func SubmitTestTx(val *network.Validator, msg proto.Message, from sdk.AccAddress, config SubmitTestTxConfig) (testutil.BufferWriter, error) { - clientCtx := val.ClientCtx - txBuilder := clientCtx.TxConfig.NewTxBuilder() - - err := txBuilder.SetMsgs(msg) - if err != nil { - return nil, err - } + var res proto.Message - fee := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))) - txBuilder.SetFeeAmount(fee) // Arbitrary fee + if config.Simulate { + txSvcClient := txtypes.NewServiceClient(clientCtx) + res, err = txSvcClient.Simulate(context.Background(), &txtypes.SimulateRequest{ + TxBytes: txBz, + }) + if err != nil { + return nil, err + } - if config.Gas != 0 { - txBuilder.SetGasLimit(config.Gas) } else { - txBuilder.SetGasLimit(flags.DefaultGasLimit) // Need at least 100386 - } - - if config.Memo != "" { - txBuilder.SetMemo(config.Memo) - } - - if config.GenOnly { - txBz, err := val.ClientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) + res, err = clientCtx.BroadcastTxSync(txBz) if err != nil { return nil, err } - - out := bytes.NewBuffer(txBz) - return out, nil - } - - acc, err := clientCtx.AccountRetriever.GetAccount(clientCtx, from) - if err != nil { - return nil, err - } - - txFactory := tx.Factory{} - txFactory = txFactory. - WithChainID(clientCtx.ChainID). - WithKeybase(clientCtx.Keyring). - WithTxConfig(clientCtx.TxConfig). - WithSignMode(signing.SignMode_SIGN_MODE_DIRECT). - WithAccountNumber(acc.GetAccountNumber()). - WithSequence(acc.GetSequence()) - - if config.Simulate { - txFactory = txFactory.WithSimulateAndExecute(true) - } - - accBytes, err := clientCtx.AddressCodec.StringToBytes(from.String()) - if err != nil { - return nil, err - } - - keyRecord, err := clientCtx.Keyring.KeyByAddress(accBytes) - if err != nil { - return nil, err - } - - err = tx.Sign(context.Background(), txFactory, keyRecord.Name, txBuilder, true) - if err != nil { - return nil, err } - txBz, err := val.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx()) + bz, err := clientCtx.Codec.MarshalJSON(res) if err != nil { return nil, err } - res, err := val.BroadcastTx(txBz) - out := bytes.NewBuffer(res) + out := bytes.NewBuffer(bz) return out, err } diff --git a/testutil/network/network.go b/testutil/network/network.go index 661120cc9a86..8fc1266045f8 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -52,7 +52,6 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - txtypes "github.com/cosmos/cosmos-sdk/types/tx" _ "github.com/cosmos/cosmos-sdk/x/auth" // import auth as a blank _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import auth tx config as a blank authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -328,19 +327,6 @@ func (v Validator) GetAppConfig() *srvconfig.Config { return v.AppConfig } -func (v Validator) BroadcastTx(txBytes []byte) ([]byte, error) { - txReq := &txtypes.BroadcastTxRequest{ - Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC, - TxBytes: txBytes, - } - req, err := v.ClientCtx.Codec.MarshalJSON(txReq) - if err != nil { - return nil, err - } - - return testutil.PostRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs", v.APIAddress), "application/json", req) -} - // CLILogger wraps a cobra.Command and provides command logging methods. type CLILogger struct { cmd *cobra.Command diff --git a/x/authz/client/cli/tx_test.go b/x/authz/client/cli/tx_test.go index bc4dba6de1ae..100293f9a6fd 100644 --- a/x/authz/client/cli/tx_test.go +++ b/x/authz/client/cli/tx_test.go @@ -61,6 +61,7 @@ func TestCLITestSuite(t *testing.T) { func (s *CLITestSuite) SetupSuite() { s.encCfg = testutilmod.MakeTestEncodingConfig(gov.AppModuleBasic{}, bank.AppModuleBasic{}) s.kr = keyring.NewInMemory(s.encCfg.Codec) + s.baseCtx = client.Context{}. WithKeyring(s.kr). WithTxConfig(s.encCfg.TxConfig). @@ -188,7 +189,7 @@ func (s *CLITestSuite) msgSendExec(grantee sdk.AccAddress) { Amount: coins, } - _, err = clitestutil.GenOrBroadcastTestTx(s.clientCtx, msgSend, from, false) + _, err = clitestutil.SubmitTestTx(s.clientCtx, msgSend, from, clitestutil.TestTxConfig{}) s.Require().NoError(err) } @@ -773,11 +774,11 @@ func (s *CLITestSuite) TestNewExecGrantAuthorized() { ToAddress: grantee.String(), Amount: tokens, } - normalGeneratedTx, err := clitestutil.GenOrBroadcastTestTx( + normalGeneratedTx, err := clitestutil.SubmitTestTx( s.clientCtx, msgSend, from, - true, + clitestutil.TestTxConfig{GenOnly: true}, ) s.Require().NoError(err) execMsg := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String()) @@ -871,11 +872,11 @@ func (s *CLITestSuite) TestExecSendAuthzWithAllowList() { ToAddress: grantee.String(), Amount: tokens, } - validGeneratedTx, err := clitestutil.GenOrBroadcastTestTx( + validGeneratedTx, err := clitestutil.SubmitTestTx( s.clientCtx, msgSend, from, - true, + clitestutil.TestTxConfig{GenOnly: true}, ) s.Require().NoError(err) @@ -887,11 +888,11 @@ func (s *CLITestSuite) TestExecSendAuthzWithAllowList() { ToAddress: notAllowedAddr.String(), Amount: tokens, } - invalidGeneratedTx, err := clitestutil.GenOrBroadcastTestTx( + invalidGeneratedTx, err := clitestutil.SubmitTestTx( s.clientCtx, msgSend1, from, - true, + clitestutil.TestTxConfig{GenOnly: true}, ) s.Require().NoError(err) diff --git a/x/group/client/cli/tx_test.go b/x/group/client/cli/tx_test.go index c8337df7f453..79932c58e6ce 100644 --- a/x/group/client/cli/tx_test.go +++ b/x/group/client/cli/tx_test.go @@ -99,7 +99,7 @@ func (s *CLITestSuite) SetupSuite() { Amount: coins, } - clitestutil.GenOrBroadcastTestTx(s.clientCtx, msgSend, from, false) + _, err = clitestutil.SubmitTestTx(s.clientCtx, msgSend, from, clitestutil.TestTxConfig{}) s.Require().NoError(err) // create a group diff --git a/x/nft/client/cli/tx_test.go b/x/nft/client/cli/tx_test.go index bd0068a324e2..0071dcc98818 100644 --- a/x/nft/client/cli/tx_test.go +++ b/x/nft/client/cli/tx_test.go @@ -27,6 +27,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) const ( @@ -87,6 +88,7 @@ func TestCLITestSuite(t *testing.T) { func (s *CLITestSuite) SetupSuite() { s.encCfg = testutilmod.MakeTestEncodingConfig(nftmodule.AppModuleBasic{}) + banktypes.RegisterInterfaces(s.encCfg.InterfaceRegistry) s.kr = keyring.NewInMemory(s.encCfg.Codec) s.baseCtx = client.Context{}. WithKeyring(s.kr). @@ -227,16 +229,21 @@ func (s *CLITestSuite) initAccount() { keyinfo, err := ctx.Keyring.Key(OwnerName) s.Require().NoError(err) - args := []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), - } - s.owner, err = keyinfo.GetAddress() s.Require().NoError(err) amount := sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(200))) - _, err = clitestutil.MsgSendExec(ctx, accounts[0].Address, s.owner, amount, s.ac, args...) + msgSend := &banktypes.MsgSend{ + FromAddress: accounts[0].Address.String(), + ToAddress: s.owner.String(), + Amount: amount, + } + + _, err = clitestutil.SubmitTestTx( + s.clientCtx, + msgSend, + accounts[0].Address, + clitestutil.TestTxConfig{GenOnly: true}, + ) s.Require().NoError(err) } From 4fefd8cb3be7fd07d13c1f55b23d07ed10663375 Mon Sep 17 00:00:00 2001 From: atheesh Date: Thu, 28 Sep 2023 20:39:43 +0530 Subject: [PATCH 06/20] fix tests --- tests/e2e/tx/benchmarks_test.go | 10 +++++----- tests/e2e/tx/service_test.go | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/e2e/tx/benchmarks_test.go b/tests/e2e/tx/benchmarks_test.go index a5875e727279..fba472d03c0c 100644 --- a/tests/e2e/tx/benchmarks_test.go +++ b/tests/e2e/tx/benchmarks_test.go @@ -118,9 +118,9 @@ func NewE2EBenchmarkSuite(tb testing.TB) *E2EBenchmarkSuite { assert.NilError(tb, err) - var txRes tx.BroadcastTxResponse + var txRes sdk.TxResponse assert.NilError(tb, val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes)) - assert.Equal(tb, uint32(0), txRes.TxResponse.Code, txRes) + assert.Equal(tb, uint32(0), txRes.Code, txRes) msgSend1 := &banktypes.MsgSend{ FromAddress: val.Address.String(), @@ -141,11 +141,11 @@ func NewE2EBenchmarkSuite(tb testing.TB) *E2EBenchmarkSuite { ) assert.NilError(tb, err) - var tr tx.BroadcastTxResponse + var tr sdk.TxResponse assert.NilError(tb, val.ClientCtx.Codec.UnmarshalJSON(out1.Bytes(), &tr)) - assert.Equal(tb, uint32(0), tr.TxResponse.Code) + assert.Equal(tb, uint32(0), tr.Code) - resp, err := cli.GetTxResponse(s.network, val.ClientCtx, tr.TxResponse.TxHash) + resp, err := cli.GetTxResponse(s.network, val.ClientCtx, tr.TxHash) assert.NilError(tb, err) s.txHeight = resp.Height return s diff --git a/tests/e2e/tx/service_test.go b/tests/e2e/tx/service_test.go index 9b93fab6ba87..7a076b57ec8b 100644 --- a/tests/e2e/tx/service_test.go +++ b/tests/e2e/tx/service_test.go @@ -83,10 +83,10 @@ func (s *E2ETestSuite) SetupSuite() { s.Require().NoError(err) - var txRes tx.BroadcastTxResponse + var txRes sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txRes)) - s.Require().Equal(uint32(0), txRes.TxResponse.Code, txRes) - s.goodTxHash = txRes.TxResponse.TxHash + s.Require().Equal(uint32(0), txRes.Code, txRes) + s.goodTxHash = txRes.TxHash msgSend1 := &banktypes.MsgSend{ FromAddress: val.Address.String(), @@ -107,11 +107,11 @@ func (s *E2ETestSuite) SetupSuite() { ) s.Require().NoError(err) - var tr tx.BroadcastTxResponse + var tr sdk.TxResponse s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out1.Bytes(), &tr)) - s.Require().Equal(uint32(0), tr.TxResponse.Code) + s.Require().Equal(uint32(0), tr.Code) - resp, err := cli.GetTxResponse(s.network, val.ClientCtx, tr.TxResponse.TxHash) + resp, err := cli.GetTxResponse(s.network, val.ClientCtx, tr.TxHash) s.Require().NoError(err) s.txHeight = resp.Height } From 4743c2e53685273e05938e63cec6262b447ef6f4 Mon Sep 17 00:00:00 2001 From: atheesh Date: Tue, 3 Oct 2023 14:32:53 +0530 Subject: [PATCH 07/20] fix autocli --- x/bank/autocli.go | 8 ++++++-- x/crisis/autocli.go | 8 ++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/x/bank/autocli.go b/x/bank/autocli.go index 2c92ef5b99dd..9bd39d53d94d 100644 --- a/x/bank/autocli.go +++ b/x/bank/autocli.go @@ -88,7 +88,8 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { }, }, Tx: &autocliv1.ServiceCommandDescriptor{ - Service: bankv1beta1.Msg_ServiceDesc.ServiceName, + Service: bankv1beta1.Msg_ServiceDesc.ServiceName, + EnhanceCustomCommand: true, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { RpcMethod: "Send", @@ -97,7 +98,10 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Long: `Send funds from one account to another. Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. When using '--dry-run' a key name cannot be used, only a bech32 address.`, - PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "invariant_module_name"}, {ProtoField: "invariant_route"}}, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to"}, {ProtoField: "amount"}}, + FlagOptions: map[string]*autocliv1.FlagOptions{ + "sender": {Name: "from", Shorthand: "f", Usage: "Address of the sender"}, + }, }, }, }, diff --git a/x/crisis/autocli.go b/x/crisis/autocli.go index a99fd4c713b5..2a979f63cfc8 100644 --- a/x/crisis/autocli.go +++ b/x/crisis/autocli.go @@ -9,17 +9,13 @@ import ( func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { return &autocliv1.ModuleOptions{ Tx: &autocliv1.ServiceCommandDescriptor{ - Service: crisisv1beta1.Msg_ServiceDesc.ServiceName, - EnhanceCustomCommand: true, + Service: crisisv1beta1.Msg_ServiceDesc.ServiceName, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { RpcMethod: "VerifyInvariant", Use: "invariant-broken [module-name] [invariant-route]", Short: "Submit proof that an invariant broken to halt the chain", - PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to"}, {ProtoField: "amount"}}, - FlagOptions: map[string]*autocliv1.FlagOptions{ - "sender": {Name: "from", Shorthand: "f", Usage: "Address of the sender"}, - }, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "invariant_module_name"}, {ProtoField: "invariant_route"}}, }, }, }, From a58fcbe4f5c116722b1c64cd9f467ba03d85086f Mon Sep 17 00:00:00 2001 From: atheesh Date: Tue, 3 Oct 2023 15:04:12 +0530 Subject: [PATCH 08/20] fix lint --- testutil/cli/cmd.go | 1 + 1 file changed, 1 insertion(+) diff --git a/testutil/cli/cmd.go b/testutil/cli/cmd.go index 11aaa4e38ca4..90093fb0ec8b 100644 --- a/testutil/cli/cmd.go +++ b/testutil/cli/cmd.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/cobra" sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" From a527e05a3eba27be9ae21c81f55bc37f5091dfcf Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Wed, 4 Oct 2023 14:06:32 +0200 Subject: [PATCH 09/20] feat(client/v2): signing --- CHANGELOG.md | 4 +- client/flags/flags.go | 4 +- client/tx/factory.go | 7 +- client/tx/tx.go | 2 +- client/v2/Makefile | 2 +- client/v2/README.md | 25 +++- client/v2/autocli/app.go | 33 ++--- client/v2/autocli/builder.go | 49 ++++---- client/v2/autocli/common.go | 34 ++++- client/v2/autocli/common_test.go | 29 +++-- client/v2/autocli/flag/address.go | 11 +- client/v2/autocli/flag/builder.go | 119 +++++++++++++----- client/v2/autocli/flag/messager_binder.go | 26 ++-- client/v2/autocli/flags.go | 3 - client/v2/autocli/keyring/interface.go | 17 +++ client/v2/autocli/keyring/no_keyring.go | 24 +++- client/v2/autocli/msg.go | 59 +++++---- client/v2/autocli/query.go | 10 +- .../testdata/help-deprecated-msg.golden | 1 - .../v2/autocli/testdata/help-echo-msg.golden | 1 - client/v2/go.mod | 14 ++- client/v2/go.sum | 52 ++++++-- client/v2/internal/flags/flags.go | 19 +++ codec/bench_test.go | 14 ++- codec/types/any.go | 26 +++- codec/types/interface_registry.go | 2 +- codec/types/util.go | 15 +++ crypto/keyring/autocli.go | 86 +++++++++++++ crypto/keyring/keyring.go | 18 --- simapp/simd/cmd/root.go | 5 +- simapp/simd/cmd/root_v2.go | 19 ++- types/tx_msg.go | 9 +- x/auth/signing/sig_verifiable_tx.go | 2 +- x/bank/types/msgs.go | 6 - 34 files changed, 542 insertions(+), 205 deletions(-) delete mode 100644 client/v2/autocli/flags.go create mode 100644 client/v2/internal/flags/flags.go create mode 100644 codec/types/util.go create mode 100644 crypto/keyring/autocli.go diff --git a/CHANGELOG.md b/CHANGELOG.md index c322f4c07df4..72dc04203087 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (keyring) [#17913](https://github.com/cosmos/cosmos-sdk/pull/17913) Add `NewAutoCLIKeyring` for creating an AutoCLI keyring from a SDK keyring. +* (codec) [#17913](https://github.com/cosmos/cosmos-sdk/pull/17913) `codectypes.NewAnyWithValue` supports proto v2 messages. * (client) [#17503](https://github.com/cosmos/cosmos-sdk/pull/17503) Add `client.Context{}.WithAddressCodec`, `WithValidatorAddressCodec`, `WithConsensusAddressCodec` to provide address codecs to the client context. See the [UPGRADING.md](./UPGRADING.md) for more details. * (crypto/keyring) [#17503](https://github.com/cosmos/cosmos-sdk/pull/17503) Simplify keyring interfaces to use `[]byte` instead of `sdk.Address` for addresses. * (all) [#16537](https://github.com/cosmos/cosmos-sdk/pull/16537) Properly propagated `fmt.Errorf` errors and using `errors.New` where appropriate. @@ -65,7 +67,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/distribution) [#17657](https://github.com/cosmos/cosmos-sdk/pull/17657) The `FundCommunityPool` and `DistributeFromFeePool` keeper methods are now removed from x/distribution. * (x/distribution) [#17657](https://github.com/cosmos/cosmos-sdk/pull/17657) The distribution module keeper now takes a new argument `PoolKeeper` in addition. * (app) [#17838](https://github.com/cosmos/cosmos-sdk/pull/17838) Params module was removed from simapp and all imports of the params module removed throughout the repo. - * The Cosmos SDK has migrated aay from using params, if you're app still uses it, then you can leave it plugged into your app + * The Cosmos SDK has migrated away from using params, if your app still uses it, then you can leave it plugged into your app * (x/staking) [#17778](https://github.com/cosmos/cosmos-sdk/pull/17778) Use collections for `Params` * remove from `Keeper`: `GetParams`, `SetParams` * (types/simulation) [#17737](https://github.com/cosmos/cosmos-sdk/pull/17737) Remove unused parameter from `RandomFees` diff --git a/client/flags/flags.go b/client/flags/flags.go index e58cabca6389..06458e2d4411 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -117,7 +117,9 @@ func AddQueryFlagsToCmd(cmd *cobra.Command) { func AddTxFlagsToCmd(cmd *cobra.Command) { f := cmd.Flags() f.StringP(FlagOutput, "o", OutputFormatJSON, "Output format (text|json)") - f.String(FlagFrom, "", "Name or address of private key with which to sign") + if cmd.Flag(FlagFrom) == nil { // avoid flag redefinition when it's already been added by AutoCLI + f.String(FlagFrom, "", "Name or address of private key with which to sign") + } f.Uint64P(FlagAccountNumber, "a", 0, "The account number of the signing account (offline mode only)") f.Uint64P(FlagSequence, "s", 0, "The sequence number of the signing account (offline mode only)") f.String(FlagNote, "", "Note to add a description to the transaction (previously --memo)") diff --git a/client/tx/factory.go b/client/tx/factory.go index f21d861f3bb5..81ce5784d5ac 100644 --- a/client/tx/factory.go +++ b/client/tx/factory.go @@ -419,7 +419,12 @@ func (f Factory) BuildSimTx(msgs ...sdk.Msg) ([]byte, error) { return nil, err } - return f.txConfig.TxEncoder()(txb.GetTx()) + encoder := f.txConfig.TxEncoder() + if encoder == nil { + return nil, fmt.Errorf("cannot simulate tx: tx encoder is nil") + } + + return encoder(txb.GetTx()) } // getSimPK gets the public key to use for building a simulation tx. diff --git a/client/tx/tx.go b/client/tx/tx.go index b7c665362358..8d905922cad8 100644 --- a/client/tx/tx.go +++ b/client/tx/tx.go @@ -107,7 +107,7 @@ func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error { txBytes, err := encoder(tx.GetTx()) if err != nil { - return err + return fmt.Errorf("failed to encode transaction: %w", err) } if err := clientCtx.PrintRaw(json.RawMessage(txBytes)); err != nil { diff --git a/client/v2/Makefile b/client/v2/Makefile index 6868d1941a36..1b4bb0cbe7f6 100644 --- a/client/v2/Makefile +++ b/client/v2/Makefile @@ -1,2 +1,2 @@ codegen: - @(cd internal; buf generate) + @(cd internal; buf generate) \ No newline at end of file diff --git a/client/v2/README.md b/client/v2/README.md index 516c7f49569e..e5458ea9a9a5 100644 --- a/client/v2/README.md +++ b/client/v2/README.md @@ -75,7 +75,7 @@ if err := rootCmd.Execute(); err != nil { ### Keyring -`autocli` supports a keyring for key name resolving and signing transactions. Providing a keyring is optional, but if you want to use the `autocli` generated commands to sign transactions, you must provide a keyring. +`autocli` uses a keyring for key name resolving and signing transactions. Providing a keyring is optional, but if you want to use the `autocli` generated commands to sign transactions, you must provide a keyring. :::tip This provides a better UX as it allows to resolve key names directly from the keyring in all transactions and commands. @@ -87,16 +87,23 @@ This provides a better UX as it allows to resolve key names directly from the ke ::: -The keyring to be provided to `client/v2` must match the `client/v2` keyring interface. The Cosmos SDK keyring and Hubl keyring both implement this interface. +The keyring to be provided to `client/v2` must match the `client/v2` keyring interface. The keyring should be provided in the `appOptions` struct as follows, and can be gotten from the client context: +:::tip +The Cosmos SDK keyring and Hubl keyring both implement the `client/v2/autocli/keyring` interface, thanks to the following wrapper: + +```go +keyring.NewAutoCLIKeyring(kb) +``` + +::: + :::warning When using AutoCLI the keyring will only be created once and before any command flag parsing. ::: ```go -// Get the keyring from the client context -keyring := ctx.Keyring // Set the keyring in the appOptions appOptions.Keyring = keyring @@ -104,6 +111,16 @@ err := autoCliOpts.EnhanceRootCommand(rootCmd) ... ``` +## Signing + +`autocli` supports signing transactions with the keyring. +The [`cosmos.msg.v1.signer` protobuf annotation](https://github.com/cosmos/cosmos-sdk/blob/9dd34510e27376005e7e7ff3628eab9dbc8ad6dc/docs/build/building-modules/05-protobuf-annotations.md#L9) defines the signer field of the message. +This field is automatically filled when using the `--from` flag or defining the signer as a positional argument. + +:::warning +AutoCLI currently supports only one signer per transaction. +::: + ## Module Wiring & Customization The `AutoCLIOptions()` method on your module allows to specify custom commands, sub-commands or flags for each service, as it was a `cobra.Command` instance, within the `RpcCommandOptions` struct. Defining such options will customize the behavior of the `autocli` command generation, which by default generates a command for each method in your gRPC service. diff --git a/client/v2/autocli/app.go b/client/v2/autocli/app.go index 5133d822c66a..052b660e1573 100644 --- a/client/v2/autocli/app.go +++ b/client/v2/autocli/app.go @@ -11,10 +11,10 @@ import ( "cosmossdk.io/client/v2/autocli/keyring" "cosmossdk.io/core/appmodule" "cosmossdk.io/depinject" - "cosmossdk.io/log" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" + sdkflags "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/x/auth/tx" ) // AppOptions are autocli options for an app. These options can be built via depinject based on an app config. Ex: @@ -28,9 +28,6 @@ import ( type AppOptions struct { depinject.In - // Logger is the logger to use for client/v2. - Logger log.Logger - // Modules are the AppModule implementations for the modules in the app. Modules map[string]appmodule.AppModule @@ -40,11 +37,14 @@ type AppOptions struct { // module or need to be improved. ModuleOptions map[string]*autocliv1.ModuleOptions `optional:"true"` - // ClientCtx contains the necessary information needed to execute the commands. - ClientCtx *client.Context - // Keyring is the keyring to use for client/v2. Keyring keyring.Keyring `optional:"true"` + + // ClientCtx contains the necessary information needed to execute the commands. + ClientCtx client.Context + + // TxConfigOptions are the transactions config options. + TxConfigOpts tx.ConfigOptions } // EnhanceRootCommand enhances the provided root command with autocli AppOptions, @@ -64,18 +64,21 @@ type AppOptions struct { // err = autoCliOpts.EnhanceRootCommand(rootCmd) func (appOptions AppOptions) EnhanceRootCommand(rootCmd *cobra.Command) error { builder := &Builder{ - Logger: appOptions.Logger, Builder: flag.Builder{ - TypeResolver: protoregistry.GlobalTypes, - FileResolver: proto.HybridResolver, - ClientCtx: appOptions.ClientCtx, - Keyring: appOptions.Keyring, + TypeResolver: protoregistry.GlobalTypes, + FileResolver: proto.HybridResolver, + Keyring: appOptions.Keyring, + AddressCodec: appOptions.ClientCtx.AddressCodec, + ValidatorAddressCodec: appOptions.ClientCtx.ValidatorAddressCodec, + ConsensusAddressCodec: appOptions.ClientCtx.ConsensusAddressCodec, }, + ClientCtx: appOptions.ClientCtx, + TxConfigOpts: appOptions.TxConfigOpts, GetClientConn: func(cmd *cobra.Command) (grpc.ClientConnInterface, error) { return client.GetClientQueryContext(cmd) }, - AddQueryConnFlags: flags.AddQueryFlagsToCmd, - AddTxConnFlags: flags.AddTxFlagsToCmd, + AddQueryConnFlags: sdkflags.AddQueryFlagsToCmd, + AddTxConnFlags: sdkflags.AddTxFlagsToCmd, } return appOptions.EnhanceRootCommandWithBuilder(rootCmd, builder) diff --git a/client/v2/autocli/builder.go b/client/v2/autocli/builder.go index ef2299d32783..f92147df324b 100644 --- a/client/v2/autocli/builder.go +++ b/client/v2/autocli/builder.go @@ -8,7 +8,9 @@ import ( "cosmossdk.io/client/v2/autocli/flag" "cosmossdk.io/client/v2/autocli/keyring" - "cosmossdk.io/log" + + "github.com/cosmos/cosmos-sdk/client" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" ) // Builder manages options for building CLI commands. @@ -16,13 +18,16 @@ type Builder struct { // flag.Builder embeds the flag builder and its options. flag.Builder - // Logger is the logger used by the builder. - Logger log.Logger - // GetClientConn specifies how CLI commands will resolve a grpc.ClientConnInterface // from a given context. GetClientConn func(*cobra.Command) (grpc.ClientConnInterface, error) + // ClientCtx contains the necessary information needed to execute the commands. + ClientCtx client.Context + + // TxConfigOptions is required to support sign mode textual + TxConfigOpts authtx.ConfigOptions + // AddQueryConnFlags and AddTxConnFlags are functions that add flags to query and transaction commands AddQueryConnFlags func(*cobra.Command) AddTxConnFlags func(*cobra.Command) @@ -33,40 +38,28 @@ type Builder struct { // If the Logger is nil, it will be set to a nop logger. // If the keyring is nil, it will be set to a no keyring. func (b *Builder) ValidateAndComplete() error { - if b.Logger == nil { - b.Logger = log.NewNopLogger() - } - - if b.ClientCtx == nil { - return errors.New("client context is required in builder") - } - - if b.ClientCtx.AddressCodec == nil { - return errors.New("address codec is required in builder") + if b.Builder.AddressCodec == nil { + return errors.New("address codec is required in flag builder") } - if b.ClientCtx.ValidatorAddressCodec == nil { - return errors.New("validator address codec is required in builder") + if b.Builder.ValidatorAddressCodec == nil { + return errors.New("validator address codec is required in flag builder") } - if b.ClientCtx.ConsensusAddressCodec == nil { - return errors.New("consensus address codec is required in builder") + if b.Builder.ConsensusAddressCodec == nil { + return errors.New("consensus address codec is required in flag builder") } - if b.Keyring == nil { - if b.ClientCtx.Keyring != nil { - b.Keyring = b.ClientCtx.Keyring - } else { - b.Keyring = keyring.NoKeyring{} - } + if b.Builder.Keyring == nil { + b.Keyring = keyring.NoKeyring{} } - if b.TypeResolver == nil { - return errors.New("type resolver is required in builder") + if b.Builder.TypeResolver == nil { + return errors.New("type resolver is required in flag builder") } - if b.FileResolver == nil { - return errors.New("file resolver is required in builder") + if b.Builder.FileResolver == nil { + return errors.New("file resolver is required in flag builder") } return nil diff --git a/client/v2/autocli/common.go b/client/v2/autocli/common.go index 480faacd1eb2..f6aa375e0852 100644 --- a/client/v2/autocli/common.go +++ b/client/v2/autocli/common.go @@ -10,9 +10,8 @@ import ( "sigs.k8s.io/yaml" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + "cosmossdk.io/client/v2/internal/flags" "cosmossdk.io/client/v2/internal/util" - - "github.com/cosmos/cosmos-sdk/client/flags" ) type cmdType int @@ -67,6 +66,37 @@ func (b *Builder) buildMethodCommandCommon(descriptor protoreflect.MethodDescrip return err } + // signer related logic, triggers only when there is a signer defined + if binder.SignerInfo.FieldName != "" { + // mark the signer flag as required if defined + // TODO(@julienrbrt): UX improvement by only marking the flag as required when there is more than one key in the keyring; + // when there is only one key, use that key by default. + if binder.SignerInfo.IsFlag { + if err := cmd.MarkFlagRequired(binder.SignerInfo.FieldName); err != nil { + return err + } + + // the client context uses the from flag to determine the signer. + // this sets the signer flags to the from flag value if a custom signer flag is set. + if binder.SignerInfo.FieldName != flags.FlagFrom { + signer, err := cmd.Flags().GetString(binder.SignerInfo.FieldName) + if err != nil { + return fmt.Errorf("failed to get signer flag: %w", err) + } + + if err := cmd.Flags().Set(flags.FlagFrom, signer); err != nil { + return err + } + } + } else { + // if the signer is not a flag, it is a positional argument + // we need to get the correct positional arguments + if err := cmd.Flags().Set(flags.FlagFrom, args[binder.SignerInfo.PositionalArgIndex]); err != nil { + return err + } + } + } + return exec(cmd, input) } diff --git a/client/v2/autocli/common_test.go b/client/v2/autocli/common_test.go index 5c4e0f322e74..5926941d8bea 100644 --- a/client/v2/autocli/common_test.go +++ b/client/v2/autocli/common_test.go @@ -19,7 +19,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" addresscodec "github.com/cosmos/cosmos-sdk/codec/address" - "github.com/cosmos/cosmos-sdk/crypto/keyring" + sdkkeyring "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" ) @@ -47,10 +47,16 @@ func initFixture(t *testing.T) *fixture { clientConn, err := grpc.Dial(listener.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) assert.NilError(t, err) - appCodec := moduletestutil.MakeTestEncodingConfig().Codec - kr, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, home, nil, appCodec) + encodingConfig := moduletestutil.MakeTestEncodingConfig() + kr, err := sdkkeyring.New(sdk.KeyringServiceName(), sdkkeyring.BackendMemory, home, nil, encodingConfig.Codec) assert.NilError(t, err) + akr, err := sdkkeyring.NewAutoCLIKeyring(kr) + assert.NilError(t, err) + + interfaceRegistry := encodingConfig.Codec.InterfaceRegistry() + interfaceRegistry.RegisterInterface(sdk.MsgTypeURL(&testpb.MsgRequest{}), (*sdk.Msg)(nil), &testpb.MsgRequest{}) + var initClientCtx client.Context initClientCtx = initClientCtx. WithAddressCodec(addresscodec.NewBech32Codec("cosmos")). @@ -59,21 +65,28 @@ func initFixture(t *testing.T) *fixture { WithKeyring(kr). WithKeyringDir(home). WithHomeDir(home). - WithViper("") + WithViper(""). + WithInterfaceRegistry(interfaceRegistry). + WithTxConfig(encodingConfig.TxConfig). + WithAccountRetriever(client.MockAccountRetriever{}). + WithChainID("autocli-test") conn := &testClientConn{ClientConn: clientConn} b := &Builder{ Builder: flag.Builder{ - TypeResolver: protoregistry.GlobalTypes, - FileResolver: protoregistry.GlobalFiles, - ClientCtx: &initClientCtx, - Keyring: kr, + TypeResolver: protoregistry.GlobalTypes, + FileResolver: protoregistry.GlobalFiles, + AddressCodec: initClientCtx.AddressCodec, + ValidatorAddressCodec: initClientCtx.ValidatorAddressCodec, + ConsensusAddressCodec: initClientCtx.ConsensusAddressCodec, + Keyring: akr, }, GetClientConn: func(*cobra.Command) (grpc.ClientConnInterface, error) { return conn, nil }, AddQueryConnFlags: flags.AddQueryFlagsToCmd, AddTxConnFlags: flags.AddTxFlagsToCmd, + ClientCtx: initClientCtx, } assert.NilError(t, b.ValidateAndComplete()) diff --git a/client/v2/autocli/flag/address.go b/client/v2/autocli/flag/address.go index 4d61e0f9dd23..ddc7e6bf2c08 100644 --- a/client/v2/autocli/flag/address.go +++ b/client/v2/autocli/flag/address.go @@ -19,7 +19,7 @@ import ( type addressStringType struct{} func (a addressStringType) NewValue(_ context.Context, b *Builder) Value { - return &addressValue{addressCodec: b.ClientCtx.AddressCodec, keyring: b.Keyring} + return &addressValue{addressCodec: b.AddressCodec, keyring: b.Keyring} } func (a addressStringType) DefaultValue() string { @@ -29,7 +29,7 @@ func (a addressStringType) DefaultValue() string { type validatorAddressStringType struct{} func (a validatorAddressStringType) NewValue(_ context.Context, b *Builder) Value { - return &addressValue{addressCodec: b.ClientCtx.ValidatorAddressCodec, keyring: b.Keyring} + return &addressValue{addressCodec: b.ValidatorAddressCodec, keyring: b.Keyring} } func (a validatorAddressStringType) DefaultValue() string { @@ -80,7 +80,12 @@ func (a addressValue) Type() string { type consensusAddressStringType struct{} func (a consensusAddressStringType) NewValue(ctx context.Context, b *Builder) Value { - return &consensusAddressValue{addressValue: addressValue{addressCodec: b.ClientCtx.ConsensusAddressCodec, keyring: b.Keyring}} + return &consensusAddressValue{ + addressValue: addressValue{ + addressCodec: b.ConsensusAddressCodec, + keyring: b.Keyring, + }, + } } func (a consensusAddressStringType) DefaultValue() string { diff --git a/client/v2/autocli/flag/builder.go b/client/v2/autocli/flag/builder.go index a97906029f9b..f0accc2e0971 100644 --- a/client/v2/autocli/flag/builder.go +++ b/client/v2/autocli/flag/builder.go @@ -14,10 +14,13 @@ import ( "google.golang.org/protobuf/reflect/protoregistry" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + msgv1 "cosmossdk.io/api/cosmos/msg/v1" "cosmossdk.io/client/v2/autocli/keyring" + "cosmossdk.io/client/v2/internal/flags" "cosmossdk.io/client/v2/internal/util" + "cosmossdk.io/core/address" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/runtime" ) // Builder manages options for building pflag flags for protobuf messages. @@ -39,11 +42,13 @@ type Builder struct { messageFlagTypes map[protoreflect.FullName]Type scalarFlagTypes map[string]Type - // Keyring implementation + // Keyring is the keyring to use for client/v2. Keyring keyring.Keyring - // ClientCtx contains the necessary information needed to execute the commands. - ClientCtx *client.Context + // Address Codecs are the address codecs to use for client/v2. + AddressCodec address.Codec + ValidatorAddressCodec runtime.ValidatorAddressCodec + ConsensusAddressCodec runtime.ConsensusAddressCodec } func (b *Builder) init() { @@ -62,35 +67,48 @@ func (b *Builder) init() { } } +// DefineMessageFlagType allows to extend custom protobuf message type handling for flags (and positional arguments). func (b *Builder) DefineMessageFlagType(messageName protoreflect.FullName, flagType Type) { b.init() b.messageFlagTypes[messageName] = flagType } +// DefineScalarFlagType allows to extend custom scalar type handling for flags (and positional arguments). func (b *Builder) DefineScalarFlagType(scalarName string, flagType Type) { b.init() b.scalarFlagTypes[scalarName] = flagType } +// AddMessageFlags adds flags for each field in the message to the flag set. func (b *Builder) AddMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions) (*MessageBinder, error) { return b.addMessageFlags(ctx, flagSet, messageType, commandOptions, namingOptions{}) } -// AddMessageFlags adds flags for each field in the message to the flag set. +// addMessageFlags adds flags for each field in the message to the flag set. func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions, options namingOptions) (*MessageBinder, error) { - fields := messageType.Descriptor().Fields() - numFields := fields.Len() - handler := &MessageBinder{ + messageBinder := &MessageBinder{ messageType: messageType, + // positional args are also parsed using a FlagSet so that we can reuse all the same parsers + positionalFlagSet: pflag.NewFlagSet("positional", pflag.ContinueOnError), } + fields := messageType.Descriptor().Fields() + signerFieldName := getSignerFieldName(messageType.Descriptor()) + isPositional := map[string]bool{} - n := len(commandOptions.PositionalArgs) - // positional args are also parsed using a FlagSet so that we can reuse all the same parsers - handler.positionalFlagSet = pflag.NewFlagSet("positional", pflag.ContinueOnError) + + lengthPositionalArgsOptions := len(commandOptions.PositionalArgs) for i, arg := range commandOptions.PositionalArgs { isPositional[arg.ProtoField] = true + // verify if a positional field is a signer field + if arg.ProtoField == signerFieldName { + messageBinder.SignerInfo = SignerInfo{ + PositionalArgIndex: i, + FieldName: arg.ProtoField, + } + } + field := fields.ByName(protoreflect.Name(arg.ProtoField)) if field == nil { return nil, fmt.Errorf("can't find field %s on %s", arg.ProtoField, messageType.Descriptor().FullName()) @@ -101,24 +119,24 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m } if arg.Varargs { - if i != n-1 { + if i != lengthPositionalArgsOptions-1 { return nil, fmt.Errorf("varargs positional argument %s must be the last argument", arg.ProtoField) } - handler.hasVarargs = true + messageBinder.hasVarargs = true } if arg.Optional { - if i != n-1 { + if i != lengthPositionalArgsOptions-1 { return nil, fmt.Errorf("optional positional argument %s must be the last argument", arg.ProtoField) } - handler.hasOptional = true + messageBinder.hasOptional = true } _, hasValue, err := b.addFieldFlag( ctx, - handler.positionalFlagSet, + messageBinder.positionalFlagSet, field, &autocliv1.FlagOptions{Name: fmt.Sprintf("%d", i)}, namingOptions{}, @@ -127,21 +145,21 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m return nil, err } - handler.positionalArgs = append(handler.positionalArgs, fieldBinding{ + messageBinder.positionalArgs = append(messageBinder.positionalArgs, fieldBinding{ field: field, hasValue: hasValue, }) } - if handler.hasVarargs { - handler.CobraArgs = cobra.MinimumNArgs(n - 1) - handler.MandatoryArgUntil = n - 1 - } else if handler.hasOptional { - handler.CobraArgs = cobra.RangeArgs(n-1, n) - handler.MandatoryArgUntil = n - 1 + if messageBinder.hasVarargs { + messageBinder.CobraArgs = cobra.MinimumNArgs(lengthPositionalArgsOptions - 1) + messageBinder.mandatoryArgUntil = lengthPositionalArgsOptions - 1 + } else if messageBinder.hasOptional { + messageBinder.CobraArgs = cobra.RangeArgs(lengthPositionalArgsOptions-1, lengthPositionalArgsOptions) + messageBinder.mandatoryArgUntil = lengthPositionalArgsOptions - 1 } else { - handler.CobraArgs = cobra.ExactArgs(n) - handler.MandatoryArgUntil = n + messageBinder.CobraArgs = cobra.ExactArgs(lengthPositionalArgsOptions) + messageBinder.mandatoryArgUntil = lengthPositionalArgsOptions } // validate flag options @@ -149,12 +167,41 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m if fields.ByName(protoreflect.Name(name)) == nil { return nil, fmt.Errorf("can't find field %s on %s specified as a flag", name, messageType.Descriptor().FullName()) } + + // verify if a flag is a signer field + if name == signerFieldName { + messageBinder.SignerInfo = SignerInfo{ + FieldName: name, + IsFlag: false, + } + } } + // if signer has not been specified as positional arguments, + // add it as `--from` flag (instead of --field-name flags) + if signerFieldName != "" && messageBinder.SignerInfo.FieldName == "" { + if commandOptions.FlagOptions == nil { + commandOptions.FlagOptions = make(map[string]*autocliv1.FlagOptions) + } + + commandOptions.FlagOptions[signerFieldName] = &autocliv1.FlagOptions{ + Name: flags.FlagFrom, + Usage: "Name or address with which to sign the message", + Shorthand: "f", + } + + messageBinder.SignerInfo = SignerInfo{ + FieldName: flags.FlagFrom, + IsFlag: true, + } + } + + // define all other fields as flags flagOptsByFlagName := map[string]*autocliv1.FlagOptions{} - for i := 0; i < numFields; i++ { + for i := 0; i < fields.Len(); i++ { field := fields.Get(i) - if isPositional[string(field.Name())] { + // skips positional args and signer field + if isPositional[string(field.Name())] || string(field.Name()) == signerFieldName { continue } @@ -165,7 +212,7 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m return nil, err } - handler.flagBindings = append(handler.flagBindings, fieldBinding{ + messageBinder.flagBindings = append(messageBinder.flagBindings, fieldBinding{ hasValue: hasValue, field: field, }) @@ -184,7 +231,7 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m } }) - return handler, nil + return messageBinder, nil } // bindPageRequest create a flag for pagination @@ -259,10 +306,11 @@ func (b *Builder) addFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel // This is a bit of hacking around the pflag API, but the // defaultValue is set in this way because this is much easier than trying - // to parse the string into the types that StringSliceP, Int32P, etc. expect + // to parse the string into the types that StringSliceP, Int32P, etc. if defaultValue != "" { err = flagSet.Set(name, defaultValue) } + return name, val, err } @@ -363,3 +411,14 @@ func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) Type return nil } } + +// getSignerFieldName gets signer field name of a message. +// AutoCLI supports only one signer field per message. +func getSignerFieldName(descriptor protoreflect.MessageDescriptor) string { + signersFields := proto.GetExtension(descriptor.Options(), msgv1.E_Signer).([]string) + if len(signersFields) == 0 { + return "" + } + + return signersFields[0] +} diff --git a/client/v2/autocli/flag/messager_binder.go b/client/v2/autocli/flag/messager_binder.go index 9053e90439bb..ecd822395030 100644 --- a/client/v2/autocli/flag/messager_binder.go +++ b/client/v2/autocli/flag/messager_binder.go @@ -8,15 +8,26 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) +// SignerInfo contains information about the signer field. +// That field is special because it needs to be known for signing. +// This struct keeps track of the field name and whether it is a flag. +// IsFlag and PositionalArgIndex are mutually exclusive. +type SignerInfo struct { + PositionalArgIndex int + IsFlag bool + FieldName string +} + // MessageBinder binds multiple flags in a flag set to a protobuf message. type MessageBinder struct { - MandatoryArgUntil int - CobraArgs cobra.PositionalArgs + CobraArgs cobra.PositionalArgs + SignerInfo SignerInfo positionalFlagSet *pflag.FlagSet positionalArgs []fieldBinding hasVarargs bool hasOptional bool + mandatoryArgUntil int flagBindings []fieldBinding messageType protoreflect.MessageType @@ -39,15 +50,14 @@ func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) e } name := fmt.Sprintf("%d", i) - if i == m.MandatoryArgUntil && m.hasVarargs { + if i == m.mandatoryArgUntil && m.hasVarargs { for _, v := range positionalArgs[i:] { if err := m.positionalFlagSet.Set(name, v); err != nil { return err } } } else { - err := m.positionalFlagSet.Set(name, positionalArgs[i]) - if err != nil { + if err := m.positionalFlagSet.Set(name, positionalArgs[i]); err != nil { return err } } @@ -55,16 +65,14 @@ func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) e // bind positional arg values to the message for _, arg := range m.positionalArgs { - err := arg.bind(msg) - if err != nil { + if err := arg.bind(msg); err != nil { return err } } // bind flag values to the message for _, binding := range m.flagBindings { - err := binding.bind(msg) - if err != nil { + if err := binding.bind(msg); err != nil { return err } } diff --git a/client/v2/autocli/flags.go b/client/v2/autocli/flags.go deleted file mode 100644 index e6e153fcc6fe..000000000000 --- a/client/v2/autocli/flags.go +++ /dev/null @@ -1,3 +0,0 @@ -package autocli - -var flagNoIndent = "no-indent" diff --git a/client/v2/autocli/keyring/interface.go b/client/v2/autocli/keyring/interface.go index fee5f3434ad3..fa448bd20599 100644 --- a/client/v2/autocli/keyring/interface.go +++ b/client/v2/autocli/keyring/interface.go @@ -1,6 +1,23 @@ package keyring +import ( + signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +// Keyring is an interface used for signing transactions. +// It aims to be simplistic and easy to use. type Keyring interface { + // List returns the names of all keys stored in the keyring. + List() ([]string, error) + // LookupAddressByKeyName returns the address of the key with the given name. LookupAddressByKeyName(name string) ([]byte, error) + + // GetPubKey returns the public key of the key with the given name. + GetPubKey(name string) (cryptotypes.PubKey, error) + + // Sign signs the given bytes with the key with the given name. + Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error) } diff --git a/client/v2/autocli/keyring/no_keyring.go b/client/v2/autocli/keyring/no_keyring.go index 916fff4bd452..e14267cee5e3 100644 --- a/client/v2/autocli/keyring/no_keyring.go +++ b/client/v2/autocli/keyring/no_keyring.go @@ -1,11 +1,31 @@ package keyring -import "errors" +import ( + "errors" + + signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) var _ Keyring = NoKeyring{} +var errNoKeyring = errors.New("no keyring configured") + type NoKeyring struct{} +func (k NoKeyring) List() ([]string, error) { + return nil, errNoKeyring +} + func (k NoKeyring) LookupAddressByKeyName(name string) ([]byte, error) { - return nil, errors.New("no keyring configured") + return nil, errNoKeyring +} + +func (k NoKeyring) GetPubKey(name string) (cryptotypes.PubKey, error) { + return nil, errNoKeyring +} + +func (k NoKeyring) Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error) { + return nil, errNoKeyring } diff --git a/client/v2/autocli/msg.go b/client/v2/autocli/msg.go index d97786be0519..c014d3aa500d 100644 --- a/client/v2/autocli/msg.go +++ b/client/v2/autocli/msg.go @@ -4,12 +4,20 @@ import ( "context" "fmt" - autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" "github.com/cockroachdb/errors" - "github.com/cosmos/cosmos-sdk/client" "github.com/spf13/cobra" - "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/dynamicpb" + + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + + "github.com/cosmos/cosmos-sdk/client" + clienttx "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + authtxconfig "github.com/cosmos/cosmos-sdk/x/auth/tx/config" ) // BuildMsgCommand builds the msg commands for all the provided modules. If a custom command is provided for a @@ -97,46 +105,43 @@ func (b *Builder) AddMsgServiceCommands(cmd *cobra.Command, cmdDescriptor *autoc // BuildMsgMethodCommand returns a command that outputs the JSON representation of the message. func (b *Builder) BuildMsgMethodCommand(descriptor protoreflect.MethodDescriptor, options *autocliv1.RpcCommandOptions) (*cobra.Command, error) { - jsonMarshalOptions := protojson.MarshalOptions{ - Indent: " ", - UseProtoNames: true, - UseEnumNumbers: false, - EmitUnpopulated: true, - Resolver: b.TypeResolver, - } - cmd, err := b.buildMethodCommandCommon(descriptor, options, func(cmd *cobra.Command, input protoreflect.Message) error { - if noIdent, _ := cmd.Flags().GetBool(flagNoIndent); noIdent { - jsonMarshalOptions.Indent = "" - } + cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &b.ClientCtx)) - bz, err := jsonMarshalOptions.Marshal(input.Interface()) + clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err } - clientCtx, err := client.ReadPersistentCommandFlags(*b.ClientCtx, cmd.Flags()) - if err != nil { - return err - } - - cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)) - if err = client.SetCmdClientContextHandler(clientCtx, cmd); err != nil { - return err - } + // enable sign mode textual and config tx options + b.TxConfigOpts.EnabledSignModes = append(b.TxConfigOpts.EnabledSignModes, signing.SignMode_SIGN_MODE_TEXTUAL) + b.TxConfigOpts.TextualCoinMetadataQueryFn = authtxconfig.NewGRPCCoinMetadataQueryFn(clientCtx) - clientCtx, err = client.GetClientTxContext(cmd) + txConfigWithTextual, err := authtx.NewTxConfigWithOptions( + codec.NewProtoCodec(clientCtx.InterfaceRegistry), + b.TxConfigOpts, + ) if err != nil { return err } + clientCtx = clientCtx.WithTxConfig(txConfigWithTextual) - return b.outOrStdoutFormat(cmd, bz) + // AutoCLI uses protov2 messages, while the SDK only supports proto v1 messages. + // Here we use dynamicpb, to create a proto v1 compatible message. + // The SDK codec will handle protov2 -> protov1 (marshal) + msg := dynamicpb.NewMessage(input.Descriptor()) + proto.Merge(msg, input.Interface()) + + return clienttx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }) if b.AddTxConnFlags != nil { b.AddTxConnFlags(cmd) + } - cmd.Flags().BoolP(flagNoIndent, "", false, "Do not indent JSON output") + // silence usage only for inner txs & queries commands + if cmd != nil { + cmd.SilenceUsage = true } return cmd, err diff --git a/client/v2/autocli/query.go b/client/v2/autocli/query.go index da88d5b0d25a..d35a6e2101a0 100644 --- a/client/v2/autocli/query.go +++ b/client/v2/autocli/query.go @@ -11,6 +11,7 @@ import ( "github.com/spf13/cobra" "google.golang.org/protobuf/reflect/protoreflect" + "cosmossdk.io/client/v2/internal/flags" "cosmossdk.io/client/v2/internal/util" ) @@ -111,7 +112,7 @@ func (b *Builder) BuildQueryMethodCommand(descriptor protoreflect.MethodDescript } cmd, err := b.buildMethodCommandCommon(descriptor, options, func(cmd *cobra.Command, input protoreflect.Message) error { - if noIndent, _ := cmd.Flags().GetBool(flagNoIndent); noIndent { + if noIndent, _ := cmd.Flags().GetBool(flags.FlagNoIndent); noIndent { encoderOptions.Indent = "" } @@ -140,7 +141,12 @@ func (b *Builder) BuildQueryMethodCommand(descriptor protoreflect.MethodDescript if b.AddQueryConnFlags != nil { b.AddQueryConnFlags(cmd) - cmd.Flags().BoolP(flagNoIndent, "", false, "Do not indent JSON output") + cmd.Flags().BoolP(flags.FlagNoIndent, "", false, "Do not indent JSON output") + } + + // silence usage only for inner txs & queries commands + if cmd != nil { + cmd.SilenceUsage = true } return cmd, nil diff --git a/client/v2/autocli/testdata/help-deprecated-msg.golden b/client/v2/autocli/testdata/help-deprecated-msg.golden index 4de93a2d067b..31d61d736cbe 100644 --- a/client/v2/autocli/testdata/help-deprecated-msg.golden +++ b/client/v2/autocli/testdata/help-deprecated-msg.golden @@ -37,7 +37,6 @@ Flags: --keyring-backend string Select keyring's backend (os|file|kwallet|pass|test|memory) (default "os") --keyring-dir string The client Keyring directory; if omitted, the default 'home' directory will be used --ledger Use a connected Ledger device - --no-indent Do not indent JSON output --node string : to CometBFT rpc interface for this chain (default "tcp://localhost:26657") --note string Note to add a description to the transaction (previously --memo) --offline Offline mode (does not allow any online functionality) diff --git a/client/v2/autocli/testdata/help-echo-msg.golden b/client/v2/autocli/testdata/help-echo-msg.golden index 7a0905579ad9..0b5e9e69b756 100644 --- a/client/v2/autocli/testdata/help-echo-msg.golden +++ b/client/v2/autocli/testdata/help-echo-msg.golden @@ -41,7 +41,6 @@ Flags: --keyring-backend string Select keyring's backend (os|file|kwallet|pass|test|memory) (default "os") --keyring-dir string The client Keyring directory; if omitted, the default 'home' directory will be used --ledger Use a connected Ledger device - --no-indent Do not indent JSON output --node string : to CometBFT rpc interface for this chain (default "tcp://localhost:26657") --note string Note to add a description to the transaction (previously --memo) --offline Offline mode (does not allow any online functionality) diff --git a/client/v2/go.mod b/client/v2/go.mod index e7ac8538e158..011065cb198e 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -3,10 +3,9 @@ module cosmossdk.io/client/v2 go 1.21 require ( - cosmossdk.io/api v0.7.1 + cosmossdk.io/api v0.7.2-0.20230927090904-9dd34510e273 cosmossdk.io/core v0.12.0 cosmossdk.io/depinject v1.0.0-alpha.4 - cosmossdk.io/log v1.2.1 cosmossdk.io/x/tx v0.10.0 github.com/cockroachdb/errors v1.11.1 github.com/cosmos/cosmos-proto v1.0.0-beta.3 @@ -23,6 +22,7 @@ require ( require ( cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/errors v1.0.0 // indirect + cosmossdk.io/log v1.2.1 // indirect cosmossdk.io/math v1.1.3-rc.1 // indirect cosmossdk.io/store v1.0.0-rc.0 // indirect filippo.io/edwards25519 v1.0.0 // indirect @@ -73,6 +73,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/orderedcode v0.0.1 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect @@ -95,18 +96,20 @@ require ( github.com/klauspost/compress v1.16.7 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect + github.com/lib/pq v1.10.7 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/linxGnu/grocksdb v1.8.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce // indirect github.com/oklog/run v1.1.0 // indirect - github.com/pelletier/go-toml/v2 v2.0.9 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20230808133559-b036b712a89b // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -134,11 +137,12 @@ require ( golang.org/x/crypto v0.13.0 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect golang.org/x/net v0.15.0 // indirect + golang.org/x/sync v0.3.0 // indirect golang.org/x/sys v0.12.0 // indirect golang.org/x/term v0.12.0 // indirect golang.org/x/text v0.13.0 // indirect google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -146,3 +150,5 @@ require ( nhooyr.io/websocket v1.8.6 // indirect pgregory.net/rapid v1.1.0 // indirect ) + +replace github.com/cosmos/cosmos-sdk => ./../../ diff --git a/client/v2/go.sum b/client/v2/go.sum index 9244ba7ab9c2..819af0aca15e 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -35,8 +35,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cosmossdk.io/api v0.7.1 h1:PNQ1xN8+/0hj/sSD0ANqjkgfXFys+bZ5L8Hg7uzoUTU= -cosmossdk.io/api v0.7.1/go.mod h1:ure9edhcROIHsngavM6mBLilMGFnfjhV/AaYhEMUkdo= +cosmossdk.io/api v0.7.2-0.20230927090904-9dd34510e273 h1:rNTYK/OQQ5B8jNY0wGSOv+64Fwm7DG8Yke5eRmdTPqk= +cosmossdk.io/api v0.7.2-0.20230927090904-9dd34510e273/go.mod h1:RgzIuGUBiX4E4imKHFyxl+uSKU+qs2v0W2ymVoGoyQQ= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.12.0 h1:aFuvkG6eDv0IQC+UDjx86wxNWVAxdCFk7OABJ1Vh4RU= @@ -51,6 +51,8 @@ cosmossdk.io/math v1.1.3-rc.1 h1:NebCNWDqb1MJRNfvxr4YY7d8FSYgkuB3L75K6xvM+Zo= cosmossdk.io/math v1.1.3-rc.1/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= cosmossdk.io/store v1.0.0-rc.0 h1:9DwOjuUYxDtYxn/REkTxGQAmxlIGfRroB35MQ8TrxF4= cosmossdk.io/store v1.0.0-rc.0/go.mod h1:FtBDOJmwtOZfmKKF65bKZbTYgS3bDNjjo3nP76dAegk= +cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 h1:XQJj9Dv9Gtze0l2TF79BU5lkP6MkUveTUuKICmxoz+o= +cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190/go.mod h1:7WUGupOvmlHJoIMBz1JbObQxeo6/TDiuDBxmtod8HRg= cosmossdk.io/x/tx v0.10.0 h1:LxWF/hksVDbeQmFj4voLM5ZCHyVZ1cCNIqKenfH9plc= cosmossdk.io/x/tx v0.10.0/go.mod h1:MKo9/b5wsoL8dd9y9pvD2yOP1CMvzHIWYxi1l2oLPFo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -60,18 +62,26 @@ github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMb github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= +github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= +github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -97,6 +107,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.9.0 h1:g1YivPG8jOtrN013Fe8OBXubkiTwvm7/vG2vXz03ANU= +github.com/bits-and-blooms/bitset v1.9.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= @@ -106,6 +118,7 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= @@ -151,6 +164,8 @@ github.com/cometbft/cometbft v0.38.0 h1:ogKnpiPX7gxCvqTEF4ly25/wAxUqf181t30P3vqd github.com/cometbft/cometbft v0.38.0/go.mod h1:5Jz0Z8YsHSf0ZaAqGvi/ifioSdVFPtEGrm8Y9T/993k= github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -163,8 +178,6 @@ github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0 github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U= github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o= github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= -github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230915113003-c7e0bd7b54d0 h1:BNa8miwG4Aquqcz7ItXIWCao9e6OM+2HKXAPn96oDO8= -github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230915113003-c7e0bd7b54d0/go.mod h1:fuDAZLtTNCqYD0tZSJTNkB6DRjqC3t640i4lT6LAWxo= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= @@ -203,6 +216,10 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= @@ -461,8 +478,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/jhump/protoreflect v1.15.2 h1:7YppbATX94jEt9KLAc5hICx4h6Yt3SaavhQRsIUEHP0= -github.com/jhump/protoreflect v1.15.2/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= +github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= +github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= @@ -594,6 +611,12 @@ github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9 github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= +github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -602,14 +625,16 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= -github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230808133559-b036b712a89b h1:vab8deKC4QoIfm9fJM59iuNz1ELGsuLoYYpiF+pHiG8= @@ -688,6 +713,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -837,6 +864,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -916,6 +945,7 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1059,6 +1089,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1136,8 +1168,8 @@ google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= -google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 h1:nIgk/EEq3/YlnmVVXVnm14rC2oxgs1o0ong4sD/rd44= -google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= diff --git a/client/v2/internal/flags/flags.go b/client/v2/internal/flags/flags.go new file mode 100644 index 000000000000..cd50a96be87b --- /dev/null +++ b/client/v2/internal/flags/flags.go @@ -0,0 +1,19 @@ +package flags + +// This defines flag names that can be used in autocli. +const ( + // FlagFrom is the flag to set the from address with which to sign the transaction. + FlagFrom = "from" + + // FlagOutput is the flag to set the output format. + FlagOutput = "output" + + // FlagNoIndent is the flag to not indent the output. + FlagNoIndent = "no-indent" +) + +// List of supported output formats +const ( + OutputFormatJSON = "json" + OutputFormatText = "text" +) diff --git a/codec/bench_test.go b/codec/bench_test.go index abbbbfccab24..d5b5fa132dc9 100644 --- a/codec/bench_test.go +++ b/codec/bench_test.go @@ -12,16 +12,26 @@ import ( codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) +type bankSendWrapper struct { + *banktypes.MsgSend +} + +func (msg bankSendWrapper) GetSigners() []sdk.AccAddress { + fromAddress, _ := sdk.AccAddressFromBech32(msg.FromAddress) + return []sdk.AccAddress{fromAddress} +} + func BenchmarkLegacyGetSigners(b *testing.B) { _, _, addr := testdata.KeyTestPubAddr() - msg := &banktypes.MsgSend{ + msg := bankSendWrapper{&banktypes.MsgSend{ FromAddress: addr.String(), ToAddress: "", Amount: nil, - } + }} b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/codec/types/any.go b/codec/types/any.go index c08b08d855be..ad9ba3bdc48e 100644 --- a/codec/types/any.go +++ b/codec/types/any.go @@ -4,6 +4,7 @@ import ( fmt "fmt" "github.com/cosmos/gogoproto/proto" + protov2 "google.golang.org/protobuf/proto" errorsmod "cosmossdk.io/errors" @@ -62,13 +63,21 @@ func NewAnyWithValue(v proto.Message) (*Any, error) { return nil, errorsmod.Wrap(sdkerrors.ErrPackAny, "Expecting non nil value to create a new Any") } - bz, err := proto.Marshal(v) + var ( + bz []byte + err error + ) + if msg, ok := v.(protov2.Message); ok { + bz, err = protov2.Marshal(msg) + } else { + bz, err = proto.Marshal(v) + } if err != nil { return nil, err } return &Any{ - TypeUrl: "/" + proto.MessageName(v), + TypeUrl: MsgTypeURL(v), Value: bz, cachedValue: v, }, nil @@ -93,8 +102,17 @@ func UnsafePackAny(x interface{}) *Any { // the packed value so that it can be retrieved from GetCachedValue without // unmarshaling func (any *Any) pack(x proto.Message) error { - any.TypeUrl = "/" + proto.MessageName(x) - bz, err := proto.Marshal(x) + any.TypeUrl = MsgTypeURL(x) + + var ( + bz []byte + err error + ) + if msg, ok := x.(protov2.Message); ok { + bz, err = protov2.Marshal(msg) + } else { + bz, err = proto.Marshal(x) + } if err != nil { return err } diff --git a/codec/types/interface_registry.go b/codec/types/interface_registry.go index 4790bf6ef664..99393fa2c57c 100644 --- a/codec/types/interface_registry.go +++ b/codec/types/interface_registry.go @@ -189,7 +189,7 @@ func (registry *interfaceRegistry) EnsureRegistered(impl interface{}) error { // same typeURL. func (registry *interfaceRegistry) RegisterImplementations(iface interface{}, impls ...proto.Message) { for _, impl := range impls { - typeURL := "/" + proto.MessageName(impl) + typeURL := MsgTypeURL(impl) registry.registerImpl(iface, typeURL, impl) } } diff --git a/codec/types/util.go b/codec/types/util.go new file mode 100644 index 000000000000..b29fb33b5034 --- /dev/null +++ b/codec/types/util.go @@ -0,0 +1,15 @@ +package types + +import ( + "github.com/cosmos/gogoproto/proto" + protov2 "google.golang.org/protobuf/proto" +) + +// MsgTypeURL returns the TypeURL of a `sdk.Msg`. +func MsgTypeURL(msg proto.Message) string { + if m, ok := msg.(protov2.Message); ok { + return "/" + string(m.ProtoReflect().Descriptor().FullName()) + } + + return "/" + proto.MessageName(msg) +} diff --git a/crypto/keyring/autocli.go b/crypto/keyring/autocli.go new file mode 100644 index 000000000000..0dd91ff60a43 --- /dev/null +++ b/crypto/keyring/autocli.go @@ -0,0 +1,86 @@ +package keyring + +import ( + signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" +) + +// autoCLIKeyring represents the keyring interface used by the AutoCLI. +// It purposely does not import the AutoCLI package to avoid circular dependencies. +type autoCLIKeyring interface { + // List returns the names of all keys stored in the keyring. + List() ([]string, error) + + // LookupAddressByKeyName returns the address of the key with the given name. + LookupAddressByKeyName(name string) ([]byte, error) + + // GetPubKey returns the public key of the key with the given name. + GetPubKey(name string) (cryptotypes.PubKey, error) + + // Sign signs the given bytes with the key with the given name. + Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error) +} + +// NewAutoCLIKeyring wraps the SDK keyring and make it compatible with the AutoCLI keyring interfaces. +func NewAutoCLIKeyring(kr Keyring) (autoCLIKeyring, error) { + return &autoCLIKeyringAdapter{kr}, nil +} + +type autoCLIKeyringAdapter struct { + Keyring +} + +func (a *autoCLIKeyringAdapter) List() ([]string, error) { + list, err := a.Keyring.List() + if err != nil { + return nil, err + } + + names := make([]string, len(list)) + for i, key := range list { + names[i] = key.Name + } + + return names, nil +} + +// LookupAddressByKeyName returns the address of a key stored in the keyring +func (a *autoCLIKeyringAdapter) LookupAddressByKeyName(name string) ([]byte, error) { + record, err := a.Keyring.Key(name) + if err != nil { + return nil, err + } + + addr, err := record.GetAddress() + if err != nil { + return nil, err + } + + return addr, nil +} + +func (a *autoCLIKeyringAdapter) GetPubKey(name string) (cryptotypes.PubKey, error) { + record, err := a.Keyring.Key(name) + if err != nil { + return nil, err + } + + return record.GetPubKey() +} + +func (a *autoCLIKeyringAdapter) Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error) { + record, err := a.Keyring.Key(name) + if err != nil { + return nil, err + } + + sdkSignMode, err := authsigning.APISignModeToInternal(signMode) + if err != nil { + return nil, err + } + + signBytes, _, err := a.Keyring.Sign(record.Name, msg, sdkSignMode) + return signBytes, err +} diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 91004aa91a45..2e92c484254e 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -102,9 +102,6 @@ type Keyring interface { Exporter Migrator - - // Implements client/v2 keyring interface - LookupAddressByKeyName(name string) ([]byte, error) } // Signer is implemented by key stores that want to provide signing capabilities. @@ -622,21 +619,6 @@ func (ks keystore) SupportedAlgorithms() (SigningAlgoList, SigningAlgoList) { return ks.options.SupportedAlgos, ks.options.SupportedAlgosLedger } -// LookupAddressByKeyName returns the address of a key stored in the keyring -func (ks keystore) LookupAddressByKeyName(name string) ([]byte, error) { - record, err := ks.Key(name) - if err != nil { - return nil, err - } - - addr, err := record.GetAddress() - if err != nil { - return nil, err - } - - return addr, nil -} - // SignWithLedger signs a binary message with the ledger device referenced by an Info object // and returns the signed bytes and the public key. It returns an error if the device could // not be queried or it returned an error. diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index 6678166ad5ce..1b8291367900 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/config" "github.com/cosmos/cosmos-sdk/codec" addresscodec "github.com/cosmos/cosmos-sdk/codec/address" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/server" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" @@ -109,8 +110,8 @@ func NewRootCmd() *cobra.Command { } autoCliOpts := tempApp.AutoCliOpts() - autoCliOpts.Keyring = initClientCtx.Keyring - autoCliOpts.ClientCtx = &initClientCtx + autoCliOpts.Keyring, _ = keyring.NewAutoCLIKeyring(initClientCtx.Keyring) + autoCliOpts.ClientCtx = initClientCtx if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil { panic(err) diff --git a/simapp/simd/cmd/root_v2.go b/simapp/simd/cmd/root_v2.go index d22230b0face..170aa94b0fba 100644 --- a/simapp/simd/cmd/root_v2.go +++ b/simapp/simd/cmd/root_v2.go @@ -18,6 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/config" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/server" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" @@ -34,7 +35,7 @@ func NewRootCmd() *cobra.Command { txConfigOpts tx.ConfigOptions autoCliOpts autocli.AppOptions moduleBasicManager module.BasicManager - initClientCtx *client.Context + clientCtx client.Context ) if err := depinject.Inject( @@ -51,7 +52,7 @@ func NewRootCmd() *cobra.Command { &txConfigOpts, &autoCliOpts, &moduleBasicManager, - &initClientCtx, + &clientCtx, ); err != nil { panic(err) } @@ -65,7 +66,6 @@ func NewRootCmd() *cobra.Command { cmd.SetOut(cmd.OutOrStdout()) cmd.SetErr(cmd.ErrOrStderr()) - clientCtx := *initClientCtx clientCtx = clientCtx.WithCmdContext(cmd.Context()) clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags()) if err != nil { @@ -89,7 +89,6 @@ func NewRootCmd() *cobra.Command { return err } clientCtx = clientCtx.WithTxConfig(txConfigWithTextual) - if err := client.SetCmdClientContextHandler(clientCtx, cmd); err != nil { return err } @@ -101,7 +100,7 @@ func NewRootCmd() *cobra.Command { }, } - initRootCmd(rootCmd, initClientCtx.TxConfig, initClientCtx.InterfaceRegistry, initClientCtx.Codec, moduleBasicManager) + initRootCmd(rootCmd, clientCtx.TxConfig, clientCtx.InterfaceRegistry, clientCtx.Codec, moduleBasicManager) if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil { panic(err) @@ -118,7 +117,7 @@ func ProvideClientContext( addressCodec address.Codec, validatorAddressCodec runtime.ValidatorAddressCodec, consensusAddressCodec runtime.ConsensusAddressCodec, -) *client.Context { +) client.Context { var err error clientCtx := client.Context{}. @@ -141,14 +140,14 @@ func ProvideClientContext( panic(err) } - return &clientCtx + return clientCtx } -func ProvideKeyring(clientCtx *client.Context, addressCodec address.Codec) (clientv2keyring.Keyring, error) { - kb, err := client.NewKeyringFromBackend(*clientCtx, clientCtx.Keyring.Backend()) +func ProvideKeyring(clientCtx client.Context, addressCodec address.Codec) (clientv2keyring.Keyring, error) { + kb, err := client.NewKeyringFromBackend(clientCtx, clientCtx.Keyring.Backend()) if err != nil { return nil, err } - return kb, nil + return keyring.NewAutoCLIKeyring(kb) } diff --git a/types/tx_msg.go b/types/tx_msg.go index 230092ad2181..399dafd4cc43 100644 --- a/types/tx_msg.go +++ b/types/tx_msg.go @@ -9,6 +9,7 @@ import ( protov2 "google.golang.org/protobuf/proto" "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" ) @@ -95,13 +96,7 @@ type TxDecoder func(txBytes []byte) (Tx, error) type TxEncoder func(tx Tx) ([]byte, error) // MsgTypeURL returns the TypeURL of a `sdk.Msg`. -func MsgTypeURL(msg proto.Message) string { - if m, ok := msg.(protov2.Message); ok { - return "/" + string(m.ProtoReflect().Descriptor().FullName()) - } - - return "/" + proto.MessageName(msg) -} +var MsgTypeURL = codectypes.MsgTypeURL // GetMsgFromTypeURL returns a `sdk.Msg` message type from a type URL func GetMsgFromTypeURL(cdc codec.Codec, input string) (Msg, error) { diff --git a/x/auth/signing/sig_verifiable_tx.go b/x/auth/signing/sig_verifiable_tx.go index 0b6da14aff50..c8a752e7e475 100644 --- a/x/auth/signing/sig_verifiable_tx.go +++ b/x/auth/signing/sig_verifiable_tx.go @@ -16,7 +16,7 @@ type SigVerifiableTx interface { } // Tx defines a transaction interface that supports all standard message, signature -// fee, memo, tips, and auxiliary interfaces. +// fee, memo and auxiliary interfaces. type Tx interface { SigVerifiableTx diff --git a/x/bank/types/msgs.go b/x/bank/types/msgs.go index 9ce68e48344d..05a23c280e2b 100644 --- a/x/bank/types/msgs.go +++ b/x/bank/types/msgs.go @@ -15,12 +15,6 @@ func NewMsgSend(fromAddr, toAddr sdk.AccAddress, amount sdk.Coins) *MsgSend { return &MsgSend{FromAddress: fromAddr.String(), ToAddress: toAddr.String(), Amount: amount} } -// GetSigners Implements Msg. -func (msg MsgSend) GetSigners() []sdk.AccAddress { - fromAddress, _ := sdk.AccAddressFromBech32(msg.FromAddress) - return []sdk.AccAddress{fromAddress} -} - // NewMsgMultiSend - construct arbitrary multi-in, multi-out send msg. func NewMsgMultiSend(in Input, out []Output) *MsgMultiSend { return &MsgMultiSend{Inputs: []Input{in}, Outputs: out} From 77f5068ed453c5106754b619d64a1fc504a0c26b Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Wed, 4 Oct 2023 16:00:11 +0200 Subject: [PATCH 10/20] fix tests --- client/v2/autocli/common_test.go | 86 +++++- client/v2/autocli/msg.go | 1 + client/v2/autocli/msg_test.go | 285 ++---------------- client/v2/autocli/query_test.go | 6 +- .../testdata/help-deprecated-msg.golden | 64 ---- .../v2/autocli/testdata/help-echo-msg.golden | 90 ++---- .../autocli/testdata/help-toplevel-msg.golden | 12 +- client/v2/autocli/testdata/msg-output.golden | 1 + client/v2/go.mod | 1 + client/v2/go.sum | 4 + 10 files changed, 150 insertions(+), 400 deletions(-) delete mode 100644 client/v2/autocli/testdata/help-deprecated-msg.golden create mode 100644 client/v2/autocli/testdata/msg-output.golden diff --git a/client/v2/autocli/common_test.go b/client/v2/autocli/common_test.go index 5926941d8bea..f1472d486b7e 100644 --- a/client/v2/autocli/common_test.go +++ b/client/v2/autocli/common_test.go @@ -12,6 +12,7 @@ import ( "google.golang.org/protobuf/reflect/protoregistry" "gotest.tools/v3/assert" + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" reflectionv2alpha1 "cosmossdk.io/api/cosmos/base/reflection/v2alpha1" "cosmossdk.io/client/v2/autocli/flag" "cosmossdk.io/client/v2/internal/testpb" @@ -22,6 +23,8 @@ import ( sdkkeyring "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + "github.com/cosmos/cosmos-sdk/x/bank" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) type fixture struct { @@ -47,7 +50,7 @@ func initFixture(t *testing.T) *fixture { clientConn, err := grpc.Dial(listener.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) assert.NilError(t, err) - encodingConfig := moduletestutil.MakeTestEncodingConfig() + encodingConfig := moduletestutil.MakeTestEncodingConfig(bank.AppModuleBasic{}) kr, err := sdkkeyring.New(sdk.KeyringServiceName(), sdkkeyring.BackendMemory, home, nil, encodingConfig.Codec) assert.NilError(t, err) @@ -55,7 +58,7 @@ func initFixture(t *testing.T) *fixture { assert.NilError(t, err) interfaceRegistry := encodingConfig.Codec.InterfaceRegistry() - interfaceRegistry.RegisterInterface(sdk.MsgTypeURL(&testpb.MsgRequest{}), (*sdk.Msg)(nil), &testpb.MsgRequest{}) + banktypes.RegisterInterfaces(interfaceRegistry) var initClientCtx client.Context initClientCtx = initClientCtx. @@ -144,3 +147,82 @@ func (t testEchoServer) Echo(_ context.Context, request *testpb.EchoRequest) (*t } var _ testpb.QueryServer = testEchoServer{} + +func TestEnhanceCommand(t *testing.T) { + b := &Builder{} + // Test that the command has a subcommand + cmd := &cobra.Command{Use: "test"} + cmd.AddCommand(&cobra.Command{Use: "test"}) + + for i := 0; i < 2; i++ { + cmdTp := cmdType(i) + + appOptions := AppOptions{ + ModuleOptions: map[string]*autocliv1.ModuleOptions{ + "test": {}, + }, + } + + err := b.enhanceCommandCommon(cmd, cmdTp, appOptions, map[string]*cobra.Command{}) + assert.NilError(t, err) + + cmd = &cobra.Command{Use: "test"} + + appOptions = AppOptions{ + ModuleOptions: map[string]*autocliv1.ModuleOptions{}, + } + customCommands := map[string]*cobra.Command{ + "test2": {Use: "test"}, + } + err = b.enhanceCommandCommon(cmd, cmdTp, appOptions, customCommands) + assert.NilError(t, err) + + cmd = &cobra.Command{Use: "test"} + appOptions = AppOptions{ + ModuleOptions: map[string]*autocliv1.ModuleOptions{ + "test": {Tx: nil}, + }, + } + err = b.enhanceCommandCommon(cmd, cmdTp, appOptions, map[string]*cobra.Command{}) + assert.NilError(t, err) + } +} + +func TestErrorBuildCommand(t *testing.T) { + fixture := initFixture(t) + b := fixture.b + b.AddQueryConnFlags = nil + b.AddTxConnFlags = nil + + commandDescriptor := &autocliv1.ServiceCommandDescriptor{ + Service: testpb.Msg_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Send", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + { + ProtoField: "un-existent-proto-field", + }, + }, + }, + }, + } + + appOptions := AppOptions{ + ModuleOptions: map[string]*autocliv1.ModuleOptions{ + "test": { + Query: commandDescriptor, + Tx: commandDescriptor, + }, + }, + ClientCtx: b.ClientCtx, + } + + _, err := b.BuildMsgCommand(appOptions, nil) + assert.ErrorContains(t, err, "can't find field un-existent-proto-field") + + appOptions.ModuleOptions["test"].Tx = &autocliv1.ServiceCommandDescriptor{Service: "un-existent-service"} + appOptions.ModuleOptions["test"].Query = &autocliv1.ServiceCommandDescriptor{Service: "un-existent-service"} + _, err = b.BuildMsgCommand(appOptions, nil) + assert.ErrorContains(t, err, "can't find service un-existent-service") +} diff --git a/client/v2/autocli/msg.go b/client/v2/autocli/msg.go index c014d3aa500d..a2bd5eb9051a 100644 --- a/client/v2/autocli/msg.go +++ b/client/v2/autocli/msg.go @@ -125,6 +125,7 @@ func (b *Builder) BuildMsgMethodCommand(descriptor protoreflect.MethodDescriptor return err } clientCtx = clientCtx.WithTxConfig(txConfigWithTextual) + clientCtx.Output = cmd.OutOrStdout() // AutoCLI uses protov2 messages, while the SDK only supports proto v1 messages. // Here we use dynamicpb, to create a proto v1 compatible message. diff --git a/client/v2/autocli/msg_test.go b/client/v2/autocli/msg_test.go index 74d72933183a..86d328aaa4a6 100644 --- a/client/v2/autocli/msg_test.go +++ b/client/v2/autocli/msg_test.go @@ -2,135 +2,45 @@ package autocli import ( "fmt" - "strings" "testing" "github.com/spf13/cobra" - "google.golang.org/protobuf/encoding/protojson" "gotest.tools/v3/assert" "gotest.tools/v3/golden" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" "cosmossdk.io/client/v2/internal/testpb" ) var buildModuleMsgCommand = func(moduleName string, b *Builder) (*cobra.Command, error) { cmd := topLevelCmd(moduleName, fmt.Sprintf("Transactions commands for the %s module", moduleName)) - err := b.AddMsgServiceCommands(cmd, testCmdMsgDesc) + err := b.AddMsgServiceCommands(cmd, bankAutoCLI) return cmd, err } -var testCmdMsgDesc = &autocliv1.ServiceCommandDescriptor{ - Service: testpb.Msg_ServiceDesc.ServiceName, +var bankAutoCLI = &autocliv1.ServiceCommandDescriptor{ + Service: bankv1beta1.Msg_ServiceDesc.ServiceName, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { - RpcMethod: "Send", - Use: "send [pos1] [pos2] [pos3...]", - Version: "1.0", - Alias: []string{"s"}, - SuggestFor: []string{"send"}, - Example: "send 1 abc {}", - Short: "send msg the value provided by the user", - Long: "send msg the value provided by the user as a proto JSON object with populated with the provided fields and positional arguments", - PositionalArgs: []*autocliv1.PositionalArgDescriptor{ - { - ProtoField: "positional1", - }, - { - ProtoField: "positional2", - }, - { - ProtoField: "positional3_varargs", - Varargs: true, - }, - }, - FlagOptions: map[string]*autocliv1.FlagOptions{ - "u32": { - Name: "uint32", - Shorthand: "u", - Usage: "some random uint32", - }, - "i32": { - Usage: "some random int32", - DefaultValue: "3", - }, - "u64": { - Usage: "some random uint64", - DefaultValue: "5", - }, - "deprecated_field": { - Deprecated: "don't use this", - }, - "shorthand_deprecated_field": { - Shorthand: "d", - Deprecated: "bad idea", - }, - "hidden_bool": { - Hidden: true, - }, - }, - }, - }, - SubCommands: map[string]*autocliv1.ServiceCommandDescriptor{ - // we test the sub-command functionality using the same service with different options - "deprecatedmsg": { - Service: testpb.Msg_ServiceDesc.ServiceName, - RpcCommandOptions: []*autocliv1.RpcCommandOptions{ - { - RpcMethod: "Send", - Deprecated: "dont use this", - Short: "deprecated subcommand", - }, - }, - }, - "skipmsg": { - Service: testpb.Msg_ServiceDesc.ServiceName, - RpcCommandOptions: []*autocliv1.RpcCommandOptions{ - { - RpcMethod: "Send", - Skip: true, - Short: "skip subcommand", - }, - }, + RpcMethod: "Send", + Use: "send [from_key_or_address] [to_address] [amount] [flags]", + Short: "Send coins from one account to another", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "from_address"}, {ProtoField: "to_address"}, {ProtoField: "amount"}}, }, }, + EnhanceCustomCommand: true, } -func TestMsgOptions(t *testing.T) { +func TestMsg(t *testing.T) { fixture := initFixture(t) out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send", - "5", "6", "1foo", - "--uint32", "7", - "--u64", "8", - "--output", "json", - ) - assert.NilError(t, err) - - response := out.String() - var output testpb.MsgRequest - err = protojson.Unmarshal([]byte(response), &output) - assert.NilError(t, err) - assert.Equal(t, output.GetU32(), uint32(7)) - assert.Equal(t, output.GetPositional1(), int32(5)) - assert.Equal(t, output.GetPositional2(), "6") -} - -func TestMsgOutputFormat(t *testing.T) { - fixture := initFixture(t) - - out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, - "send", "5", "6", "1foo", + "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", "1foo", + "--generate-only", "--output", "json", ) assert.NilError(t, err) - assert.Assert(t, strings.Contains(out.String(), "{")) - - out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, - "send", "5", "6", "1foo", - "--output", "text", - ) - assert.NilError(t, err) - assert.Assert(t, strings.Contains(out.String(), "positional1: 5")) + golden.Assert(t, out.String(), "msg-output.golden") } func TestMsgOptionsError(t *testing.T) { @@ -138,92 +48,13 @@ func TestMsgOptionsError(t *testing.T) { _, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send", "5", - "--uint32", "7", - "--u64", "8", ) - assert.ErrorContains(t, err, "requires at least 2 arg(s)") + assert.ErrorContains(t, err, "accepts 3 arg(s)") _, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, - "send", "5", "6", `{"denom":"foo","amount":"1"}`, - "--uint32", "7", - "--u64", "abc", + "send", "foo", "bar", "invalid", ) - assert.ErrorContains(t, err, "invalid argument ") -} - -func TestDeprecatedMsg(t *testing.T) { - fixture := initFixture(t) - - out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, - "send", "1", "abc", "--deprecated-field", "foo", - ) - assert.NilError(t, err) - assert.Assert(t, strings.Contains(out.String(), "--deprecated-field has been deprecated")) - - out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, - "send", "1", "abc", "5stake", "-d", "foo", - ) - assert.NilError(t, err) - assert.Assert(t, strings.Contains(out.String(), "--shorthand-deprecated-field has been deprecated")) -} - -func TestEverythingMsg(t *testing.T) { - fixture := initFixture(t) - - out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, - "send", - "1", - "abc", - "1234foo", - "4321foo", - "--output", "json", - "--a-bool", - "--an-enum", "two", - "--a-message", `{"bar":"abc", "baz":-3}`, - "--duration", "4h3s", - "--uint32", "27", - "--u64", "3267246890", - "--i32", "-253", - "--i64", "-234602347", - "--str", "def", - "--timestamp", "2019-01-02T00:01:02Z", - "--a-coin", "10000000foo", - "--an-address", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", - "--bz", "c2RncXdlZndkZ3NkZw==", - "--page-count-total", - "--page-key", "MTIzNTQ4N3NnaGRhcw==", - "--page-limit", "1000", - "--page-offset", "10", - "--page-reverse", - "--bools", "true", - "--bools", "false,false,true", - "--enums", "one", - "--enums", "five", - "--enums", "two", - "--strings", "abc", - "--strings", "xyz", - "--strings", "xyz,qrs", - "--durations", "3s", - "--durations", "5s", - "--durations", "10h", - "--some-messages", "{}", - "--some-messages", `{"bar":"baz"}`, - "--some-messages", `{"baz":-1}`, - "--uints", "1,2,3", - "--uints", "4", - ) - assert.NilError(t, err) - - response := out.String() - var output testpb.MsgRequest - err = protojson.Unmarshal([]byte(response), &output) - assert.NilError(t, err) - assert.Equal(t, output.GetU32(), uint32(27)) - assert.Equal(t, output.GetU64(), uint64(3267246890)) - assert.Equal(t, output.GetPositional1(), int32(1)) - assert.Equal(t, output.GetPositional2(), "abc") - assert.Equal(t, output.GetABool(), true) - assert.Equal(t, output.GetAnEnum(), testpb.Enum_ENUM_TWO) + assert.ErrorContains(t, err, "invalid argument") } func TestHelpMsg(t *testing.T) { @@ -236,19 +67,18 @@ func TestHelpMsg(t *testing.T) { out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send", "-h") assert.NilError(t, err) golden.Assert(t, out.String(), "help-echo-msg.golden") - - out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "deprecatedmsg", "send", "-h") - assert.NilError(t, err) - golden.Assert(t, out.String(), "help-deprecated-msg.golden") } -func TestBuildMsgCommand(t *testing.T) { +func TestBuildCustomMsgCommand(t *testing.T) { b := &Builder{} customCommandCalled := false appOptions := AppOptions{ ModuleOptions: map[string]*autocliv1.ModuleOptions{ "test": { - Tx: testCmdMsgDesc, + Tx: &autocliv1.ServiceCommandDescriptor{ + Service: testpb.Msg_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{}, + }, }, }, } @@ -264,44 +94,6 @@ func TestBuildMsgCommand(t *testing.T) { assert.Assert(t, customCommandCalled) } -func TestErrorBuildMsgCommand(t *testing.T) { - fixture := initFixture(t) - b := fixture.b - b.AddQueryConnFlags = nil - b.AddTxConnFlags = nil - - commandDescriptor := &autocliv1.ServiceCommandDescriptor{ - Service: testpb.Msg_ServiceDesc.ServiceName, - RpcCommandOptions: []*autocliv1.RpcCommandOptions{ - { - RpcMethod: "Send", - PositionalArgs: []*autocliv1.PositionalArgDescriptor{ - { - ProtoField: "un-existent-proto-field", - }, - }, - }, - }, - } - - appOptions := AppOptions{ - ModuleOptions: map[string]*autocliv1.ModuleOptions{ - "test": { - Tx: commandDescriptor, - }, - }, - ClientCtx: b.ClientCtx, - } - - _, err := b.BuildMsgCommand(appOptions, nil) - assert.ErrorContains(t, err, "can't find field un-existent-proto-field") - - nonExistentService := &autocliv1.ServiceCommandDescriptor{Service: "un-existent-service"} - appOptions.ModuleOptions["test"].Tx = nonExistentService - _, err = b.BuildMsgCommand(appOptions, nil) - assert.ErrorContains(t, err, "can't find service un-existent-service") -} - func TestNotFoundErrorsMsg(t *testing.T) { fixture := initFixture(t) b := fixture.b @@ -353,38 +145,3 @@ func TestNotFoundErrorsMsg(t *testing.T) { }) assert.ErrorContains(t, err, "can't find field un-existent-flag") } - -func TestEnhanceMessageCommand(t *testing.T) { - b := &Builder{} - // Test that the command has a subcommand - cmd := &cobra.Command{Use: "test"} - cmd.AddCommand(&cobra.Command{Use: "test"}) - - appOptions := AppOptions{ - ModuleOptions: map[string]*autocliv1.ModuleOptions{ - "test": {}, - }, - } - - err := b.enhanceCommandCommon(cmd, msgCmdType, appOptions, map[string]*cobra.Command{}) - assert.NilError(t, err) - - cmd = &cobra.Command{Use: "test"} - - appOptions.ModuleOptions = map[string]*autocliv1.ModuleOptions{} - customCommands := map[string]*cobra.Command{ - "test2": {Use: "test"}, - } - err = b.enhanceCommandCommon(cmd, msgCmdType, appOptions, customCommands) - assert.NilError(t, err) - - cmd = &cobra.Command{Use: "test"} - appOptions = AppOptions{ - ModuleOptions: map[string]*autocliv1.ModuleOptions{ - "test": {Tx: nil}, - }, - } - customCommands = map[string]*cobra.Command{} - err = b.enhanceCommandCommon(cmd, msgCmdType, appOptions, customCommands) - assert.NilError(t, err) -} diff --git a/client/v2/autocli/query_test.go b/client/v2/autocli/query_test.go index bc556af268a6..b1945f83995a 100644 --- a/client/v2/autocli/query_test.go +++ b/client/v2/autocli/query_test.go @@ -613,7 +613,7 @@ func TestOutputFormat(t *testing.T) { assert.Assert(t, strings.Contains(out.String(), " positional1: 1")) } -func TestHelp(t *testing.T) { +func TestHelpQuery(t *testing.T) { fixture := initFixture(t) out, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "-h") @@ -633,7 +633,7 @@ func TestHelp(t *testing.T) { golden.Assert(t, out.String(), "help-skip.golden") } -func TestDeprecated(t *testing.T) { +func TestDeprecatedQuery(t *testing.T) { fixture := initFixture(t) out, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", @@ -670,7 +670,7 @@ func TestBuildCustomQueryCommand(t *testing.T) { assert.Assert(t, customCommandCalled) } -func TestNotFoundErrors(t *testing.T) { +func TestNotFoundErrorsQuery(t *testing.T) { fixture := initFixture(t) b := fixture.b b.AddQueryConnFlags = nil diff --git a/client/v2/autocli/testdata/help-deprecated-msg.golden b/client/v2/autocli/testdata/help-deprecated-msg.golden deleted file mode 100644 index 31d61d736cbe..000000000000 --- a/client/v2/autocli/testdata/help-deprecated-msg.golden +++ /dev/null @@ -1,64 +0,0 @@ -Command "send" is deprecated, dont use this -deprecated subcommand - -Usage: - test deprecatedmsg send [flags] - -Flags: - --a-bool - --a-coin cosmos.base.v1beta1.Coin - --a-message testpb.AMessage (json) - --a-validator-address account address or key name - -a, --account-number uint The account number of the signing account (offline mode only) - --an-address account address or key name - --an-enum Enum (unspecified | one | two | five | neg-three) (default unspecified) - --aux Generate aux signer data instead of sending a tx - --bools bools (default []) - -b, --broadcast-mode string Transaction broadcasting mode (sync|async) (default "sync") - --bz binary - --chain-id string The network chain ID - --deprecated-field string - --dry-run ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it (when enabled, the local Keybase is not accessible) - --duration duration - --durations duration (repeated) - --enums Enum (unspecified | one | two | five | neg-three) (repeated) - --fee-granter string Fee granter grants fees for the transaction - --fee-payer string Fee payer pays fees for the transaction instead of deducting from the signer - --fees string Fees to pay along with transaction; eg: 10uatom - --from string Name or address of private key with which to sign - --gas string gas limit to set per-transaction; set to "auto" to calculate sufficient gas automatically. Note: "auto" option doesn't always report accurate results. Set a valid coin value to adjust the result. Can be used instead of "fees". (default 200000) - --gas-adjustment float adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored (default 1) - --gas-prices string Gas prices in decimal format to determine the transaction fee (e.g. 0.1uatom) - --generate-only Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase only accessed when providing a key name) - -h, --help help for send - --hidden-bool - --i32 int32 - --i64 int - --keyring-backend string Select keyring's backend (os|file|kwallet|pass|test|memory) (default "os") - --keyring-dir string The client Keyring directory; if omitted, the default 'home' directory will be used - --ledger Use a connected Ledger device - --node string : to CometBFT rpc interface for this chain (default "tcp://localhost:26657") - --note string Note to add a description to the transaction (previously --memo) - --offline Offline mode (does not allow any online functionality) - -o, --output string Output format (text|json) (default "json") - --page-count-total - --page-key binary - --page-limit uint - --page-offset uint - --page-reverse - --positional1 int32 - --positional2 string - --positional3-varargs cosmos.base.v1beta1.Coin (repeated) - -s, --sequence uint The sequence number of the signing account (offline mode only) - --shorthand-deprecated-field string - --sign-mode string Choose sign mode (direct|amino-json|direct-aux), this is an advanced feature - --some-messages testpb.AMessage (json) (repeated) - --str string - --strings strings - --timeout-height uint Set a block timeout height to prevent the tx from being committed past a certain height - --timestamp timestamp (RFC 3339) - --tip string 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, and is ignored if the target chain didn't enable the TipDecorator - --u32 uint32 - --u64 uint - --uints uints (default []) - -y, --yes Skip tx broadcasting prompt confirmation diff --git a/client/v2/autocli/testdata/help-echo-msg.golden b/client/v2/autocli/testdata/help-echo-msg.golden index 0b5e9e69b756..e082cd565f71 100644 --- a/client/v2/autocli/testdata/help-echo-msg.golden +++ b/client/v2/autocli/testdata/help-echo-msg.golden @@ -1,66 +1,32 @@ -send msg the value provided by the user as a proto JSON object with populated with the provided fields and positional arguments +Send coins from one account to another Usage: - test send [pos1] [pos2] [pos3...] [flags] - -Aliases: - send, s - -Examples: -send 1 abc {} + test send [from_key_or_address] [to_address] [amount] [flags] Flags: - --a-bool - --a-coin cosmos.base.v1beta1.Coin - --a-message testpb.AMessage (json) - --a-validator-address account address or key name - -a, --account-number uint The account number of the signing account (offline mode only) - --an-address account address or key name - --an-enum Enum (unspecified | one | two | five | neg-three) (default unspecified) - --aux Generate aux signer data instead of sending a tx - --bools bools (default []) - -b, --broadcast-mode string Transaction broadcasting mode (sync|async) (default "sync") - --bz binary - --chain-id string The network chain ID - --deprecated-field string (DEPRECATED: don't use this) - --dry-run ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it (when enabled, the local Keybase is not accessible) - --duration duration - --durations duration (repeated) - --enums Enum (unspecified | one | two | five | neg-three) (repeated) - --fee-granter string Fee granter grants fees for the transaction - --fee-payer string Fee payer pays fees for the transaction instead of deducting from the signer - --fees string Fees to pay along with transaction; eg: 10uatom - --from string Name or address of private key with which to sign - --gas string gas limit to set per-transaction; set to "auto" to calculate sufficient gas automatically. Note: "auto" option doesn't always report accurate results. Set a valid coin value to adjust the result. Can be used instead of "fees". (default 200000) - --gas-adjustment float adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored (default 1) - --gas-prices string Gas prices in decimal format to determine the transaction fee (e.g. 0.1uatom) - --generate-only Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase only accessed when providing a key name) - -h, --help help for send - --i32 int32 some random int32 - --i64 int - --keyring-backend string Select keyring's backend (os|file|kwallet|pass|test|memory) (default "os") - --keyring-dir string The client Keyring directory; if omitted, the default 'home' directory will be used - --ledger Use a connected Ledger device - --node string : to CometBFT rpc interface for this chain (default "tcp://localhost:26657") - --note string Note to add a description to the transaction (previously --memo) - --offline Offline mode (does not allow any online functionality) - -o, --output string Output format (text|json) (default "json") - --page-count-total - --page-key binary - --page-limit uint - --page-offset uint - --page-reverse - -s, --sequence uint The sequence number of the signing account (offline mode only) - -d, --shorthand-deprecated-field string (DEPRECATED: bad idea) - --sign-mode string Choose sign mode (direct|amino-json|direct-aux), this is an advanced feature - --some-messages testpb.AMessage (json) (repeated) - --str string - --strings strings - --timeout-height uint Set a block timeout height to prevent the tx from being committed past a certain height - --timestamp timestamp (RFC 3339) - --tip string 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, and is ignored if the target chain didn't enable the TipDecorator - --u64 uint some random uint64 - -u, --uint32 uint32 some random uint32 - --uints uints (default []) - -v, --version version for send - -y, --yes Skip tx broadcasting prompt confirmation + -a, --account-number uint The account number of the signing account (offline mode only) + --aux Generate aux signer data instead of sending a tx + -b, --broadcast-mode string Transaction broadcasting mode (sync|async) (default "sync") + --chain-id string The network chain ID + --dry-run ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it (when enabled, the local Keybase is not accessible) + --fee-granter string Fee granter grants fees for the transaction + --fee-payer string Fee payer pays fees for the transaction instead of deducting from the signer + --fees string Fees to pay along with transaction; eg: 10uatom + --from string Name or address of private key with which to sign + --gas string gas limit to set per-transaction; set to "auto" to calculate sufficient gas automatically. Note: "auto" option doesn't always report accurate results. Set a valid coin value to adjust the result. Can be used instead of "fees". (default 200000) + --gas-adjustment float adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored (default 1) + --gas-prices string Gas prices in decimal format to determine the transaction fee (e.g. 0.1uatom) + --generate-only Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase only accessed when providing a key name) + -h, --help help for send + --keyring-backend string Select keyring's backend (os|file|kwallet|pass|test|memory) (default "os") + --keyring-dir string The client Keyring directory; if omitted, the default 'home' directory will be used + --ledger Use a connected Ledger device + --node string : to CometBFT rpc interface for this chain (default "tcp://localhost:26657") + --note string Note to add a description to the transaction (previously --memo) + --offline Offline mode (does not allow any online functionality) + -o, --output string Output format (text|json) (default "json") + -s, --sequence uint The sequence number of the signing account (offline mode only) + --sign-mode string Choose sign mode (direct|amino-json|direct-aux), this is an advanced feature + --timeout-height uint Set a block timeout height to prevent the tx from being committed past a certain height + --tip string 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, and is ignored if the target chain didn't enable the TipDecorator + -y, --yes Skip tx broadcasting prompt confirmation diff --git a/client/v2/autocli/testdata/help-toplevel-msg.golden b/client/v2/autocli/testdata/help-toplevel-msg.golden index 0eac1e006f1f..51d33ed95e69 100644 --- a/client/v2/autocli/testdata/help-toplevel-msg.golden +++ b/client/v2/autocli/testdata/help-toplevel-msg.golden @@ -5,11 +5,13 @@ Usage: test [command] Available Commands: - completion Generate the autocompletion script for the specified shell - deprecatedmsg Tx commands for the testpb.Msg service - help Help about any command - send send msg the value provided by the user - skipmsg Tx commands for the testpb.Msg service + burn + completion Generate the autocompletion script for the specified shell + help Help about any command + multi-send + send Send coins from one account to another + set-send-enabled + update-params Flags: -h, --help help for test diff --git a/client/v2/autocli/testdata/msg-output.golden b/client/v2/autocli/testdata/msg-output.golden new file mode 100644 index 000000000000..73bddd4ad8ae --- /dev/null +++ b/client/v2/autocli/testdata/msg-output.golden @@ -0,0 +1 @@ +{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk","to_address":"cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk","amount":[{"denom":"foo","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""},"tip":null},"signatures":[]} diff --git a/client/v2/go.mod b/client/v2/go.mod index 011065cb198e..1502b41bb691 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -69,6 +69,7 @@ require ( github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.1.0 // indirect + github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect diff --git a/client/v2/go.sum b/client/v2/go.sum index 819af0aca15e..9389960eaddc 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -785,6 +785,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= @@ -864,6 +865,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -934,6 +936,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1089,6 +1092,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From d0c4b434d4f1411e1ab8934f8936ea1b23154af1 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Wed, 4 Oct 2023 17:38:07 +0200 Subject: [PATCH 11/20] add tests for from flag --- client/v2/autocli/flag/builder.go | 11 ++++--- client/v2/autocli/msg.go | 13 ++++++++ client/v2/autocli/msg_test.go | 52 +++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/client/v2/autocli/flag/builder.go b/client/v2/autocli/flag/builder.go index f0accc2e0971..6c1dbe3b148b 100644 --- a/client/v2/autocli/flag/builder.go +++ b/client/v2/autocli/flag/builder.go @@ -93,7 +93,7 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m } fields := messageType.Descriptor().Fields() - signerFieldName := getSignerFieldName(messageType.Descriptor()) + signerFieldName := GetSignerFieldName(messageType.Descriptor()) isPositional := map[string]bool{} @@ -200,8 +200,9 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m flagOptsByFlagName := map[string]*autocliv1.FlagOptions{} for i := 0; i < fields.Len(); i++ { field := fields.Get(i) - // skips positional args and signer field - if isPositional[string(field.Name())] || string(field.Name()) == signerFieldName { + // skips positional args and signer field if already set + if isPositional[string(field.Name())] || + (string(field.Name()) == signerFieldName && messageBinder.SignerInfo.FieldName == flags.FlagFrom) { continue } @@ -412,9 +413,9 @@ func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) Type } } -// getSignerFieldName gets signer field name of a message. +// GetSignerFieldName gets signer field name of a message. // AutoCLI supports only one signer field per message. -func getSignerFieldName(descriptor protoreflect.MessageDescriptor) string { +func GetSignerFieldName(descriptor protoreflect.MessageDescriptor) string { signersFields := proto.GetExtension(descriptor.Options(), msgv1.E_Signer).([]string) if len(signersFields) == 0 { return "" diff --git a/client/v2/autocli/msg.go b/client/v2/autocli/msg.go index a2bd5eb9051a..79cd25b5265a 100644 --- a/client/v2/autocli/msg.go +++ b/client/v2/autocli/msg.go @@ -11,6 +11,7 @@ import ( "google.golang.org/protobuf/types/dynamicpb" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + "cosmossdk.io/client/v2/autocli/flag" "github.com/cosmos/cosmos-sdk/client" clienttx "github.com/cosmos/cosmos-sdk/client/tx" @@ -127,6 +128,18 @@ func (b *Builder) BuildMsgMethodCommand(descriptor protoreflect.MethodDescriptor clientCtx = clientCtx.WithTxConfig(txConfigWithTextual) clientCtx.Output = cmd.OutOrStdout() + // set signer to signer field if empty + fd := input.Descriptor().Fields().ByName(protoreflect.Name(flag.GetSignerFieldName(input.Descriptor()))) + if addr := input.Get(fd).String(); addr == "" { + signerFromFlag := clientCtx.GetFromAddress() + signer, err := b.ClientCtx.AddressCodec.BytesToString(signerFromFlag.Bytes()) + if err != nil { + return fmt.Errorf("failed to set signer on message, got %v: %w", signerFromFlag, err) + } + + input.Set(fd, protoreflect.ValueOfString(signer)) + } + // AutoCLI uses protov2 messages, while the SDK only supports proto v1 messages. // Here we use dynamicpb, to create a proto v1 compatible message. // The SDK codec will handle protov2 -> protov1 (marshal) diff --git a/client/v2/autocli/msg_test.go b/client/v2/autocli/msg_test.go index 86d328aaa4a6..96b930c33c52 100644 --- a/client/v2/autocli/msg_test.go +++ b/client/v2/autocli/msg_test.go @@ -19,6 +19,14 @@ var buildModuleMsgCommand = func(moduleName string, b *Builder) (*cobra.Command, return cmd, err } +func buildCustomModuleMsgCommand(cmdDescriptor *autocliv1.ServiceCommandDescriptor) func(moduleName string, b *Builder) (*cobra.Command, error) { + return func(moduleName string, b *Builder) (*cobra.Command, error) { + cmd := topLevelCmd(moduleName, fmt.Sprintf("Transactions commands for the %s module", moduleName)) + err := b.AddMsgServiceCommands(cmd, cmdDescriptor) + return cmd, err + } +} + var bankAutoCLI = &autocliv1.ServiceCommandDescriptor{ Service: bankv1beta1.Msg_ServiceDesc.ServiceName, RpcCommandOptions: []*autocliv1.RpcCommandOptions{ @@ -41,6 +49,50 @@ func TestMsg(t *testing.T) { ) assert.NilError(t, err) golden.Assert(t, out.String(), "msg-output.golden") + + out, err = runCmd(fixture.conn, fixture.b, buildCustomModuleMsgCommand(&autocliv1.ServiceCommandDescriptor{ + Service: bankv1beta1.Msg_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Send", + Use: "send [from_key_or_address] [to_address] [amount] [flags]", + Short: "Send coins from one account to another", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to_address"}, {ProtoField: "amount"}}, + // from_address should be automatically added + }, + }, + EnhanceCustomCommand: true, + }), "send", + "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", "1foo", + "--from", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", + "--generate-only", + "--output", "json", + ) + assert.NilError(t, err) + golden.Assert(t, out.String(), "msg-output.golden") + + out, err = runCmd(fixture.conn, fixture.b, buildCustomModuleMsgCommand(&autocliv1.ServiceCommandDescriptor{ + Service: bankv1beta1.Msg_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Send", + Use: "send [from_key_or_address] [to_address] [amount] [flags]", + Short: "Send coins from one account to another", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to_address"}, {ProtoField: "amount"}}, + FlagOptions: map[string]*autocliv1.FlagOptions{ + "from_address": {Name: "sender"}, // use a custom flag for signer + }, + }, + }, + EnhanceCustomCommand: true, + }), "send", + "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", "1foo", + "--sender", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", + "--generate-only", + "--output", "json", + ) + assert.NilError(t, err) + golden.Assert(t, out.String(), "msg-output.golden") } func TestMsgOptionsError(t *testing.T) { From fc7be9dc1ec8c2eafe1b4719e2c7b1677dcc28e6 Mon Sep 17 00:00:00 2001 From: atheesh Date: Thu, 5 Oct 2023 12:40:39 +0530 Subject: [PATCH 12/20] fix tests --- x/bank/autocli.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/x/bank/autocli.go b/x/bank/autocli.go index 9bd39d53d94d..a87398ba0a4f 100644 --- a/x/bank/autocli.go +++ b/x/bank/autocli.go @@ -96,12 +96,12 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Use: "send [from_key_or_address] [to_address] [amount]", Short: "Send funds from one account to another.", Long: `Send funds from one account to another. -Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. -When using '--dry-run' a key name cannot be used, only a bech32 address.`, - PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to"}, {ProtoField: "amount"}}, - FlagOptions: map[string]*autocliv1.FlagOptions{ - "sender": {Name: "from", Shorthand: "f", Usage: "Address of the sender"}, - }, + Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. + When using '--dry-run' a key name cannot be used, only a bech32 address.`, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to_address"}, {ProtoField: "amount"}}, + // FlagOptions: map[string]*autocliv1.FlagOptions{ + // "sender": {Name: "from", Shorthand: "f", Usage: "Address of the sender"}, + // }, }, }, }, From 4664eca75c481e37d40364c05148e8924328978f Mon Sep 17 00:00:00 2001 From: atheesh Date: Thu, 5 Oct 2023 13:33:02 +0530 Subject: [PATCH 13/20] fix cmds --- x/bank/autocli.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/x/bank/autocli.go b/x/bank/autocli.go index a87398ba0a4f..9fe5a42bc519 100644 --- a/x/bank/autocli.go +++ b/x/bank/autocli.go @@ -103,6 +103,18 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { // "sender": {Name: "from", Shorthand: "f", Usage: "Address of the sender"}, // }, }, + { + RpcMethod: "UpdateParams", + Skip: true, // skipped because authority gated + }, + { + RpcMethod: "Burn", + Skip: true, // skipped because authority gated + }, + { + RpcMethod: "SetSendEnabled", + Skip: true, // skipped because authority gated + }, }, }, } From 0876b6dc8b970a6ae57f76967534817f9e4a2a51 Mon Sep 17 00:00:00 2001 From: atheesh Date: Thu, 5 Oct 2023 15:44:13 +0530 Subject: [PATCH 14/20] review changes --- CHANGELOG.md | 2 ++ x/bank/autocli.go | 7 ------- x/bank/client/cli/tx.go | 45 ----------------------------------------- 3 files changed, 2 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72dc04203087..de7274cfe386 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features +* (testutil) [#17868](https://github.com/cosmos/cosmos-sdk/pull/17868) Added helper method `SubmitTestTx` in testutil to broadcast test txns to test e2e tests. * (x/protocolpool) [#17657](https://github.com/cosmos/cosmos-sdk/pull/17657) Create a new `x/protocolpool` module that is responsible for handling community pool funds. This module is split out into a new module from x/distribution. * (baseapp) [#16581](https://github.com/cosmos/cosmos-sdk/pull/16581) Implement Optimistic Execution as an experimental feature (not enabled by default). * (client/keys) [#17639](https://github.com/cosmos/cosmos-sdk/pull/17639) Allows using and saving public keys encoded as base64 @@ -64,6 +65,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes +* (testutil) [#17868](https://github.com/cosmos/cosmos-sdk/pull/17868) `MsgSendExec` has been removed because of AutoCLI migration. * (x/distribution) [#17657](https://github.com/cosmos/cosmos-sdk/pull/17657) The `FundCommunityPool` and `DistributeFromFeePool` keeper methods are now removed from x/distribution. * (x/distribution) [#17657](https://github.com/cosmos/cosmos-sdk/pull/17657) The distribution module keeper now takes a new argument `PoolKeeper` in addition. * (app) [#17838](https://github.com/cosmos/cosmos-sdk/pull/17838) Params module was removed from simapp and all imports of the params module removed throughout the repo. diff --git a/x/bank/autocli.go b/x/bank/autocli.go index 9fe5a42bc519..e96788943f03 100644 --- a/x/bank/autocli.go +++ b/x/bank/autocli.go @@ -99,18 +99,11 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. When using '--dry-run' a key name cannot be used, only a bech32 address.`, PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to_address"}, {ProtoField: "amount"}}, - // FlagOptions: map[string]*autocliv1.FlagOptions{ - // "sender": {Name: "from", Shorthand: "f", Usage: "Address of the sender"}, - // }, }, { RpcMethod: "UpdateParams", Skip: true, // skipped because authority gated }, - { - RpcMethod: "Burn", - Skip: true, // skipped because authority gated - }, { RpcMethod: "SetSendEnabled", Skip: true, // skipped because authority gated diff --git a/x/bank/client/cli/tx.go b/x/bank/client/cli/tx.go index 289ffea4db75..d45db2b248f1 100644 --- a/x/bank/client/cli/tx.go +++ b/x/bank/client/cli/tx.go @@ -29,57 +29,12 @@ func NewTxCmd(ac address.Codec) *cobra.Command { } txCmd.AddCommand( - // NewSendTxCmd(ac), NewMultiSendTxCmd(ac), ) return txCmd } -// // NewSendTxCmd returns a CLI command handler for creating a MsgSend transaction. -// func NewSendTxCmd(ac address.Codec) *cobra.Command { -// cmd := &cobra.Command{ -// Use: "send [from_key_or_address] [to_address] [amount]", -// Short: "Send funds from one account to another.", -// Long: `Send funds from one account to another. -// Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. -// When using '--dry-run' a key name cannot be used, only a bech32 address. -// `, -// Args: cobra.ExactArgs(3), -// RunE: func(cmd *cobra.Command, args []string) error { -// err := cmd.Flags().Set(flags.FlagFrom, args[0]) -// if err != nil { -// return err -// } -// clientCtx, err := client.GetClientTxContext(cmd) -// if err != nil { -// return err -// } -// toAddr, err := ac.StringToBytes(args[1]) -// if err != nil { -// return err -// } - -// coins, err := sdk.ParseCoinsNormalized(args[2]) -// if err != nil { -// return err -// } - -// if len(coins) == 0 { -// return fmt.Errorf("invalid coins") -// } - -// msg := types.NewMsgSend(clientCtx.GetFromAddress(), toAddr, coins) - -// return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) -// }, -// } - -// flags.AddTxFlagsToCmd(cmd) - -// return cmd -// } - // NewMultiSendTxCmd returns a CLI command handler for creating a MsgMultiSend transaction. // For a better UX this command is limited to send funds from one account to two or more accounts. func NewMultiSendTxCmd(ac address.Codec) *cobra.Command { From 27fa12dc0ca69fd21b15c7ea6e518f9ee8f13882 Mon Sep 17 00:00:00 2001 From: atheesh Date: Thu, 5 Oct 2023 16:16:14 +0530 Subject: [PATCH 15/20] delete x/nft tx_test file --- x/nft/client/cli/tx_test.go | 249 ------------------------------------ 1 file changed, 249 deletions(-) delete mode 100644 x/nft/client/cli/tx_test.go diff --git a/x/nft/client/cli/tx_test.go b/x/nft/client/cli/tx_test.go deleted file mode 100644 index 0071dcc98818..000000000000 --- a/x/nft/client/cli/tx_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package cli_test - -import ( - "context" - "fmt" - "io" - "testing" - - abci "github.com/cometbft/cometbft/abci/types" - rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/core/address" - "cosmossdk.io/math" - "cosmossdk.io/x/nft" - "cosmossdk.io/x/nft/client/cli" - nftmodule "cosmossdk.io/x/nft/module" - nfttestutil "cosmossdk.io/x/nft/testutil" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - addresscodec "github.com/cosmos/cosmos-sdk/codec/address" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" - "github.com/cosmos/cosmos-sdk/testutil" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/testutil/network" - sdk "github.com/cosmos/cosmos-sdk/types" - testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -const ( - OwnerName = "owner" - Owner = "cosmos1kznrznww4pd6gx0zwrpthjk68fdmqypjpkj5hp" - OwnerArmor = `-----BEGIN TENDERMINT PRIVATE KEY----- -salt: C3586B75587D2824187D2CDA22B6AFB6 -type: secp256k1 -kdf: bcrypt - -1+15OrCKgjnwym1zO3cjo/SGe3PPqAYChQ5wMHjdUbTZM7mWsH3/ueL6swgjzI3b -DDzEQAPXBQflzNW6wbne9IfT651zCSm+j1MWaGk= -=wEHs ------END TENDERMINT PRIVATE KEY-----` - - testClassID = "kitty" - testClassName = "Crypto Kitty" - testClassSymbol = "kitty" - testClassDescription = "Crypto Kitty" - testClassURI = "class uri" - testID = "kitty1" - testURI = "kitty uri" -) - -var ( - ExpClass = nft.Class{ - Id: testClassID, - Name: testClassName, - Symbol: testClassSymbol, - Description: testClassDescription, - Uri: testClassURI, - } - - ExpNFT = nft.NFT{ - ClassId: testClassID, - Id: testID, - Uri: testURI, - } -) - -type CLITestSuite struct { - suite.Suite - - kr keyring.Keyring - encCfg testutilmod.TestEncodingConfig - baseCtx client.Context - clientCtx client.Context - ctx context.Context - - owner sdk.AccAddress - - ac address.Codec -} - -func TestCLITestSuite(t *testing.T) { - suite.Run(t, new(CLITestSuite)) -} - -func (s *CLITestSuite) SetupSuite() { - s.encCfg = testutilmod.MakeTestEncodingConfig(nftmodule.AppModuleBasic{}) - banktypes.RegisterInterfaces(s.encCfg.InterfaceRegistry) - s.kr = keyring.NewInMemory(s.encCfg.Codec) - s.baseCtx = client.Context{}. - WithKeyring(s.kr). - WithTxConfig(s.encCfg.TxConfig). - WithCodec(s.encCfg.Codec). - WithClient(clitestutil.MockCometRPC{Client: rpcclientmock.Client{}}). - WithAccountRetriever(client.MockAccountRetriever{}). - WithOutput(io.Discard). - WithChainID("test-chain"). - WithAddressCodec(addresscodec.NewBech32Codec("cosmos")). - WithValidatorAddressCodec(addresscodec.NewBech32Codec("cosmosvaloper")). - WithConsensusAddressCodec(addresscodec.NewBech32Codec("cosmosvalcons")) - - s.ctx = svrcmd.CreateExecuteContext(context.Background()) - ctxGen := func() client.Context { - bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{}) - c := clitestutil.NewMockCometRPC(abci.ResponseQuery{ - Value: bz, - }) - return s.baseCtx.WithClient(c) - } - s.clientCtx = ctxGen() - - cfg, err := network.DefaultConfigWithAppConfig(nfttestutil.AppConfig) - s.Require().NoError(err) - - genesisState := cfg.GenesisState - nftGenesis := nft.GenesisState{ - Classes: []*nft.Class{&ExpClass}, - Entries: []*nft.Entry{{ - Owner: Owner, - Nfts: []*nft.NFT{&ExpNFT}, - }}, - } - - nftDataBz, err := s.encCfg.Codec.MarshalJSON(&nftGenesis) - s.Require().NoError(err) - genesisState[nft.ModuleName] = nftDataBz - - s.ac = addresscodec.NewBech32Codec("cosmos") - - s.initAccount() -} - -func (s *CLITestSuite) TestCLITxSend() { - accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - - extraArgs := []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, OwnerName), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), - } - - testCases := []struct { - name string - args []string - expectedCode uint32 - expectErr bool - expErrMsg string - }{ - { - "class id is empty", - []string{ - "", - testID, - accounts[0].Address.String(), - }, - 0, - true, - "class-id, nft-id and receiver cannot be empty", - }, - { - "nft id is empty", - []string{ - testClassID, - "", - accounts[0].Address.String(), - }, - 0, - true, - "class-id, nft-id and receiver cannot be empty", - }, - { - "empty receiver address", - []string{ - testClassID, - testID, - "", - }, - 0, - true, - "class-id, nft-id and receiver cannot be empty", - }, - { - "valid transaction", - []string{ - testClassID, - testID, - accounts[0].Address.String(), - }, - 0, - false, - "", - }, - } - - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - args := append(tc.args, extraArgs...) - cmd := cli.NewCmdSend() - cmd.SetContext(s.ctx) - cmd.SetArgs(args) - - s.Require().NoError(client.SetCmdClientContextHandler(s.clientCtx, cmd)) - - out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, args) - if tc.expectErr { - s.Require().Error(err) - s.Require().Contains(err.Error(), tc.expErrMsg) - } else { - var txResp sdk.TxResponse - s.Require().NoError(err) - s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } -} - -func (s *CLITestSuite) initAccount() { - ctx := s.clientCtx - err := ctx.Keyring.ImportPrivKey(OwnerName, OwnerArmor, "1234567890") - s.Require().NoError(err) - accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - - keyinfo, err := ctx.Keyring.Key(OwnerName) - s.Require().NoError(err) - - s.owner, err = keyinfo.GetAddress() - s.Require().NoError(err) - - amount := sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(200))) - msgSend := &banktypes.MsgSend{ - FromAddress: accounts[0].Address.String(), - ToAddress: s.owner.String(), - Amount: amount, - } - - _, err = clitestutil.SubmitTestTx( - s.clientCtx, - msgSend, - accounts[0].Address, - clitestutil.TestTxConfig{GenOnly: true}, - ) - s.Require().NoError(err) -} From 6593fac0c843f7210fea79e8effe16d42b0c3838 Mon Sep 17 00:00:00 2001 From: atheesh Date: Thu, 5 Oct 2023 16:23:48 +0530 Subject: [PATCH 16/20] review changes --- x/authz/keeper/keeper_test.go | 4 ---- x/bank/autocli.go | 6 ++++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index f043154df50f..5dc8ac76c93f 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -1,7 +1,6 @@ package keeper_test import ( - "fmt" "testing" "time" @@ -61,10 +60,7 @@ func (s *TestSuite) SetupTest() { s.encCfg.TxConfig.TxDecoder(), ) s.baseApp.SetCMS(testCtx.CMS) - fmt.Printf("s.baseApp.MsgServiceRouter()1: %v\n", s.baseApp.MsgServiceRouter()) s.baseApp.SetInterfaceRegistry(s.encCfg.InterfaceRegistry) - fmt.Printf("s.encCfg.InterfaceRegistry: %v\n", s.encCfg.InterfaceRegistry) - fmt.Printf("s.baseApp.MsgServiceRouter()2: %v\n", s.baseApp.MsgServiceRouter()) s.addrs = simtestutil.CreateIncrementalAccounts(7) diff --git a/x/bank/autocli.go b/x/bank/autocli.go index e96788943f03..dee12eef74b0 100644 --- a/x/bank/autocli.go +++ b/x/bank/autocli.go @@ -100,6 +100,12 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { When using '--dry-run' a key name cannot be used, only a bech32 address.`, PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to_address"}, {ProtoField: "amount"}}, }, + { + RpcMethod: "Burn", + Use: "burn [from_key_or_address] [amount]", + Short: "Burns the amount specified from the given account.", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "amount"}}, + }, { RpcMethod: "UpdateParams", Skip: true, // skipped because authority gated From c916ef3bc63520dbb8e557f8f3b186fdd9b1d144 Mon Sep 17 00:00:00 2001 From: atheesh Date: Thu, 5 Oct 2023 17:02:05 +0530 Subject: [PATCH 17/20] review changes --- x/bank/autocli.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x/bank/autocli.go b/x/bank/autocli.go index dee12eef74b0..652de10fa536 100644 --- a/x/bank/autocli.go +++ b/x/bank/autocli.go @@ -93,16 +93,16 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { RpcMethod: "Send", - Use: "send [from_key_or_address] [to_address] [amount]", + Use: "send [to_address] [amount] --from [from]", Short: "Send funds from one account to another.", Long: `Send funds from one account to another. - Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. + Note, the '--from' flag is ignored as it is implied from [from_key_or]. When using '--dry-run' a key name cannot be used, only a bech32 address.`, PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to_address"}, {ProtoField: "amount"}}, }, { RpcMethod: "Burn", - Use: "burn [from_key_or_address] [amount]", + Use: "burn [amount] --from [from]", Short: "Burns the amount specified from the given account.", PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "amount"}}, }, From 56879ff3685ac687b04c5029cde6746ed9f1f443 Mon Sep 17 00:00:00 2001 From: atheesh Date: Thu, 5 Oct 2023 17:10:13 +0530 Subject: [PATCH 18/20] review changes --- x/bank/autocli.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x/bank/autocli.go b/x/bank/autocli.go index 652de10fa536..e7b6044970c0 100644 --- a/x/bank/autocli.go +++ b/x/bank/autocli.go @@ -93,18 +93,18 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { RpcCommandOptions: []*autocliv1.RpcCommandOptions{ { RpcMethod: "Send", - Use: "send [to_address] [amount] --from [from]", + Use: "send [from_key_or_address] [to_address] [amount]", Short: "Send funds from one account to another.", Long: `Send funds from one account to another. Note, the '--from' flag is ignored as it is implied from [from_key_or]. When using '--dry-run' a key name cannot be used, only a bech32 address.`, - PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to_address"}, {ProtoField: "amount"}}, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "from_address"}, {ProtoField: "to_address"}, {ProtoField: "amount"}}, }, { RpcMethod: "Burn", - Use: "burn [amount] --from [from]", + Use: "burn [from_key_or_address] [amount]", Short: "Burns the amount specified from the given account.", - PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "amount"}}, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "from_address"}, {ProtoField: "amount"}}, }, { RpcMethod: "UpdateParams", From c359f0472f78fbbfd0b35a62d1b7c6f3a67055e3 Mon Sep 17 00:00:00 2001 From: atheesh Date: Thu, 5 Oct 2023 19:17:46 +0530 Subject: [PATCH 19/20] review changes --- tests/e2e/tx/benchmarks_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/e2e/tx/benchmarks_test.go b/tests/e2e/tx/benchmarks_test.go index fba472d03c0c..cf6ddd1dd1b8 100644 --- a/tests/e2e/tx/benchmarks_test.go +++ b/tests/e2e/tx/benchmarks_test.go @@ -71,11 +71,11 @@ func BenchmarkTx(b *testing.B) { assert.NilError(b, err) // Check the result and gas used are correct. // - // The 12 events are: - // - Sending Fee to the pool: coin_spent, coin_received, transfer and message.sender= - // - tx.* events: tx.fee, tx.acc_seq, tx.signature - // - Sending Amount to recipient: coin_spent, coin_received, transfer and message.sender= - // - Msg events: message.module=bank and message.action=/cosmos.bank.v1beta1.MsgSend (in one message) + // The 10 events are: + // - Sending Fee to the pool (3 events): coin_spent, coin_received, transfer + // - tx.* events (3 events): tx.fee, tx.acc_seq, tx.signature + // - Sending Amount to recipient (3 events): coin_spent, coin_received, transfer and message.sender= + // - Msg events (1 event): message.module=bank, message.action=/cosmos.bank.v1beta1.MsgSend and message.sender= assert.Equal(b, 10, len(res.GetResult().GetEvents())) assert.Assert(b, res.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty. } From 1d23f7073abfc2d2a96528947f6f1799b18b17b5 Mon Sep 17 00:00:00 2001 From: atheesh Date: Thu, 5 Oct 2023 19:18:04 +0530 Subject: [PATCH 20/20] review changes --- tests/e2e/tx/benchmarks_test.go | 6 +++--- x/bank/autocli.go | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/e2e/tx/benchmarks_test.go b/tests/e2e/tx/benchmarks_test.go index cf6ddd1dd1b8..78c1df1c8a9d 100644 --- a/tests/e2e/tx/benchmarks_test.go +++ b/tests/e2e/tx/benchmarks_test.go @@ -75,7 +75,7 @@ func BenchmarkTx(b *testing.B) { // - Sending Fee to the pool (3 events): coin_spent, coin_received, transfer // - tx.* events (3 events): tx.fee, tx.acc_seq, tx.signature // - Sending Amount to recipient (3 events): coin_spent, coin_received, transfer and message.sender= - // - Msg events (1 event): message.module=bank, message.action=/cosmos.bank.v1beta1.MsgSend and message.sender= + // - Msg events (1 event): message.module=bank, message.action=/cosmos.bank.v1beta1.MsgSend and message.sender= (all in one event) assert.Equal(b, 10, len(res.GetResult().GetEvents())) assert.Assert(b, res.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty. } @@ -128,7 +128,7 @@ func NewE2EBenchmarkSuite(tb testing.TB) *E2EBenchmarkSuite { Amount: sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdkmath.NewInt(1))), } - out1, err := cli.SubmitTestTx( + out, err = cli.SubmitTestTx( val.ClientCtx, msgSend1, val.Address, @@ -142,7 +142,7 @@ func NewE2EBenchmarkSuite(tb testing.TB) *E2EBenchmarkSuite { assert.NilError(tb, err) var tr sdk.TxResponse - assert.NilError(tb, val.ClientCtx.Codec.UnmarshalJSON(out1.Bytes(), &tr)) + assert.NilError(tb, val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &tr)) assert.Equal(tb, uint32(0), tr.Code) resp, err := cli.GetTxResponse(s.network, val.ClientCtx, tr.TxHash) diff --git a/x/bank/autocli.go b/x/bank/autocli.go index e7b6044970c0..a4f680e3a578 100644 --- a/x/bank/autocli.go +++ b/x/bank/autocli.go @@ -96,15 +96,16 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Use: "send [from_key_or_address] [to_address] [amount]", Short: "Send funds from one account to another.", Long: `Send funds from one account to another. - Note, the '--from' flag is ignored as it is implied from [from_key_or]. - When using '--dry-run' a key name cannot be used, only a bech32 address.`, - PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "from_address"}, {ProtoField: "to_address"}, {ProtoField: "amount"}}, + Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. + When using '--dry-run' a key name cannot be used, only a bech32 address. + Note: multiple coins can be send by space separated.`, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "from_address"}, {ProtoField: "to_address"}, {ProtoField: "amount", Varargs: true}}, }, { RpcMethod: "Burn", Use: "burn [from_key_or_address] [amount]", Short: "Burns the amount specified from the given account.", - PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "from_address"}, {ProtoField: "amount"}}, + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "from_address"}, {ProtoField: "amount", Varargs: true}}, }, { RpcMethod: "UpdateParams",