diff --git a/client/v2/autocli/msg.go b/client/v2/autocli/msg.go index 9493fc4808b9..199d1b4f3120 100644 --- a/client/v2/autocli/msg.go +++ b/client/v2/autocli/msg.go @@ -14,6 +14,7 @@ import ( autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" "cosmossdk.io/client/v2/autocli/flag" "cosmossdk.io/client/v2/internal/util" + addresscodec "cosmossdk.io/core/address" authtx "cosmossdk.io/x/auth/tx" authtxconfig "cosmossdk.io/x/auth/tx/config" @@ -150,16 +151,13 @@ func (b *Builder) BuildMsgMethodCommand(descriptor protoreflect.MethodDescriptor fd := input.Descriptor().Fields().ByName(protoreflect.Name(flag.GetSignerFieldName(input.Descriptor()))) addressCodec := b.Builder.AddressCodec - if options.GovProposal { // set message signer (authority) to gov module - govAuthority := authtypes.NewModuleAddress(govtypes.ModuleName) - - signer, err := addressCodec.BytesToString(govAuthority.Bytes()) - if err != nil { - return fmt.Errorf("failed to set authority on message: %w", err) - } + // handle gov proposals commands + if options.GovProposal { + return b.handleGovProposal(options, cmd, input, clientCtx, addressCodec, fd) + } - input.Set(fd, protoreflect.ValueOfString(signer)) - } else if addr := input.Get(fd).String(); addr == "" { // set signer to signer field if empty + // set signer to signer field if empty + if addr := input.Get(fd).String(); addr == "" { scalarType, ok := flag.GetScalarType(fd) if ok { // override address codec if validator or consensus address @@ -186,20 +184,6 @@ func (b *Builder) BuildMsgMethodCommand(descriptor protoreflect.MethodDescriptor msg := dynamicpb.NewMessage(input.Descriptor()) proto.Merge(msg, input.Interface()) - // create a gov proposal if enabled - if options.GovProposal { - proposal, err := govcli.ReadGovPropFlags(clientCtx, cmd.Flags()) - if err != nil { - return err - } - - if err := proposal.SetMsgs([]gogoproto.Message{msg}); err != nil { - return fmt.Errorf("failed to set msg in proposal %w", err) - } - - return clienttx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), proposal) - } - return clienttx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) } @@ -227,3 +211,43 @@ func (b *Builder) BuildMsgMethodCommand(descriptor protoreflect.MethodDescriptor return cmd, err } + +// handleGovProposal sets the authority field of the message to the gov module address and creates a gov proposal. +func (b *Builder) handleGovProposal( + options *autocliv1.RpcCommandOptions, + cmd *cobra.Command, + input protoreflect.Message, + clientCtx client.Context, + addressCodec addresscodec.Codec, + fd protoreflect.FieldDescriptor, +) error { + govAuthority := authtypes.NewModuleAddress(govtypes.ModuleName) + authority, err := addressCodec.BytesToString(govAuthority.Bytes()) + if err != nil { + return fmt.Errorf("failed to convert gov authority: %w", err) + } + input.Set(fd, protoreflect.ValueOfString(authority)) + + signerFromFlag := clientCtx.GetFromAddress() + signer, err := addressCodec.BytesToString(signerFromFlag.Bytes()) + if err != nil { + return fmt.Errorf("failed to set signer on message, got %v: %w", signerFromFlag, err) + } + + proposal, err := govcli.ReadGovPropCmdFlags(signer, cmd.Flags()) + if err != nil { + return err + } + + // 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()) + + if err := proposal.SetMsgs([]gogoproto.Message{msg}); err != nil { + return fmt.Errorf("failed to set msg in proposal %w", err) + } + + return clienttx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), proposal) +} diff --git a/client/v2/go.mod b/client/v2/go.mod index 0c487c6f6cba..56b6633c5403 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -166,6 +166,7 @@ replace ( cosmossdk.io/x/auth => ./../../x/auth cosmossdk.io/x/bank => ./../../x/bank cosmossdk.io/x/distribution => ./../../x/distribution + cosmossdk.io/x/gov => ./../../x/gov cosmossdk.io/x/mint => ./../../x/mint cosmossdk.io/x/protocolpool => ./../../x/protocolpool cosmossdk.io/x/slashing => ./../../x/slashing diff --git a/client/v2/go.sum b/client/v2/go.sum index bc69f8ef17db..4fe74f3fd546 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -51,8 +51,6 @@ cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig= cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= cosmossdk.io/store v1.0.0 h1:6tnPgTpTSIskaTmw/4s5C9FARdgFflycIc9OX8i1tOI= cosmossdk.io/store v1.0.0/go.mod h1:ABMprwjvx6IpMp8l06TwuMrj6694/QP5NIW+X6jaTYc= -cosmossdk.io/x/gov v0.0.0-20231113122742-912390d5fc4a h1:ASCFuF6NHUjjq3Yyu+ncV8kisGRyMr7OWmqtWjXgAZg= -cosmossdk.io/x/gov v0.0.0-20231113122742-912390d5fc4a/go.mod h1:8UMJW3pqnpwzsATAGG+KHHSzcjTxdf30VMwgI5xOf1s= cosmossdk.io/x/tx v0.12.0 h1:Ry2btjQdrfrje9qZ3iZeZSmDArjgxUJMMcLMrX4wj5U= cosmossdk.io/x/tx v0.12.0/go.mod h1:qTth2coAGkwCwOCjqQ8EAQg+9udXNRzcnSbMgGKGEI0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= diff --git a/client/v2/internal/flags/flags.go b/client/v2/internal/flags/flags.go index cd50a96be87b..6fe1e395414a 100644 --- a/client/v2/internal/flags/flags.go +++ b/client/v2/internal/flags/flags.go @@ -10,6 +10,9 @@ const ( // FlagNoIndent is the flag to not indent the output. FlagNoIndent = "no-indent" + + // FlagNoPrompt is the flag to not use a prompt for commands. + FlagNoPrompt = "no-prompt" ) // List of supported output formats diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index ada07254ac36..6167a0bfd8f7 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -28,6 +28,8 @@ const ( flagStatus = "status" FlagMetadata = "metadata" FlagSummary = "summary" + FlagExpedited = "expedited" + // Deprecated: only used for v1beta1 legacy proposals. FlagProposal = "proposal" // Deprecated: only used for v1beta1 legacy proposals. diff --git a/x/gov/client/cli/util.go b/x/gov/client/cli/util.go index 9b454f9b7f64..908de47055a9 100644 --- a/x/gov/client/cli/util.go +++ b/x/gov/client/cli/util.go @@ -132,13 +132,14 @@ func AddGovPropFlagsToCmd(cmd *cobra.Command) { cmd.Flags().String(FlagMetadata, "", "The metadata to include with the governance proposal") cmd.Flags().String(FlagTitle, "", "The title to put on the governance proposal") cmd.Flags().String(FlagSummary, "", "The summary to include with the governance proposal") + cmd.Flags().Bool(FlagExpedited, false, "Whether to expedite the governance proposal") } -// ReadGovPropFlags parses a MsgSubmitProposal from the provided context and flags. +// ReadGovPropCmdFlags parses a MsgSubmitProposal from the provided context and flags. // Setting the messages is up to the caller. // // See also AddGovPropFlagsToCmd. -func ReadGovPropFlags(clientCtx client.Context, flagSet *pflag.FlagSet) (*govv1.MsgSubmitProposal, error) { +func ReadGovPropCmdFlags(proposer string, flagSet *pflag.FlagSet) (*govv1.MsgSubmitProposal, error) { rv := &govv1.MsgSubmitProposal{} deposit, err := flagSet.GetString(FlagDeposit) @@ -167,7 +168,21 @@ func ReadGovPropFlags(clientCtx client.Context, flagSet *pflag.FlagSet) (*govv1. return nil, fmt.Errorf("could not read summary: %w", err) } - rv.Proposer = clientCtx.GetFromAddress().String() + rv.Expedited, err = flagSet.GetBool(FlagExpedited) + if err != nil { + return nil, fmt.Errorf("could not read expedited: %w", err) + } + + rv.Proposer = proposer return rv, nil } + +// ReadGovPropFlags parses a MsgSubmitProposal from the provided context and flags. +// Setting the messages is up to the caller. +// +// See also AddGovPropFlagsToCmd. +// Deprecated: use ReadPropCmdFlags instead, as this depends on global bech32 prefixes. +func ReadGovPropFlags(clientCtx client.Context, flagSet *pflag.FlagSet) (*govv1.MsgSubmitProposal, error) { + return ReadGovPropCmdFlags(clientCtx.GetFromAddress().String(), flagSet) +}