Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions buf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ deps:
- buf.build/cosmos/ics23
- buf.build/googleapis/googleapis
- buf.build/protocolbuffers/wellknowntypes
- buf.build/cosmwasm/wasmd
212 changes: 212 additions & 0 deletions go/cli/authz_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

"cosmossdk.io/core/address"
"github.com/CosmWasm/wasmd/x/wasm/types"
"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
Expand Down Expand Up @@ -257,6 +258,217 @@ Examples:
cmd.Flags().Int64(cflags.FlagExpiration, 0, "Expire time as Unix timestamp. Set zero (0) for no expiry. Default is 0.")
cmd.Flags().StringSlice(cflags.FlagScope, []string{}, "Scopes for Deposit authorization, array of values. Allowed values deployment|bid")

cmd.AddCommand(
GetTxAuthzGrantContractAuthorizationCmd(),
GetTxAuthzGrantStoreCodeAuthorizationCmd(),
)

return cmd
}

func GetTxAuthzGrantContractAuthorizationCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "contract [grantee] [message_type=\"execution\"|\"migration\"] [contract_addr_bech32] --allow-raw-msgs [msg1,msg2,...] --allow-msg-keys [key1,key2,...] --allow-all-messages",
Short: "Grant authorization to interact with a contract on behalf of you",
Long: fmt.Sprintf(`Grant authorization to an address.
Examples:
$ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-calls 1 --no-token-transfer --expiration 1667979596

$ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-funds 100000uwasm --expiration 1667979596

$ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-calls 5 --max-funds 100000uwasm --expiration 1667979596
`, version.AppName, version.AppName, version.AppName),
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
Comment on lines +269 to +282
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | πŸ”΄ Critical

Missing PersistentPreRunE will cause command to fail.

The GetTxAuthzGrantContractAuthorizationCmd lacks PersistentPreRunE: TxPersistentPreRunE, which is required to initialize the client context. Compare with GetTxAuthzGrantAuthorizationCmd (line 64) and GetTxAuthzRevokeAuthorizationCmd (line 499) which both set this. Without it, MustClientFromContext at line 285 will panic or return an error.

Apply this diff to fix:

 func GetTxAuthzGrantContractAuthorizationCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "contract [grantee] [message_type=\"execution\"|\"migration\"] [contract_addr_bech32] --allow-raw-msgs [msg1,msg2,...] --allow-msg-keys [key1,key2,...] --allow-all-messages",
 		Short: "Grant authorization to interact with a contract on behalf of you",
 		Long: fmt.Sprintf(`Grant authorization to an address.
 Examples:
 $ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-calls 1 --no-token-transfer --expiration 1667979596

 $ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-funds 100000uwasm --expiration 1667979596

 $ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-calls 5 --max-funds 100000uwasm --expiration 1667979596
 `, version.AppName, version.AppName, version.AppName),
