feat(auth): autocli query support (backport #16650) (#16900)

Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
mergify[bot] 2023-07-10 12:07:38 +02:00 committed by GitHub
parent 8295e4a3e0
commit 3fee9db359
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 57 additions and 486 deletions

View File

@ -49,6 +49,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### API Breaking Changes
* (x/auth) [#16650](https://github.com/cosmos/cosmos-sdk/pull/16650) The testutil `QueryAccountExec` has been removed from auth as it was using the CLI.
* (types/math) [#16040](https://github.com/cosmos/cosmos-sdk/pull/16798) Remove aliases in `types/math.go` (part 2).
* (x/staking) [#16795](https://github.com/cosmos/cosmos-sdk/pull/16795) `DelegationToDelegationResponse`, `DelegationsToDelegationResponses`, `RedelegationsToRedelegationResponses` are no longer exported.

View File

@ -31,7 +31,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"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
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"
@ -289,50 +288,6 @@ func (s *E2ETestSuite) TestCLISignBatch() {
s.Require().Equal(sigs[0].Sequence, seq1)
}
func (s *E2ETestSuite) TestCliGetAccountAddressByID() {
require := s.Require()
val1 := s.network.Validators[0]
testCases := []struct {
name string
args []string
expectErr bool
}{
{
"not enough args",
[]string{fmt.Sprintf("--%s=json", flags.FlagOutput)},
true,
},
{
"invalid account id",
[]string{fmt.Sprint(-1), fmt.Sprintf("--%s=json", flags.FlagOutput)},
true,
},
{
"valid account id",
[]string{fmt.Sprint(0), fmt.Sprintf("--%s=json", flags.FlagOutput)},
false,
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := authcli.GetAccountAddressByIDCmd()
clientCtx := val1.ClientCtx
queryResJSON, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
var res authtypes.QueryAccountAddressByIDResponse
require.NoError(val1.ClientCtx.Codec.UnmarshalJSON(queryResJSON.Bytes(), &res))
require.NotNil(res.GetAccountAddress())
}
})
}
}
func (s *E2ETestSuite) TestCLIQueryTxCmdByHash() {
val := s.network.Validators[0]
@ -1228,10 +1183,8 @@ func (s *E2ETestSuite) TestMultisignBatch() {
defer filename.Close()
val.ClientCtx.HomeDir = strings.Replace(val.ClientCtx.HomeDir, "simd", "simcli", 1)
queryResJSON, err := authclitestutil.QueryAccountExec(val.ClientCtx, addr, addresscodec.NewBech32Codec("cosmos"))
account, err := val.ClientCtx.AccountRetriever.GetAccount(val.ClientCtx, addr)
s.Require().NoError(err)
var account sdk.AccountI
s.Require().NoError(val.ClientCtx.Codec.UnmarshalInterfaceJSON(queryResJSON.Bytes(), &account))
// sign-batch file
addr1, err := account1.GetAddress()
@ -1270,121 +1223,6 @@ func (s *E2ETestSuite) TestMultisignBatch() {
}
}
func (s *E2ETestSuite) TestGetAccountCmd() {
val := s.network.Validators[0]
_, _, addr1 := testdata.KeyTestPubAddr()
testCases := []struct {
name string
address sdk.AccAddress
expectErr bool
}{
{
"invalid address",
addr1,
true,
},
{
"valid address",
val.Address,
false,
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
clientCtx := val.ClientCtx
out, err := authclitestutil.QueryAccountExec(clientCtx, tc.address, addresscodec.NewBech32Codec("cosmos"))
if tc.expectErr {
s.Require().Error(err)
s.Require().NotEqual("internal", err.Error())
} else {
var acc sdk.AccountI
s.Require().NoError(val.ClientCtx.Codec.UnmarshalInterfaceJSON(out.Bytes(), &acc))
s.Require().Equal(val.Address, acc.GetAddress())
}
})
}
}
func (s *E2ETestSuite) TestGetAccountsCmd() {
val := s.network.Validators[0]
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, authcli.GetAccountsCmd(), []string{
fmt.Sprintf("--%s=json", flags.FlagOutput),
})
s.Require().NoError(err)
var res authtypes.QueryAccountsResponse
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res))
s.Require().NotEmpty(res.Accounts)
}
func (s *E2ETestSuite) TestQueryModuleAccountByNameCmd() {
val := s.network.Validators[0]
testCases := []struct {
name string
moduleName string
expectErr bool
}{
{
"invalid module name",
"gover",
true,
},
{
"valid module name",
"mint",
false,
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, authcli.QueryModuleAccountByNameCmd(), []string{
tc.moduleName,
fmt.Sprintf("--%s=json", flags.FlagOutput),
})
if tc.expectErr {
s.Require().Error(err)
s.Require().NotEqual("internal", err.Error())
} else {
var res authtypes.QueryModuleAccountByNameResponse
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res))
var account sdk.AccountI
err := val.ClientCtx.InterfaceRegistry.UnpackAny(res.Account, &account)
s.Require().NoError(err)
moduleAccount, ok := account.(sdk.ModuleAccountI)
s.Require().True(ok)
s.Require().Equal(tc.moduleName, moduleAccount.GetName())
}
})
}
}
func (s *E2ETestSuite) TestQueryModuleAccountsCmd() {
val := s.network.Validators[0]
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, authcli.QueryModuleAccountsCmd(), []string{
fmt.Sprintf("--%s=json", flags.FlagOutput),
})
s.Require().NoError(err)
var res authtypes.QueryModuleAccountsResponse
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res))
s.Require().NotEmpty(res.Accounts)
}
func TestGetBroadcastCommandOfflineFlag(t *testing.T) {
cmd := authcli.GetBroadcastCommand()
_ = testutil.ApplyMockIODiscardOutErr(cmd)
@ -1427,45 +1265,6 @@ func TestGetBroadcastCommandWithoutOfflineFlag(t *testing.T) {
require.Contains(t, out.String(), "connect: connection refused")
}
func (s *E2ETestSuite) TestQueryParamsCmd() {
val := s.network.Validators[0]
testCases := []struct {
name string
args []string
expectErr bool
}{
{
"happy case",
[]string{fmt.Sprintf("--%s=json", flags.FlagOutput)},
false,
},
{
"with specific height",
[]string{fmt.Sprintf("--%s=1", flags.FlagHeight), fmt.Sprintf("--%s=json", flags.FlagOutput)},
false,
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := authcli.QueryParamsCmd()
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
s.Require().NotEqual("internal", err.Error())
} else {
var authParams authtypes.Params
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &authParams))
s.Require().NotNil(authParams.MaxMemoCharacters)
}
})
}
}
// TestTxWithoutPublicKey makes sure sending a proto tx message without the
// public key doesn't cause any error in the RPC layer (broadcast).
// See https://github.com/cosmos/cosmos-sdk/issues/7585 for more details.

