feat(x/authz): autocli tx support (#17970)

Co-authored-by: Julien Robert <julien@rbrt.fr>
Co-authored-by: Emmanuel T Odeke <emmanuel@orijtech.com>
This commit is contained in:
atheeshp 2023-10-08 17:04:36 +05:30 committed by GitHub
parent 9053582132
commit 83622c8f2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 20 additions and 330 deletions

View File

@ -174,9 +174,8 @@ func (s *E2ETestSuite) TearDownSuite() {
}
var (
typeMsgSend = bank.SendAuthorization{}.MsgTypeURL()
typeMsgVote = sdk.MsgTypeURL(&govv1.MsgVote{})
typeMsgSubmitProposal = sdk.MsgTypeURL(&govv1.MsgSubmitProposal{})
typeMsgSend = bank.SendAuthorization{}.MsgTypeURL()
typeMsgVote = sdk.MsgTypeURL(&govv1.MsgVote{})
)
func execDelegate(val *network.Validator, args []string) (testutil.BufferWriter, error) {
@ -185,156 +184,6 @@ func execDelegate(val *network.Validator, args []string) (testutil.BufferWriter,
return clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
}
func (s *E2ETestSuite) TestCmdRevokeAuthorizations() {
val := s.network.Validators[0]
grantee := s.grantee[0]
twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()
// send-authorization
_, err := authzclitestutil.CreateGrant(
val.ClientCtx,
[]string{
grantee.String(),
"send",
fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()),
},
)
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
// generic-authorization
_, err = authzclitestutil.CreateGrant(
val.ClientCtx,
[]string{
grantee.String(),
"generic",
fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()),
},
)
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
// generic-authorization used for amino testing
_, err = authzclitestutil.CreateGrant(
val.ClientCtx,
[]string{
grantee.String(),
"generic",
fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgSubmitProposal),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()),
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
},
)
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
testCases := []struct {
name string
args []string
respType proto.Message
expectedCode uint32
expectErr bool
}{
{
"invalid grantee address",
[]string{
"invalid grantee",
typeMsgSend,
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
},
nil,
0,
true,
},
{
"invalid granter address",
[]string{
grantee.String(),
typeMsgSend,
fmt.Sprintf("--%s=%s", flags.FlagFrom, "granter"),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
},
nil,
0,
true,
},
{
"Valid tx send authorization",
[]string{
grantee.String(),
typeMsgSend,
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()),
},
&sdk.TxResponse{}, 0,
false,
},
{
"Valid tx generic authorization",
[]string{
grantee.String(),
typeMsgVote,
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()),
},
&sdk.TxResponse{}, 0,
false,
},
{
"Valid tx with amino",
[]string{
grantee.String(),
typeMsgSubmitProposal,
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()),
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
},
&sdk.TxResponse{}, 0,
false,
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := cli.NewCmdRevokeAuthorization(addresscodec.NewBech32Codec("cosmos"))
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
txResp := tc.respType.(*sdk.TxResponse)
s.Require().NoError(clitestutil.CheckTxCode(s.network, val.ClientCtx, txResp.TxHash, tc.expectedCode))
}
})
}
}
func (s *E2ETestSuite) TestExecAuthorizationWithExpiration() {
val := s.network.Validators[0]
grantee := s.grantee[0]

View File

@ -47,7 +47,6 @@ func GetTxCmd(ac address.Codec) *cobra.Command {
AuthorizationTxCmd.AddCommand(
NewCmdGrantAuthorization(ac),
NewCmdRevokeAuthorization(ac),
NewCmdExecAuthorization(),
)
@ -55,6 +54,8 @@ func GetTxCmd(ac address.Codec) *cobra.Command {
}
// NewCmdGrantAuthorization returns a CLI command handler for creating a MsgGrant transaction.
//
// cannot give autocli support, can be CLI breaking
func NewCmdGrantAuthorization(ac address.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "grant <grantee> <authorization_type=\"send\"|\"generic\"|\"delegate\"|\"unbond\"|\"redelegate\"> --from <granter>",
@ -228,41 +229,9 @@ func getExpireTime(cmd *cobra.Command) (*time.Time, error) {
return &e, nil
}
// NewCmdRevokeAuthorization returns a CLI command handler for creating a MsgRevoke transaction.
func NewCmdRevokeAuthorization(ac address.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "revoke [grantee] [msg-type-url] --from=[granter]",
Short: "revoke authorization",
Long: strings.TrimSpace(
fmt.Sprintf(`revoke authorization from a granter to a grantee:
Example:
$ %s tx %s revoke cosmos1skj.. %s --from=cosmos1skj..
`, version.AppName, authz.ModuleName, bank.SendAuthorization{}.MsgTypeURL()),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
grantee, err := ac.StringToBytes(args[0])
if err != nil {
return err
}
granter := clientCtx.GetFromAddress()
msgAuthorized := args[1]
msg := authz.NewMsgRevoke(granter, grantee, msgAuthorized)
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}
flags.AddTxFlagsToCmd(cmd)
return cmd
}
// NewCmdExecAuthorization returns a CLI command handler for creating a MsgExec transaction.
//
// cannot give autocli support, can be CLI breaking
func NewCmdExecAuthorization() *cobra.Command {
cmd := &cobra.Command{
Use: "exec [tx-json-file] --from [grantee]",

View File

@ -35,11 +35,7 @@ import (
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
)
var (
typeMsgSend = banktypes.SendAuthorization{}.MsgTypeURL()
typeMsgVote = sdk.MsgTypeURL(&govv1.MsgVote{})
typeMsgSubmitProposal = sdk.MsgTypeURL(&govv1.MsgSubmitProposal{})
)
var typeMsgVote = sdk.MsgTypeURL(&govv1.MsgVote{})
type CLITestSuite struct {
suite.Suite
@ -475,142 +471,6 @@ func (s *CLITestSuite) TestCLITxGrantAuthorization() {
}
}
func (s *CLITestSuite) TestCmdRevokeAuthorizations() {
val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
grantee := s.grantee[0]
twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix()
// send-authorization
_, err := authzclitestutil.CreateGrant(s.clientCtx,
[]string{
grantee.String(),
"send",
fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
},
)
s.Require().NoError(err)
// generic-authorization
_, err = authzclitestutil.CreateGrant(s.clientCtx,
[]string{
grantee.String(),
"generic",
fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
},
)
s.Require().NoError(err)
// generic-authorization used for amino testing
_, err = authzclitestutil.CreateGrant(s.clientCtx,
[]string{
grantee.String(),
"generic",
fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgSubmitProposal),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
},
)
s.Require().NoError(err)
testCases := []struct {
name string
args []string
respType proto.Message
expectErr bool
}{
{
"invalid grantee address",
[]string{
"invalid grantee",
typeMsgSend,
fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
},
nil,
true,
},
{
"invalid granter address",
[]string{
grantee.String(),
typeMsgSend,
fmt.Sprintf("--%s=%s", flags.FlagFrom, "granter"),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
},
nil,
true,
},
{
"Valid tx send authorization",
[]string{
grantee.String(),
typeMsgSend,
fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
},
&sdk.TxResponse{},
false,
},
{
"Valid tx generic authorization",
[]string{
grantee.String(),
typeMsgVote,
fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
},
&sdk.TxResponse{},
false,
},
{
"Valid tx with amino",
[]string{
grantee.String(),
typeMsgSubmitProposal,
fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON),
},
&sdk.TxResponse{},
false,
},
}
for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := cli.NewCmdRevokeAuthorization(addresscodec.NewBech32Codec("cosmos"))
out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String())
}
})
}
}
func (s *CLITestSuite) TestExecAuthorizationWithExpiration() {
val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)

View File

@ -7,6 +7,7 @@ import (
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/authz"
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
)
@ -47,7 +48,18 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
},
},
Tx: &autocliv1.ServiceCommandDescriptor{
Service: authzv1beta1.Msg_ServiceDesc.ServiceName,
Service: authzv1beta1.Msg_ServiceDesc.ServiceName,
EnhanceCustomCommand: true,
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{
RpcMethod: "Revoke",
Use: "revoke [grantee] [msg-type-url] --from=[granter]",
Short: `Revoke authorization from a granter to a grantee`,
Example: fmt.Sprintf(`%s tx %s revoke cosmos1skj.. %s --from=cosmos1skj..`,
version.AppName, authz.ModuleName, bank.SendAuthorization{}.MsgTypeURL()),
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "grantee"}, {ProtoField: "msg_type_url"}},
},
},
},
}
}