-		Args: cobra.ExactArgs(3),
-		RunE: func(cmd *cobra.Command, args []string) error {
+		Args:              cobra.ExactArgs(3),
+		PersistentPreRunE: TxPersistentPreRunE,
+		RunE: func(cmd *cobra.Command, args []string) error {
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func GetTxAuthzGrantContractAuthorizationCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "contract [grantee] [message_type=\"execution\"|\"migration\"] [contract_addr_bech32] --allow-raw-msgs [msg1,msg2,...] --allow-msg-keys [key1,key2,...] --allow-all-messages",
Short: "Grant authorization to interact with a contract on behalf of you",
Long: fmt.Sprintf(`Grant authorization to an address.
Examples:
$ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-calls 1 --no-token-transfer --expiration 1667979596
$ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-funds 100000uwasm --expiration 1667979596
$ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-calls 5 --max-funds 100000uwasm --expiration 1667979596
`, version.AppName, version.AppName, version.AppName),
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
func GetTxAuthzGrantContractAuthorizationCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "contract [grantee] [message_type=\"execution\"|\"migration\"] [contract_addr_bech32] --allow-raw-msgs [msg1,msg2,...] --allow-msg-keys [key1,key2,...] --allow-all-messages",
Short: "Grant authorization to interact with a contract on behalf of you",
Long: fmt.Sprintf(`Grant authorization to an address.
Examples:
$ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-calls 1 --no-token-transfer --expiration 1667979596
$ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-funds 100000uwasm --expiration 1667979596
$ %s tx grant contract <grantee_addr> execution <contract_addr> --allow-all-messages --max-calls 5 --max-funds 100000uwasm --expiration 1667979596
`, version.AppName, version.AppName, version.AppName),
Args: cobra.ExactArgs(3),
PersistentPreRunE: TxPersistentPreRunE,
RunE: func(cmd *cobra.Command, args []string) error {
πŸ€– Prompt for AI Agents
In go/cli/authz_tx.go around lines 269 to 282, the command returned by
GetTxAuthzGrantContractAuthorizationCmd is missing PersistentPreRunE:
TxPersistentPreRunE which is required to initialize the client context before
RunE; add PersistentPreRunE: TxPersistentPreRunE to the cobra.Command struct
literal (same place other commands set it) so MustClientFromContext used later
does not panic or error.

ctx := cmd.Context()

cl := MustClientFromContext(ctx)
cctx := cl.ClientContext()

grantee, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}

contract, err := sdk.AccAddressFromBech32(args[2])
if err != nil {
return err
}

msgKeys, err := cmd.Flags().GetStringSlice(cflags.FlagAllowedMsgKeys)
if err != nil {
return err
}

rawMsgs, err := cmd.Flags().GetStringSlice(cflags.FlagAllowedRawMsgs)
if err != nil {
return err
}

maxFundsStr, err := cmd.Flags().GetString(cflags.FlagMaxFunds)
if err != nil {
return fmt.Errorf("max funds: %s", err)
}

maxCalls, err := cmd.Flags().GetUint64(cflags.FlagMaxCalls)
if err != nil {
return err
}

exp, err := cmd.Flags().GetInt64(cflags.FlagExpiration)
if err != nil {
return err
}
if exp == 0 {
return errors.New("expiration must be set")
}

allowAllMsgs, err := cmd.Flags().GetBool(cflags.FlagAllowAllMsgs)
if err != nil {
return err
}

noTokenTransfer, err := cmd.Flags().GetBool(cflags.FlagNoTokenTransfer)
if err != nil {
return err
}

var limit types.ContractAuthzLimitX
switch {
case maxFundsStr != "" && maxCalls != 0 && !noTokenTransfer:
maxFunds, err := sdk.ParseCoinsNormalized(maxFundsStr)
if err != nil {
return fmt.Errorf("max funds: %s", err)
}
limit = types.NewCombinedLimit(maxCalls, maxFunds...)
case maxFundsStr != "" && maxCalls == 0 && !noTokenTransfer:
maxFunds, err := sdk.ParseCoinsNormalized(maxFundsStr)
if err != nil {
return fmt.Errorf("max funds: %s", err)
}
limit = types.NewMaxFundsLimit(maxFunds...)
case maxCalls != 0 && noTokenTransfer && maxFundsStr == "":
limit = types.NewMaxCallsLimit(maxCalls)
default:
return errors.New("invalid limit setup")
}

var filter types.ContractAuthzFilterX
switch {
case allowAllMsgs && len(msgKeys) != 0 || allowAllMsgs && len(rawMsgs) != 0 || len(msgKeys) != 0 && len(rawMsgs) != 0:
return errors.New("cannot set more than one filter within one grant")
case allowAllMsgs:
filter = types.NewAllowAllMessagesFilter()
case len(msgKeys) != 0:
filter = types.NewAcceptedMessageKeysFilter(msgKeys...)
case len(rawMsgs) != 0:
msgs := make([]types.RawContractMessage, len(rawMsgs))
for i, msg := range rawMsgs {
msgs[i] = types.RawContractMessage(msg)
}
filter = types.NewAcceptedMessagesFilter(msgs...)
default:
return errors.New("invalid filter setup")
}

grant, err := types.NewContractGrant(contract, limit, filter)
if err != nil {
return err
}

var authorization authz.Authorization
switch args[1] {
case "execution":
authorization = types.NewContractExecutionAuthorization(*grant)
case "migration":
authorization = types.NewContractMigrationAuthorization(*grant)
default:
return fmt.Errorf("%s authorization type not supported", args[1])
}

expire, err := getExpireTime(cmd)
if err != nil {
return err
}

grantMsg, err := authz.NewMsgGrant(cctx.GetFromAddress(), grantee, authorization, expire)
if err != nil {
return err
}

resp, err := cl.Tx().BroadcastMsgs(ctx, []sdk.Msg{grantMsg})
if err != nil {
return err
}

return cl.PrintMessage(resp)
},
}