View File

@ -30,7 +30,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth"
authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtestutil "github.com/cosmos/cosmos-sdk/x/auth/client/testutil"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/bank"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
@ -818,43 +817,6 @@ func (s *CLITestSuite) TestGetBroadcastCommandWithoutOfflineFlag() {
s.Require().Contains(out.String(), "connect: connection refused")
}
func (s *CLITestSuite) TestQueryParamsCmd() {
testCases := []struct {
name string
args []string
expectErr bool
}{
{
"happy case",
[]string{fmt.Sprintf("--%s=json", flags.FlagOutput)},
false,
},
{
"with specific height",
[]string{fmt.Sprintf("--%s=1", flags.FlagHeight), fmt.Sprintf("--%s=json", flags.FlagOutput)},
false,
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := authcli.QueryParamsCmd()
clientCtx := s.clientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
s.Require().NotEqual("internal", err.Error())
} else {
var authParams authtypes.Params
s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &authParams))
s.Require().NotNil(authParams.MaxMemoCharacters)
}
})
}
}
// TestTxWithoutPublicKey makes sure sending a proto tx message without the
// public key doesn't cause any error in the RPC layer (broadcast).
// See https://github.com/cosmos/cosmos-sdk/issues/7585 for more details.

View File

@ -1,8 +1,14 @@
package auth
import (
"fmt"
authv1beta1 "cosmossdk.io/api/cosmos/auth/v1beta1"
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
_ "cosmossdk.io/api/cosmos/crypto/secp256k1" // register to that it shows up in protoregistry.GlobalTypes
_ "cosmossdk.io/api/cosmos/crypto/secp256r1" // register to that it shows up in protoregistry.GlobalTypes
"github.com/cosmos/cosmos-sdk/version"
)
// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface.
@ -11,18 +17,63 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
Query: &autocliv1.ServiceCommandDescriptor{
Service: authv1beta1.Query_ServiceDesc.ServiceName,
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{
RpcMethod: "Accounts",
Use: "accounts",
Short: "Query all the accounts",
},
{
RpcMethod: "Account",
Use: "account [address]",
Short: "query account by address",
Short: "Query account by address",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}},
},
{
RpcMethod: "AccountInfo",
Use: "account-info [address]",
Short: "Query account info which is common to all account types.",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}},
},
{
RpcMethod: "AccountAddressByID",
Use: "address-by-acc-num [acc-num]",
Short: "query account address by account number",
Short: "Query account address by account number",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "id"}},
},
{
RpcMethod: "ModuleAccounts",
Use: "module-accounts",
Short: "Query all module accounts",
},
{
RpcMethod: "ModuleAccountByName",
Use: "module-account [module-name]",
Short: "Query module account info by module name",
Example: fmt.Sprintf("%s q auth module-account gov", version.AppName),
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "name"}},
},
{
RpcMethod: "AddressBytesToString",
Use: "address-bytes-to-string [address-bytes]",
Short: "Transform an address bytes to string",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address_bytes"}},
},
{
RpcMethod: "AddressStringToBytes",
Use: "address-string-to-bytes [address-string]",
Short: "Transform an address string to bytes",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address_string"}},
},
{
RpcMethod: "Bech32Prefix",
Use: "bech32-prefix",
Short: "Query the chain bech32 prefix (if applicable)",
},
{
RpcMethod: "Params",
Use: "params",
Short: "Query the current auth parameters",
},
},
},
// Tx is purposely left empty, as the only tx is MsgUpdateParams which is gov gated.

