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 UpdateParams to attribute module #1987

Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* Replace deprecated wasm features [#1988](https://github.com/provenance-io/provenance/pull/1988).
* Add `UpdateParams` and `Params` query rpc endpoints to modules.
* `ibcratelimit` add `UpdateParams` endpoint and deprecate `GovUpdateParams` [#1984](https://github.com/provenance-io/provenance/pull/1984).
* `attribute` add `UpdateParams` endpoint and cli [#1987](https://github.com/provenance-io/provenance/pull/1987).

### Client Breaking

Expand Down
2 changes: 1 addition & 1 deletion client/docs/statik/statik.go

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions client/docs/swagger-ui/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100875,6 +100875,11 @@ definitions:
provenance.attribute.v1.MsgUpdateAttributeResponse:
type: object
description: MsgUpdateAttributeResponse defines the Msg/UpdateAttribute response type.
provenance.attribute.v1.MsgUpdateParamsResponse:
type: object
description: >-
MsgUpdateParamsResponse is a response message for the UpdateParams
endpoint.
provenance.exchange.v1.AccessGrant:
type: object
properties:
Expand Down
5 changes: 5 additions & 0 deletions proto/provenance/attribute/v1/attribute.proto
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,8 @@ message EventAttributeExpired {
message EventAccountDataUpdated {
string account = 1;
}

// EventAttributeParamsUpdated event emitted when attribute params are updated.
message EventAttributeParamsUpdated {
string max_value_length = 1;
}
18 changes: 17 additions & 1 deletion proto/provenance/attribute/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ option java_package = "io.provenance.attribute.v1";
option java_multiple_files = true;

import "cosmos/msg/v1/msg.proto";
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";
import "provenance/attribute/v1/attribute.proto";
Expand All @@ -31,7 +32,8 @@ service Msg {
// SetAccountData defines a method for setting/updating an account's accountdata attribute.
rpc SetAccountData(MsgSetAccountDataRequest) returns (MsgSetAccountDataResponse);

// TODO add update params
// UpdateParams is a governance proposal endpoint for updating the attribute module's params.
rpc UpdateParams(MsgUpdateParamsRequest) returns (MsgUpdateParamsResponse);
}

// MsgAddAttributeRequest defines an sdk.Msg type that is used to add a new attribute to an account.
Expand Down Expand Up @@ -144,3 +146,17 @@ message MsgSetAccountDataRequest {

// MsgSetAccountDataResponse defines the Msg/SetAccountData response type.
message MsgSetAccountDataResponse {}

// MsgUpdateParamsRequest is a request message for the UpdateParams endpoint.
message MsgUpdateParamsRequest {
option (cosmos.msg.v1.signer) = "authority";

// authority should be the governance module account address.
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];

// params are the new param values to set.
Params params = 2 [(gogoproto.nullable) = false];
}

// MsgUpdateParamsResponse is a response message for the UpdateParams endpoint.
message MsgUpdateParamsResponse {}
36 changes: 36 additions & 0 deletions x/attribute/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cli
import (
"encoding/base64"
"fmt"
"strconv"
"strings"
"time"

Expand All @@ -12,7 +13,9 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/version"
govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli"

"github.com/provenance-io/provenance/internal/provcli"
"github.com/provenance-io/provenance/x/attribute/types"
)

Expand All @@ -33,6 +36,7 @@ func NewTxCmd() *cobra.Command {
NewDeleteAccountAttributeCmd(),
NewSetAccountDataCmd(),
NewUpdateAccountAttributeExpirationCmd(),
NewUpdateParamsCmd(),
)
return txCmd
}
Expand Down Expand Up @@ -314,3 +318,35 @@ $ %[1]s tx attribute account-data --%s

return cmd
}

// NewUpdateParamsCmd creates a command to update the attribute module's params via governance proposal.
func NewUpdateParamsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "update-params <max-value-length>",
Short: "Update the attribute module's params via governance proposal",
Long: "Submit an update params via governance proposal along with an initial deposit.",
Args: cobra.ExactArgs(1),
Example: fmt.Sprintf(`%[1]s tx attribute update-params 100 --deposit 50000nhash`, version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

flagSet := cmd.Flags()
authority := provcli.GetAuthority(flagSet)
maxValueLength, err := strconv.ParseUint(args[0], 10, 32)
if err != nil {
return fmt.Errorf("invalid max value length: %w", err)
}
msg := types.NewMsgUpdateParamsRequest(authority, uint32(maxValueLength))
return provcli.GenerateOrBroadcastTxCLIAsGovProp(clientCtx, flagSet, msg)
},
}

govcli.AddGovPropFlagsToCmd(cmd)
provcli.AddAuthorityFlagToCmd(cmd)
flags.AddTxFlagsToCmd(cmd)

return cmd
}
22 changes: 22 additions & 0 deletions x/attribute/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"

