Skip to content

Commit

Permalink
feat: add new msg MsgSetTag
Browse files Browse the repository at this point in the history
  • Loading branch information
pythonberg1997 committed Nov 20, 2023
1 parent db6f3f0 commit 5a65cc8
Show file tree
Hide file tree
Showing 10 changed files with 1,402 additions and 251 deletions.
5 changes: 5 additions & 0 deletions app/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
paymentmodule "github.com/bnb-chain/greenfield/x/payment"
paymenttypes "github.com/bnb-chain/greenfield/x/payment/types"
storagemoduletypes "github.com/bnb-chain/greenfield/x/storage/types"
gashubtypes "github.com/cosmos/cosmos-sdk/x/gashub/types"
)

func (app *App) RegisterUpgradeHandlers(chainID string, serverCfg *serverconfig.Config) error {
Expand Down Expand Up @@ -112,6 +113,10 @@ func (app *App) registerEddystoneUpgradeHandler() {
func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
app.Logger().Info("upgrade to ", plan.Name)

typeUrl := sdk.MsgTypeURL(&storagemoduletypes.MsgSetTag{})
msgSetTagGasParams := gashubtypes.NewMsgGasParamsWithFixedGas(typeUrl, 1.2e3)
app.GashubKeeper.SetMsgGasParams(ctx, *msgSetTagGasParams)

return app.mm.RunMigrations(ctx, app.configurator, fromVM)
})

Expand Down
10 changes: 10 additions & 0 deletions proto/greenfield/storage/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package greenfield.storage;
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";
import "greenfield/resource/types.proto";
import "greenfield/storage/common.proto";
import "greenfield/storage/types.proto";

Expand Down Expand Up @@ -553,3 +554,12 @@ message EventCompleteMigrationBucket {
// The src_primary_sp_id defines the primary sp id of the bucket before migrate.
uint32 src_primary_sp_id = 5;
}

message EventSetTag {
// resource_type define the type of the source that the tag belongs to
greenfield.resource.ResourceType resource_type = 1;
// resource_id define the u256 id of the source that the tag belongs to
string resource_id = 2;
// tags define the tag of the source
map<string, string> tags = 3;
}
17 changes: 17 additions & 0 deletions proto/greenfield/storage/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ service Msg {
rpc CompleteMigrateBucket(MsgCompleteMigrateBucket) returns (MsgCompleteMigrateBucketResponse);
rpc CancelMigrateBucket(MsgCancelMigrateBucket) returns (MsgCancelMigrateBucketResponse);
rpc RejectMigrateBucket(MsgRejectMigrateBucket) returns (MsgRejectMigrateBucketResponse);

rpc SetTag(MsgSetTag) returns (MsgSetTagResponse);
}
message MsgCreateBucket {
option (cosmos.msg.v1.signer) = "creator";
Expand Down Expand Up @@ -628,3 +630,18 @@ message MsgRejectMigrateBucket {
}

message MsgRejectMigrateBucketResponse {}

message MsgSetTag {
option (cosmos.msg.v1.signer) = "operator";

// operator defines the granter who grant the permission to another principal
string operator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];

// resource defines a greenfield standard resource name that can be generated by GRN structure
string resource = 2;

// tags defines a list of tags which will be set to the resource
map<string, string> tags = 3;
}

message MsgSetTagResponse {}
27 changes: 27 additions & 0 deletions x/storage/client/cli/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
flag "github.com/spf13/pflag"

"strings"

gnfderrors "github.com/bnb-chain/greenfield/types/errors"
permissiontypes "github.com/bnb-chain/greenfield/x/permission/types"
storagetypes "github.com/bnb-chain/greenfield/x/storage/types"
Expand Down Expand Up @@ -148,3 +150,28 @@ func FlagSetApproval() *flag.FlagSet {
fs.Uint64(FlagApproveTimeoutHeight, math.MaxUint, "The approval timeout height of primarySp")
return fs
}

func GetTags(str string) map[string]string {
tags := make(map[string]string)
if str == "" {
return tags
}

tagsStr := str
if tagsStr[0] == '{' {
tagsStr = tagsStr[1:]
}
if tagsStr[len(tagsStr)-1] == '}' {
tagsStr = tagsStr[:len(tagsStr)-1]
}

for _, tagStr := range strings.Split(tagsStr, ",") {
kv := strings.Split(tagStr, "=")
if len(kv) != 2 {
continue
}
tags[kv[0]] = kv[1]
}

return tags
}
33 changes: 33 additions & 0 deletions x/storage/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ func GetTxCmd() *cobra.Command {
CmdPutPolicy(),
CmdDeletePolicy(),
)

cmd.AddCommand(
CmdSetTag(),
)
// this line is used by starport scaffolding # 1

return cmd
Expand Down Expand Up @@ -1115,3 +1119,32 @@ func CmdMirrorGroup() *cobra.Command {

return cmd
}