cflags.AddTxFlagsToCmd(cmd)

cmd.Flags().StringSlice(cflags.FlagAllowedMsgKeys, []string{}, "Allowed msg keys")
cmd.Flags().StringSlice(cflags.FlagAllowedRawMsgs, []string{}, "Allowed raw msgs")
cmd.Flags().Uint64(cflags.FlagMaxCalls, 0, "Maximal number of calls to the contract")
cmd.Flags().String(cflags.FlagMaxFunds, "", "Maximal amount of tokens transferable to the contract.")
cmd.Flags().Int64(cflags.FlagExpiration, 0, "The Unix timestamp.")
cmd.Flags().Bool(cflags.FlagAllowAllMsgs, false, "Allow all messages")
cmd.Flags().Bool(cflags.FlagNoTokenTransfer, false, "Don't allow token transfer")

return cmd
}

func GetTxAuthzGrantStoreCodeAuthorizationCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "store-code [grantee] [code_hash:permission]",
Short: "Grant authorization to upload contract code on behalf of you",
Long: fmt.Sprintf(`Grant authorization to an address.
Examples:
$ %s tx grant store-code <grantee_addr> 13a1fc994cc6d1c81b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2a5:everybody 1wqrtry681b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2a5:nobody --expiration 1667979596

$ %s tx grant store-code <grantee_addr> *:%s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm,%s1vx8knpllrj7n963p9ttd80w47kpacrhuts497x
`, version.AppName, version.AppName, version.AppName, version.AppName),
Args: cobra.MinimumNArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
Comment on lines +421 to +432
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | πŸ”΄ Critical

Missing PersistentPreRunE on store-code grant command.

Same issue as the contract grant command - PersistentPreRunE: TxPersistentPreRunE is missing, which will cause the command to fail when attempting to retrieve the client context.

Apply this diff to fix:

 func GetTxAuthzGrantStoreCodeAuthorizationCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "store-code [grantee] [code_hash:permission]",
 		Short: "Grant authorization to upload contract code on behalf of you",
 		Long: fmt.Sprintf(`Grant authorization to an address.
 Examples:
 $ %s tx grant store-code <grantee_addr> 13a1fc994cc6d1c81b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2a5:everybody  1wqrtry681b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2a5:nobody --expiration 1667979596

 $ %s tx grant store-code <grantee_addr> *:%s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm,%s1vx8knpllrj7n963p9ttd80w47kpacrhuts497x
 `, version.AppName, version.AppName, version.AppName, version.AppName),
