Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UpdateInstantiateConfig gov proposal #796

1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Yes
- Fix SudoContractProposal and ExecuteContractProposal [\#808](https://github.com/CosmWasm/wasmd/pull/808) ([the-frey](https://github.com/the-frey))

**Implemented Enhancements**
- Add UpdateInstantiateConfig governance proposal [\#820](https://github.com/CosmWasm/wasmd/pull/796) ([jhernandezb](https://github.com/jhernandezb))
- Upgrade wasmvm to v1.0.0-rc.0 [\#844](https://github.com/CosmWasm/wasmd/pull/844)
- Support state sync [\#478](https://github.com/CosmWasm/wasmd/issues/478)
- Upgrade to ibc-go v3 [\#806](https://github.com/CosmWasm/wasmd/issues/806)
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ proto-lint:
@$(DOCKER_BUF) lint --error-format=json

proto-check-breaking:
@$(DOCKER_BUF) breaking --against-input $(HTTPS_GIT)#branch=master
@$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=main
jhernandezb marked this conversation as resolved.
Show resolved Hide resolved

.PHONY: all install install-debug \
go-mod-cache draw-deps clean build format \
Expand Down
37 changes: 37 additions & 0 deletions docs/proto/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
- [MsgIBCSend](#cosmwasm.wasm.v1.MsgIBCSend)

- [cosmwasm/wasm/v1/proposal.proto](#cosmwasm/wasm/v1/proposal.proto)
- [AccessConfigUpdate](#cosmwasm.wasm.v1.AccessConfigUpdate)
- [ClearAdminProposal](#cosmwasm.wasm.v1.ClearAdminProposal)
- [ExecuteContractProposal](#cosmwasm.wasm.v1.ExecuteContractProposal)
- [InstantiateContractProposal](#cosmwasm.wasm.v1.InstantiateContractProposal)
Expand All @@ -54,6 +55,7 @@
- [SudoContractProposal](#cosmwasm.wasm.v1.SudoContractProposal)
- [UnpinCodesProposal](#cosmwasm.wasm.v1.UnpinCodesProposal)
- [UpdateAdminProposal](#cosmwasm.wasm.v1.UpdateAdminProposal)
- [UpdateInstantiateConfigProposal](#cosmwasm.wasm.v1.UpdateInstantiateConfigProposal)

- [cosmwasm/wasm/v1/query.proto](#cosmwasm/wasm/v1/query.proto)
- [CodeInfoResponse](#cosmwasm.wasm.v1.CodeInfoResponse)
Expand Down Expand Up @@ -641,6 +643,23 @@ MsgIBCSend



<a name="cosmwasm.wasm.v1.AccessConfigUpdate"></a>

### AccessConfigUpdate
AccessConfigUpdate contains the code id and the access config to be
applied.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `code_id` | [uint64](#uint64) | | CodeID is the reference to the stored WASM code to be updated |
| `instantiate_permission` | [AccessConfig](#cosmwasm.wasm.v1.AccessConfig) | | InstantiatePermission to apply to the set of code ids |






<a name="cosmwasm.wasm.v1.ClearAdminProposal"></a>

### ClearAdminProposal
Expand Down Expand Up @@ -814,6 +833,24 @@ UpdateAdminProposal gov proposal content type to set an admin for a contract.




<a name="cosmwasm.wasm.v1.UpdateInstantiateConfigProposal"></a>

### UpdateInstantiateConfigProposal
UpdateInstantiateConfigProposal gov proposal content type to update
instantiate config to a set of code ids.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `title` | [string](#string) | | Title is a short summary |
| `description` | [string](#string) | | Description is a human readable text |
| `access_config_updates` | [AccessConfigUpdate](#cosmwasm.wasm.v1.AccessConfigUpdate) | repeated | AccessConfigUpdate contains the list of code ids and the access config to be applied. |





<!-- end messages -->

<!-- end enums -->
Expand Down
22 changes: 22 additions & 0 deletions proto/cosmwasm/wasm/v1/proposal.proto
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,25 @@ message UnpinCodesProposal {
(gogoproto.moretags) = "yaml:\"code_ids\""
];
}

// AccessConfigUpdate contains the code id and the access config to be
// applied.
message AccessConfigUpdate {
// CodeID is the reference to the stored WASM code to be updated
uint64 code_id = 1 [ (gogoproto.customname) = "CodeID" ];
// InstantiatePermission to apply to the set of code ids
AccessConfig instantiate_permission = 2 [ (gogoproto.nullable) = false ];
}

// UpdateInstantiateConfigProposal gov proposal content type to update
// instantiate config to a set of code ids.
message UpdateInstantiateConfigProposal {
// Title is a short summary
string title = 1 [ (gogoproto.moretags) = "yaml:\"title\"" ];
// Description is a human readable text
string description = 2 [ (gogoproto.moretags) = "yaml:\"description\"" ];
// AccessConfigUpdate contains the list of code ids and the access config
// to be applied.
repeated AccessConfigUpdate access_config_updates = 3
[ (gogoproto.nullable) = false ];
}
1 change: 1 addition & 0 deletions x/wasm/Governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ We have added 9 new wasm specific proposal types that cover the contract's live
* `ClearAdminProposal` - clear admin for a contract to prevent further migrations
* `PinCodes` - pin the given code ids in cache. This trades memory for reduced startup time and lowers gas cost
* `UnpinCodes` - unpin the given code ids from the cache. This frees up memory and returns to standard speed and gas cost
* `UpdateInstantiateConfigProposal` - update instantiate permissions to a list of given code ids.

For details see the proposal type [implementation](https://github.com/CosmWasm/wasmd/blob/master/x/wasm/types/proposal.go)

Expand Down
108 changes: 108 additions & 0 deletions x/wasm/client/cli/gov_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package cli
import (
"fmt"
"strconv"
"strings"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/gov/client/cli"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/pkg/errors"
Expand Down Expand Up @@ -614,3 +616,109 @@ func ProposalUnpinCodesCmd() *cobra.Command {
cmd.Flags().String(flagProposalType, "", "Permission of proposal, types: store-code/instantiate/migrate/update-admin/clear-admin/text/parameter_change/software_upgrade")
return cmd
}

func parseAccessConfig(config string) (types.AccessConfig, error) {
switch config {
case "nobody":
return types.AllowNobody, nil
case "everybody":
return types.AllowEverybody, nil
default:
address, err := sdk.AccAddressFromBech32(config)
if err != nil {
return types.AccessConfig{}, fmt.Errorf("unable to parse address %s", config)
}
return types.AccessTypeOnlyAddress.With(address), nil
}
}

func parseAccessConfigUpdates(args []string) ([]types.AccessConfigUpdate, error) {
updates := make([]types.AccessConfigUpdate, len(args))
for i, c := range args {
// format: code_id,access_config
// access_config: nobody|everybody|address
parts := strings.Split(c, ",")
if len(parts) != 2 {
return nil, fmt.Errorf("invalid format")
}

codeID, err := strconv.ParseUint(parts[0], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid code ID: %s", err)
}

accessConfig, err := parseAccessConfig(parts[1])
if err != nil {
return nil, err
}
updates[i] = types.AccessConfigUpdate{
CodeID: codeID,
InstantiatePermission: accessConfig,
}
}
return updates, nil
}
func ProposalUpdateInstantiateConfigCmd() *cobra.Command {
bech32Prefix := sdk.GetConfig().GetBech32AccountAddrPrefix()
cmd := &cobra.Command{
Use: "update-instantiate-config [code-id,permission]...",
Short: "Submit an update instantiate config proposal.",
Args: cobra.MinimumNArgs(1),
Long: strings.TrimSpace(
fmt.Sprintf(`Submit an update instantiate config proposal for multiple code ids.

Example:
$ %s tx gov submit-proposal update-instantiate-config 1,nobody 2,everybody 3,%s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm
jhernandezb marked this conversation as resolved.
Show resolved Hide resolved
`, version.AppName, bech32Prefix)),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

proposalTitle, err := cmd.Flags().GetString(cli.FlagTitle)
if err != nil {
return fmt.Errorf("proposal title: %s", err)
}
proposalDescr, err := cmd.Flags().GetString(cli.FlagDescription)
if err != nil {
return fmt.Errorf("proposal description: %s", err)
}
depositArg, err := cmd.Flags().GetString(cli.FlagDeposit)
if err != nil {
return fmt.Errorf("deposit: %s", err)
}
deposit, err := sdk.ParseCoinsNormalized(depositArg)
if err != nil {
return err
}
updates, err := parseAccessConfigUpdates(args)
if err != nil {
return err
}

content := types.UpdateInstantiateConfigProposal{
Title: proposalTitle,
Description: proposalDescr,
AccessConfigUpdates: updates,
}
msg, err := govtypes.NewMsgSubmitProposal(&content, deposit, clientCtx.GetFromAddress())
if err != nil {
return err
}
if err = msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
// proposal flags
cmd.Flags().String(cli.FlagTitle, "", "Title of proposal")
cmd.Flags().String(cli.FlagDescription, "", "Description of proposal")
cmd.Flags().String(cli.FlagDeposit, "", "Deposit of proposal")
cmd.Flags().String(cli.FlagProposal, "", "Proposal file path (if this path is given, other proposal flags are ignored)")
// type values must match the "ProposalHandler" "routes" in cli
cmd.Flags().String(flagProposalType, "", "Permission of proposal, types: store-code/instantiate/migrate/update-admin/clear-admin/text/parameter_change/software_upgrade")
Copy link
Member

Choose a reason for hiding this comment

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

I'm a bit confused why this flag is here?

Usage is tx gov submit-proposal update-instantiate-config 1,nobody 2,everybody 3,%s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is unrelated to this logic, but it's used by this https://github.com/cosmos/cosmos-sdk/blob/v0.45.4/x/gov/client/cli/parse.go#L13

All other proposals have it but I don't think its actually used and could be removed.

Copy link
Member

Choose a reason for hiding this comment

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

Good point, can you make a follow up (cleanup issue), so someone can look into that later.
Not blocking merge at all, but don't want to forget it

return cmd
}
40 changes: 40 additions & 0 deletions x/wasm/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func GetQueryCmd() *cobra.Command {
GetCmdListCode(),
GetCmdListContractByCode(),
GetCmdQueryCode(),
GetCmdQueryCodeInfo(),
GetCmdGetContractInfo(),
GetCmdGetContractHistory(),
GetCmdGetContractState(),
Expand Down Expand Up @@ -181,6 +182,45 @@ func GetCmdQueryCode() *cobra.Command {
return cmd
}

// GetCmdQueryCodeInfo returns the code info for a given code id
func GetCmdQueryCodeInfo() *cobra.Command {
cmd := &cobra.Command{
jhernandezb marked this conversation as resolved.
Show resolved Hide resolved
Use: "code-info [code_id]",
Short: "Prints out metadata of a code id",
Long: "Prints out metadata of a code id",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}

codeID, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
return err
}

queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.Code(
context.Background(),
&types.QueryCodeRequest{
CodeId: codeID,
},
)
if err != nil {
return err
}
if res.CodeInfoResponse == nil {
return fmt.Errorf("contract not found")
}

return clientCtx.PrintProto(res.CodeInfoResponse)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}

// GetCmdGetContractInfo gets details about a given contract
func GetCmdGetContractInfo() *cobra.Command {
cmd := &cobra.Command{
Expand Down
1 change: 1 addition & 0 deletions x/wasm/client/proposal_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ var ProposalHandlers = []govclient.ProposalHandler{
govclient.NewProposalHandler(cli.ProposalClearContractAdminCmd, rest.ClearContractAdminProposalHandler),
govclient.NewProposalHandler(cli.ProposalPinCodesCmd, rest.PinCodeProposalHandler),
govclient.NewProposalHandler(cli.ProposalUnpinCodesCmd, rest.UnpinCodeProposalHandler),
govclient.NewProposalHandler(cli.ProposalUpdateInstantiateConfigCmd, rest.UpdateInstantiateConfigProposalHandler),
}
42 changes: 41 additions & 1 deletion x/wasm/client/rest/gov.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ func (s UnpinCodeJSONReq) GetBaseReq() rest.BaseReq {

func UnpinCodeProposalHandler(cliCtx client.Context) govrest.ProposalRESTHandler {
return govrest.ProposalRESTHandler{
SubRoute: "pin_code",
SubRoute: "unpin_code",
jhernandezb marked this conversation as resolved.
Show resolved Hide resolved
Handler: func(w http.ResponseWriter, r *http.Request) {
var req UnpinCodeJSONReq
if !rest.ReadRESTReq(w, r, cliCtx.LegacyAmino, &req) {
Expand All @@ -418,6 +418,46 @@ func UnpinCodeProposalHandler(cliCtx client.Context) govrest.ProposalRESTHandler
}
}

type UpdateInstantiateConfigProposalJSONReq struct {
BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"`

Title string `json:"title" yaml:"title"`
Description string `json:"description" yaml:"description"`
Proposer string `json:"proposer" yaml:"proposer"`
Deposit sdk.Coins `json:"deposit" yaml:"deposit"`
AccessConfigUpdates []types.AccessConfigUpdate `json:"access_config_updates" yaml:"access_config_updates"`
}

func (s UpdateInstantiateConfigProposalJSONReq) Content() govtypes.Content {
return &types.UpdateInstantiateConfigProposal{
Title: s.Title,
Description: s.Description,
AccessConfigUpdates: s.AccessConfigUpdates,
}
}
func (s UpdateInstantiateConfigProposalJSONReq) GetProposer() string {
return s.Proposer
}
func (s UpdateInstantiateConfigProposalJSONReq) GetDeposit() sdk.Coins {
return s.Deposit
}
func (s UpdateInstantiateConfigProposalJSONReq) GetBaseReq() rest.BaseReq {
return s.BaseReq
}

func UpdateInstantiateConfigProposalHandler(cliCtx client.Context) govrest.ProposalRESTHandler {
return govrest.ProposalRESTHandler{
jhernandezb marked this conversation as resolved.
Show resolved Hide resolved
SubRoute: "update_instantiate_config",
Handler: func(w http.ResponseWriter, r *http.Request) {
var req UpdateInstantiateConfigProposalJSONReq
if !rest.ReadRESTReq(w, r, cliCtx.LegacyAmino, &req) {
return
}
toStdTxResponse(cliCtx, w, req)
},
}
}

type wasmProposalData interface {
Content() govtypes.Content
GetProposer() string
Expand Down
6 changes: 6 additions & 0 deletions x/wasm/keeper/contract_keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type decoratedKeeper interface {
execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins) ([]byte, error)
Sudo(ctx sdk.Context, contractAddress sdk.AccAddress, msg []byte) ([]byte, error)
setContractInfoExtension(ctx sdk.Context, contract sdk.AccAddress, extra types.ContractInfoExtension) error
setAccessConfig(ctx sdk.Context, codeID uint64, config types.AccessConfig) error
}

type PermissionedKeeper struct {
Expand Down Expand Up @@ -78,3 +79,8 @@ func (p PermissionedKeeper) UnpinCode(ctx sdk.Context, codeID uint64) error {
func (p PermissionedKeeper) SetContractInfoExtension(ctx sdk.Context, contract sdk.AccAddress, extra types.ContractInfoExtension) error {
return p.nested.setContractInfoExtension(ctx, contract, extra)
}

// SetAccessConfig updates the access config of a code id.
func (p PermissionedKeeper) SetAccessConfig(ctx sdk.Context, codeID uint64, config types.AccessConfig) error {
return p.nested.setAccessConfig(ctx, codeID, config)
}
11 changes: 11 additions & 0 deletions x/wasm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,17 @@ func (k Keeper) setContractInfoExtension(ctx sdk.Context, contractAddr sdk.AccAd
return nil
}

// setAccessConfig updates the access config of a code id.
func (k Keeper) setAccessConfig(ctx sdk.Context, codeID uint64, config types.AccessConfig) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice! Just tagging #843 here to pass and call the authZ policy

info := k.GetCodeInfo(ctx, codeID)
if info == nil {
return sdkerrors.Wrap(types.ErrNotFound, "code info")
}
info.InstantiateConfig = config
k.storeCodeInfo(ctx, codeID, *info)
return nil
}

// handleContractResponse processes the contract response data by emitting events and sending sub-/messages.
func (k *Keeper) handleContractResponse(
ctx sdk.Context,
Expand Down
Loading