"github.com/provenance-io/provenance/x/attribute/types"
)
Expand All @@ -35,6 +36,8 @@ type Keeper struct {
cdc codec.BinaryCodec

modAddr sdk.AccAddress

authority string
}

// NewKeeper returns an attribute keeper. It handles:
Expand All @@ -53,11 +56,30 @@ func NewKeeper(
nameKeeper: nameKeeper,
cdc: cdc,
modAddr: authtypes.NewModuleAddress(types.ModuleName),
authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(),
}
nameKeeper.SetAttributeKeeper(keeper)
return keeper
}

// GetAuthority is signer of the proposal
func (k Keeper) GetAuthority() string {
return k.authority
}

// IsAuthority returns true if the provided address bech32 string is the authority address.
func (k Keeper) IsAuthority(addr string) bool {
return strings.EqualFold(k.authority, addr)
}

// ValidateAuthority returns an error if the provided address is not the authority.
func (k Keeper) ValidateAuthority(addr string) error {
if !k.IsAuthority(addr) {
return govtypes.ErrInvalidSigner.Wrapf("expected %q got %q", k.GetAuthority(), addr)
}
return nil
}

// Logger returns a module-specific logger.
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
Expand Down
16 changes: 16 additions & 0 deletions x/attribute/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,19 @@ func (k msgServer) SetAccountData(goCtx context.Context, msg *types.MsgSetAccoun

return &types.MsgSetAccountDataResponse{}, nil
}

// UpdateParams is a governance proposal endpoint for updating the attribute module's params.
func (k msgServer) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParamsRequest) (*types.MsgUpdateParamsResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

if err := k.ValidateAuthority(msg.Authority); err != nil {
return nil, err
}

k.SetParams(ctx, msg.Params)
if err := ctx.EventManager().EmitTypedEvent(types.NewEventAttributeParamsUpdated(msg.Params)); err != nil {
return nil, err
}

return &types.MsgUpdateParamsResponse{}, nil
}
45 changes: 45 additions & 0 deletions x/attribute/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,48 @@ func (s *MsgServerTestSuite) TestMsgDeleteAttributeRequest() {
})
}
}

func (s *MsgServerTestSuite) TestUpdateParams() {
newParams := types.Params{
MaxValueLength: 200,
}

tests := []struct {
name string
msg types.MsgUpdateParamsRequest
errorMsg string
}{
{
name: "Should fail due to invalid authority",
msg: types.MsgUpdateParamsRequest{
Authority: "invalid-authority",
Params: newParams,
},
errorMsg: `expected "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" got "invalid-authority": expected gov account as only signer for proposal message`,
},
{
name: "Should succeed",
msg: types.MsgUpdateParamsRequest{
Authority: authtypes.NewModuleAddress("gov").String(),
Params: newParams,
},
},
}

for _, tt := range tests {
s.Run(tt.name, func() {
s.ctx = s.ctx.WithEventManager(sdk.NewEventManager())
response, err := s.msgServer.UpdateParams(s.ctx, &tt.msg)
if len(tt.errorMsg) > 0 {
s.Assert().Error(err)
s.Assert().Equal(tt.errorMsg, err.Error())
s.Assert().Nil(response)
} else {
s.Assert().NoError(err)
s.Assert().NotNil(response)
result := s.containsMessage(s.ctx.EventManager().ABCIEvents(), types.NewEventAttributeParamsUpdated(newParams))
s.True(result, fmt.Sprintf("Expected typed event was not found: %v", types.NewEventAttributeParamsUpdated(newParams)))
}
})
}
}
Loading
Loading