-		Args: cobra.MinimumNArgs(2),
-		RunE: func(cmd *cobra.Command, args []string) error {
+		Args:              cobra.MinimumNArgs(2),
+		PersistentPreRunE: TxPersistentPreRunE,
+		RunE: func(cmd *cobra.Command, args []string) error {
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func GetTxAuthzGrantStoreCodeAuthorizationCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "store-code [grantee] [code_hash:permission]",
Short: "Grant authorization to upload contract code on behalf of you",
Long: fmt.Sprintf(`Grant authorization to an address.
Examples:
$ %s tx grant store-code <grantee_addr> 13a1fc994cc6d1c81b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2a5:everybody 1wqrtry681b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2a5:nobody --expiration 1667979596
$ %s tx grant store-code <grantee_addr> *:%s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm,%s1vx8knpllrj7n963p9ttd80w47kpacrhuts497x
`, version.AppName, version.AppName, version.AppName, version.AppName),
Args: cobra.MinimumNArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
func GetTxAuthzGrantStoreCodeAuthorizationCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "store-code [grantee] [code_hash:permission]",
Short: "Grant authorization to upload contract code on behalf of you",
Long: fmt.Sprintf(`Grant authorization to an address.
Examples:
$ %s tx grant store-code <grantee_addr> 13a1fc994cc6d1c81b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2a5:everybody 1wqrtry681b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2a5:nobody --expiration 1667979596
$ %s tx grant store-code <grantee_addr> *:%s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm,%s1vx8knpllrj7n963p9ttd80w47kpacrhuts497x
`, version.AppName, version.AppName, version.AppName, version.AppName),
Args: cobra.MinimumNArgs(2),
PersistentPreRunE: TxPersistentPreRunE,
RunE: func(cmd *cobra.Command, args []string) error {
πŸ€– Prompt for AI Agents
In go/cli/authz_tx.go around lines 421 to 432, the store-code grant command is
missing the PersistentPreRunE hook so TxPersistentPreRunE is not invoked and
client context retrieval will fail; add PersistentPreRunE: TxPersistentPreRunE
to the cobra.Command literal (alongside Use/Short/Long/Args) so the command runs
the common pre-run initialization; ensure it matches the other grant commands'
placement and style.

ctx := cmd.Context()

cl := MustClientFromContext(ctx)
cctx := cl.ClientContext()

grantee, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
return err
}

grants, err := ParseStoreCodeGrants(args[1:])
if err != nil {
return err
}

authorization := types.NewStoreCodeAuthorization(grants...)

expire, err := getExpireTime(cmd)
if err != nil {
return err
}

grantMsg, err := authz.NewMsgGrant(cctx.GetFromAddress(), grantee, authorization, expire)
if err != nil {
return err
}

resp, err := cl.Tx().BroadcastMsgs(ctx, []sdk.Msg{grantMsg})
if err != nil {
return err
}

return cl.PrintMessage(resp)
},
}

cflags.AddTxFlagsToCmd(cmd)
cmd.Flags().Int64(cflags.FlagExpiration, 0, "The Unix timestamp.")

return cmd
}