View File

@ -1,16 +1,11 @@
package cli
import (
"context"
"fmt"
"strconv"
"strings"
"github.com/spf13/cobra"
"cosmossdk.io/core/address"
errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -18,11 +13,9 @@ import (
querytypes "github.com/cosmos/cosmos-sdk/types/query"
"github.com/cosmos/cosmos-sdk/version"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
const (
FlagEvents = "events" // TODO: Remove when #14758 is merged
FlagQuery = "query"
FlagType = "type"
FlagOrderBy = "order_by"
@ -35,232 +28,6 @@ const (
EventFormat = "{eventType}.{eventAttribute}={value}"
)
// GetQueryCmd returns the transaction commands for this module
func GetQueryCmd(ac address.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: types.ModuleName,
Short: "Querying commands for the auth module",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
cmd.AddCommand(
GetAccountCmd(ac),
GetAccountAddressByIDCmd(),
GetAccountsCmd(),
QueryParamsCmd(),
QueryModuleAccountsCmd(),
QueryModuleAccountByNameCmd(),
)
return cmd
}
// QueryParamsCmd returns the command handler for evidence parameter querying.
func QueryParamsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "params",
Short: "Query the current auth parameters",
Args: cobra.NoArgs,
Long: strings.TrimSpace(`Query the current auth parameters:
$ <appd> query auth params
`),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(&res.Params)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetAccountCmd returns a query account that will display the state of the
// account at a given address.
func GetAccountCmd(ac address.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "account [address]",
Short: "Query for account by address",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
_, err = ac.StringToBytes(args[0])
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Account(cmd.Context(), &types.QueryAccountRequest{Address: args[0]})
if err != nil {
node, err2 := clientCtx.GetNode()
if err2 != nil {
return err2
}
status, err2 := node.Status(context.Background())
if err2 != nil {
return err2
}
catchingUp := status.SyncInfo.CatchingUp
if !catchingUp {
return errorsmod.Wrapf(err, "your node may be syncing, please check node status using `/status`")
}
return err
}
return clientCtx.PrintProto(res.Account)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetAccountAddressByIDCmd returns a query account that will display the account address of a given account id.
func GetAccountAddressByIDCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "address-by-acc-num [acc-num]",
Aliases: []string{"address-by-id"},
Short: "Query for an address by account number",
Args: cobra.ExactArgs(1),
Example: fmt.Sprintf("%s q auth address-by-acc-num 1", version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
accNum, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.AccountAddressByID(cmd.Context(), &types.QueryAccountAddressByIDRequest{
AccountId: accNum,
})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// GetAccountsCmd returns a query command that will display a list of accounts
func GetAccountsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "accounts",
Short: "Query all the accounts",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Accounts(cmd.Context(), &types.QueryAccountsRequest{Pagination: pageReq})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "all-accounts")
return cmd
}
// QueryAllModuleAccountsCmd returns a list of all the existing module accounts with their account information and permissions
func QueryModuleAccountsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "module-accounts",
Short: "Query all module accounts",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.ModuleAccounts(context.Background(), &types.QueryModuleAccountsRequest{})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// QueryModuleAccountByNameCmd returns a command to
func QueryModuleAccountByNameCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "module-account [module-name]",
Short: "Query module account info by module name",
Args: cobra.ExactArgs(1),
Example: fmt.Sprintf("%s q auth module-account auth", version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
moduleName := args[0]
if len(moduleName) == 0 {
return fmt.Errorf("module name should not be empty")
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.ModuleAccountByName(context.Background(), &types.QueryModuleAccountByNameRequest{Name: moduleName})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// QueryTxsByEventsCmd returns a command to search through transactions by events.
func QueryTxsByEventsCmd() *cobra.Command {
cmd := &cobra.Command{

View File

@ -4,8 +4,6 @@ import (
"fmt"
"strings"
"cosmossdk.io/core/address"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
@ -91,12 +89,6 @@ func TxAuxToFeeExec(clientCtx client.Context, filename string, extraArgs ...stri
return clitestutil.ExecTestCLICmd(clientCtx, cli.GetAuxToFeeCommand(), append(args, extraArgs...))
}
func QueryAccountExec(clientCtx client.Context, address fmt.Stringer, ac address.Codec, extraArgs ...string) (testutil.BufferWriter, error) {
args := []string{address.String(), fmt.Sprintf("--%s=json", flags.FlagOutput)}
return clitestutil.ExecTestCLICmd(clientCtx, cli.GetAccountCmd(ac), append(args, extraArgs...))
}
func TxMultiSignBatchExec(clientCtx client.Context, filename, from, sigFile1, sigFile2 string, extraArgs ...string) (testutil.BufferWriter, error) {
args := []string{
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),

View File

@ -222,7 +222,7 @@ func (suite *KeeperTestSuite) TestGRPCQueryAccountAddressByID() {
}
}
func (suite *KeeperTestSuite) TestGRPCQueryParameters() {
func (suite *KeeperTestSuite) TestGRPCQueryParams() {
var (
req *types.QueryParamsRequest
expParams types.Params

View File

@ -21,7 +21,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"
"github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/auth/keeper"
@ -86,7 +85,7 @@ func (AppModuleBasic) GetTxCmd() *cobra.Command {
// GetQueryCmd returns the root query command for the auth module.
func (ab AppModuleBasic) GetQueryCmd() *cobra.Command {
return cli.GetQueryCmd(ab.ac)
return nil
}
// RegisterInterfaces registers interfaces and implementations of the auth module.