func CmdSetTag() *cobra.Command {
cmd := &cobra.Command{
Use: "set-tag [resource] [tags]",
Short: "set a bucket/object/group's tag. The tags should be like: key1=value1,key2=value2",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) (err error) {
argResource := args[0]
argTags := args[1]

clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

tags := GetTags(argTags)

msg := types.NewMsgSetTag(clientCtx.GetFromAddress(), argResource, tags)
if err := msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
17 changes: 17 additions & 0 deletions x/storage/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,23 @@ func (k msgServer) RejectMigrateBucket(goCtx context.Context, msg *storagetypes.
return &types.MsgRejectMigrateBucketResponse{}, nil
}

func (k msgServer) SetTag(goCtx context.Context, msg *types.MsgSetTag) (*types.MsgSetTagResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

operatorAddr := sdk.MustAccAddressFromHex(msg.Operator)

var grn types2.GRN
err := grn.ParseFromString(msg.Resource, true)
if err != nil {
return nil, err
}

if err := k.Keeper.SetTag(ctx, operatorAddr, grn, msg.Tags); err != nil {
return nil, err
}
return &types.MsgSetTagResponse{}, nil
}

func (k Keeper) verifyGVGSignatures(ctx sdk.Context, bucketID math.Uint, dstSP *sptypes.StorageProvider, gvgMappings []*storagetypes.GVGMapping) error {
// verify secondary sp signature
for _, newLvg2gvg := range gvgMappings {
Expand Down
70 changes: 67 additions & 3 deletions x/storage/keeper/permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ func (k Keeper) PutPolicy(ctx sdk.Context, operator sdk.AccAddress, grn types2.G

if !operator.Equals(resOwner) {
return math.ZeroUint(), types.ErrAccessDenied.Wrapf(
"Only resource owner can put bucket policy, operator (%s), owner(%s)",
"Only resource owner can put policy, operator (%s), owner(%s)",
operator.String(), resOwner.String())
}
k.normalizePrincipal(ctx, policy.Principal)
Expand All @@ -304,8 +304,7 @@ func (k Keeper) PutPolicy(ctx sdk.Context, operator sdk.AccAddress, grn types2.G
}

func (k Keeper) DeletePolicy(ctx sdk.Context, operator sdk.AccAddress, principal *permtypes.Principal,
grn types2.GRN) (math.Uint,
error) {
grn types2.GRN) (math.Uint, error) {
var resOwner sdk.AccAddress
var resID math.Uint

Expand Down Expand Up @@ -355,6 +354,71 @@ func (k Keeper) DeletePolicy(ctx sdk.Context, operator sdk.AccAddress, principal
return k.permKeeper.DeletePolicy(ctx, principal, grn.ResourceType(), resID)
}

func (k Keeper) SetTag(ctx sdk.Context, operator sdk.AccAddress, grn types2.GRN, tags map[string]string) error {
var resOwner sdk.AccAddress
var resType gnfdresource.ResourceType
var resID math.Uint
switch grn.ResourceType() {
case gnfdresource.RESOURCE_TYPE_BUCKET:
resType = gnfdresource.RESOURCE_TYPE_BUCKET
bucketName, grnErr := grn.GetBucketName()
if grnErr != nil {
return grnErr
}
bucketInfo, found := k.GetBucketInfo(ctx, bucketName)
if !found {
return types.ErrNoSuchBucket.Wrapf("bucketName: %s", bucketName)
}
resOwner = sdk.MustAccAddressFromHex(bucketInfo.Owner)
resID = bucketInfo.Id
case gnfdresource.RESOURCE_TYPE_OBJECT:
resType = gnfdresource.RESOURCE_TYPE_OBJECT
bucketName, objectName, grnErr := grn.GetBucketAndObjectName()
if grnErr != nil {
return grnErr
}
objectInfo, found := k.GetObjectInfo(ctx, bucketName, objectName)
if !found {
return types.ErrNoSuchObject.Wrapf("BucketName: %s, objectName: %s", bucketName, objectName)
}

resOwner = sdk.MustAccAddressFromHex(objectInfo.Owner)
resID = objectInfo.Id
case gnfdresource.RESOURCE_TYPE_GROUP:
resType = gnfdresource.RESOURCE_TYPE_GROUP
groupOwner, groupName, grnErr := grn.GetGroupOwnerAndAccount()
if grnErr != nil {
return grnErr
}
groupInfo, found := k.GetGroupInfo(ctx, groupOwner, groupName)
if !found {
return types.ErrNoSuchBucket.Wrapf("groupOwner: %s, groupName: %s", groupOwner.String(), groupName)
}

resOwner = sdk.MustAccAddressFromHex(groupInfo.Owner)
resID = groupInfo.Id
default:
return gnfderrors.ErrInvalidGRN.Wrap("Unknown resource type in greenfield resource name")
}

if !operator.Equals(resOwner) {
return types.ErrAccessDenied.Wrapf(
"Only resource owner can set tag, operator (%s), owner(%s)",
operator.String(), resOwner.String())
}

// emit Event
if err := ctx.EventManager().EmitTypedEvents(&types.EventSetTag{
ResourceType: resType,
ResourceId: resID.String(),
Tags: tags,
}); err != nil {
return err
}

return nil
}

func (k Keeper) normalizePrincipal(ctx sdk.Context, principal *permtypes.Principal) {
if principal.Type == permtypes.PRINCIPAL_TYPE_GNFD_GROUP {
if _, err := math.ParseUint(principal.Value); err == nil {
Expand Down
Loading

0 comments on commit 5a65cc8

Please sign in to comment.