Expand Down
31 changes: 20 additions & 11 deletions go/cli/configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,20 @@ func InterceptConfigsPreRunHandler(
cmd *cobra.Command,
envPrefixes []string,
allowEmptyEnv bool,
customAppConfigTemplate string,
customAppConfig interface{},
opts ...PreRunOption,
) error {
if len(envPrefixes) == 0 {
return ErrEmptyEnvPrefix
}

pOpts := &PreRunOptions{}

for _, opt := range opts {
if err := opt(pOpts); err != nil {
return err
}
}

serverCtx := server.NewDefaultContext()

// Configure the viper instance
Expand All @@ -174,7 +181,7 @@ func InterceptConfigsPreRunHandler(
serverCtx.Viper.AutomaticEnv()

// intercept configuration files, using both Viper instances separately
cfg, err := interceptConfigs(serverCtx.Viper, customAppConfigTemplate, customAppConfig)
cfg, err := interceptConfigs(serverCtx.Viper, pOpts.appConfigTemplate, pOpts.appConfig, pOpts.cmtCfg)
if err != nil {
return err
}
Expand All @@ -189,7 +196,7 @@ func InterceptConfigsPreRunHandler(
// the return value is a tendermint configuration object
serverCtx.Config = cfg

var opts []log.Option
var logOpts []log.Option

logTimeFmt, err := parseTimestampFormat(serverCtx.Viper.GetString(cflags.FlagLogTimestamp))
if err != nil {
Expand All @@ -199,7 +206,7 @@ func InterceptConfigsPreRunHandler(
logFmt := serverCtx.Viper.GetString(cflags.FlagLogFormat)
switch logFmt {
case cmtcfg.LogFormatJSON:
opts = append(opts, log.OutputJSONOption())
logOpts = append(logOpts, log.OutputJSONOption())
case "":
fallthrough
case cmtcfg.LogFormatPlain:
Expand All @@ -208,7 +215,7 @@ func InterceptConfigsPreRunHandler(
return fmt.Errorf("unsupported value \"%s\" for log_format flag. can be either plain|json", logFmt)
}

opts = append(opts,
logOpts = append(logOpts,
log.ColorOption(serverCtx.Viper.GetBool(cflags.FlagLogColor)),
log.TraceOption(serverCtx.Viper.GetBool(cflags.FlagTrace)),
log.TimeFormatOption(logTimeFmt),
Expand All @@ -226,13 +233,13 @@ func InterceptConfigsPreRunHandler(
return err
}

opts = append(opts, log.FilterOption(filterFunc))
logOpts = append(logOpts, log.FilterOption(filterFunc))
default:
opts = append(opts, log.LevelOption(logLvl))
logOpts = append(logOpts, log.LevelOption(logLvl))
}
}

logger := NewLogger(cmtlog.NewSyncWriter(os.Stdout), opts...).With(log.ModuleKey, "server")
logger := NewLogger(cmtlog.NewSyncWriter(os.Stdout), logOpts...).With(log.ModuleKey, "server")

serverCtx.Logger = logger

Expand Down Expand Up @@ -301,12 +308,14 @@ func bindFlags(cmd *cobra.Command, v *viper.Viper, envPrefixes []string) error {
// configuration file. The Tendermint configuration file is parsed given a root
// Viper object, whereas the application is parsed with the private package-aware
// viperCfg object.
func interceptConfigs(rootViper *viper.Viper, customAppTemplate string, customConfig interface{}) (*cmtcfg.Config, error) {
func interceptConfigs(rootViper *viper.Viper, customAppTemplate string, customConfig interface{}, conf *cmtcfg.Config) (*cmtcfg.Config, error) {
rootDir := rootViper.GetString(cflags.FlagHome)
configPath := filepath.Join(rootDir, "config")
tmCfgFile := filepath.Join(configPath, "config.toml")

conf := cmtcfg.DefaultConfig()
if conf == nil {
conf = cmtcfg.DefaultConfig()
}

switch _, err := os.Stat(tmCfgFile); {
case os.IsNotExist(err):
Expand Down
28 changes: 28 additions & 0 deletions go/cli/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,34 @@ const (
KeyIsTestnet = "is-testnet"
KeyTestnetConfig = "testnet-config"
KeyTestnetTriggerUpgrade = "testnet-trigger-upgrade"

FlagLabel = "label"
FlagSource = "code-source-url"
FlagBuilder = "builder"
FlagCodeHash = "code-hash"
FlagAdmin = "admin"
FlagNoAdmin = "no-admin"
FlagFixMsg = "fix-msg"
FlagRunAs = "run-as"
FlagInstantiateByEverybody = "instantiate-everybody"
FlagInstantiateNobody = "instantiate-nobody"
FlagInstantiateByAddress = "instantiate-only-address"
FlagInstantiateByAnyOfAddress = "instantiate-anyof-addresses"
FlagUnpinCode = "unpin-code"
FlagAllowedMsgKeys = "allow-msg-keys"
FlagAllowedRawMsgs = "allow-raw-msgs"
FlagMaxCalls = "max-calls"
FlagMaxFunds = "max-funds"
FlagAllowAllMsgs = "allow-all-messages"
FlagNoTokenTransfer = "no-token-transfer"
FlagExpedite = "expedite"

// wasm flags

FlagWasmMemoryCacheSize = "wasm.memory_cache_size"
FlagWasmQueryGasLimit = "wasm.query_gas_limit"
FlagWasmSimulationGasLimit = "wasm.simulation_gas_limit"
FlagWasmSkipWasmVMVersionCheck = "wasm.skip_wasmvm_version_check"
)

// List of supported output formats
Expand Down
Loading
Loading